Package er.rest.format

Source Code of er.rest.format.ERXXmlRestParser

package er.rest.format;

import java.io.StringReader;

import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.CDATASection;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.InputSource;

import com.webobjects.appserver.WORequest;

import er.rest.ERXRestContext;
import er.rest.ERXRestNameRegistry;
import er.rest.ERXRestRequestNode;
import er.rest.ERXRestUtils;

/**
* ERXXmlRestRequestParser is an implementation of the IERXRestRequestParser interface that supports XML document
* requests.
*
* @author mschrag
*/
public class ERXXmlRestParser implements IERXRestParser {
  protected ERXRestRequestNode createRequestNodeForElement(Element element, boolean rootNode, ERXRestFormat.Delegate delegate, ERXRestContext context) {
    String name = element.getTagName();
    ERXRestRequestNode requestNode = new ERXRestRequestNode(name, rootNode);

    String valueStr = element.getNodeValue();

    NamedNodeMap attributeNodes = element.getAttributes();
    for (int attributeNum = 0; attributeNum < attributeNodes.getLength(); attributeNum++) {
      Node attribute = attributeNodes.item(attributeNum);
      requestNode.setAttributeForKey(attribute.getNodeValue(), attribute.getNodeName());
    }
    NodeList childNodes = element.getChildNodes();
    for (int childNodeNum = 0; childNodeNum < childNodes.getLength(); childNodeNum++) {
      Node childNode = childNodes.item(childNodeNum);
      if (childNode instanceof Element) {
        Element childElement = (Element) childNode;
        ERXRestRequestNode childRequestNode = createRequestNodeForElement(childElement, false, delegate, context);
        if (childRequestNode != null) {
          String childRequestNodeName = childRequestNode.name();
          // MS: this is a huge hack, but it turns out that it's surprinsingly tricky to
          // identify an array in XML ... I'm cheating here and just saying that if the
          // node name is uppercase, it represents a new object and not an attribute ...
          // this will totally break on rails-style lowercase class names, but for now
          // this flag is just a heuristic
          if (childRequestNodeName == null || Character.isUpperCase(childRequestNodeName.charAt(0))) {
            childRequestNode.setRootNode(true);
            requestNode.setArray(true);
          }
          requestNode.addChild(childRequestNode);
        }
      }
      else if (childNode instanceof Text) {
        String text = childNode.getNodeValue();
        if (text != null) {
          if (!(childNode instanceof CDATASection)) {
            text = text.trim();
          }
          if (valueStr == null) {
            valueStr = text;
          }
          else {
            valueStr += text;
          }
        }
       
        // if there is a text node AND other sibling nodes, this is fake ...
        if (childNodes.getLength() > 1) {
          valueStr = null;
        }
      }
      else {
        // ???
      }
    }

    requestNode.setValue(valueStr);

    delegate.nodeDidParse(requestNode);

    if (valueStr != null) {
      String type = requestNode.type();
      if (type != null) {
        // MS: inverse the types we declare in ERXXmlRestWriter
        if ("datetime".equals(type)) {
          type = "NSTimestamp";
        }
        else if ("integer".equals(type)) {
          type = "int";
        }
        else if ("bigint".equals(type)) {
          type = "BigDecimal";
        }
        else if ("enum".equals(type)) {
          type = "Enum";
        }
        Object coercedValue = ERXRestUtils.coerceValueToTypeNamed(valueStr, type, context, false);
        if (coercedValue != null) {
          requestNode.setValue(coercedValue);
        }
      }
    }
   
    return requestNode;
  }

  @Deprecated
  public ERXRestRequestNode parseRestRequest(WORequest request, ERXRestFormat.Delegate delegate, ERXRestContext context) {
    return parseRestRequest(request.contentString(), delegate, context);
  }

  @Deprecated
  public ERXRestRequestNode parseRestRequest(String contentStr, ERXRestFormat.Delegate delegate, ERXRestContext context) {
    return parseRestRequest(new ERXStringRestRequest(contentStr), delegate, context);
  }
 
  public ERXRestRequestNode parseRestRequest(IERXRestRequest request, ERXRestFormat.Delegate delegate, ERXRestContext context) {
    ERXRestRequestNode rootRequestNode = null;
    String contentString = request.stringContent();
    if (contentString != null && contentString.length() > 0) {
      // MS: Support direct updating of primitive type keys -- so if you don't want to
      // wrap your request in XML, this will allow it
      if (!contentString.trim().startsWith("<")) {
        contentString = "<FakeWrapper>" + contentString.trim() + "</FakeWrapper>";
      }

      Document document;
      try {
        document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(contentString)));
        document.normalize();
        Element rootElement = document.getDocumentElement();
        rootRequestNode = createRequestNodeForElement(rootElement, true, delegate, context);
      }
      catch (Exception e) {
        throw new IllegalArgumentException("Failed to parse request document.", e);
      }
    }
    else {
      rootRequestNode = new ERXRestRequestNode(null, true);
      rootRequestNode.setNull(true);
    }

    return rootRequestNode;
  }
 

  public static void main(String[] args) {
    String str = "<Company><id>100</id><type>Company</type><name>mDT</name><firstName nil=\"true\"/><employees><Employee id=\"101\" type=\"Employee\"/><Employee id=\"102\"><name>Mike</name></Employee></employees></Company>";
    //String str = "<Employees><Employee id=\"101\" type=\"Employee\"/><Employee id=\"102\"><name>Mike</name></Employee></Employees>";
    ERXRestNameRegistry.registry().setExternalNameForInternalName("Super", "Company");
    ERXRestNameRegistry.registry().setExternalNameForInternalName("Super2", "Employee");
    ERXRestContext context = new ERXRestContext();
    ERXRestRequestNode n = new ERXXmlRestParser().parseRestRequest(new ERXStringRestRequest(str), new ERXRestFormatDelegate(), context);
    ERXStringBufferRestResponse response = new ERXStringBufferRestResponse();
    new ERXXmlRestWriter().appendToResponse(n, response, new ERXRestFormatDelegate(), context);
    System.out.println("ERXXmlRestParser.main: " + response);
  }

}
TOP

Related Classes of er.rest.format.ERXXmlRestParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.