All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.twilio.sdk.parser.XmlResponseParser Maven / Gradle / Ivy

There is a newer version: 7.0.0-rc-10
Show newest version
package com.twilio.sdk.parser;

import com.twilio.sdk.TwilioRestResponse;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// TODO: Auto-generated Javadoc
/**
 * The Class XmlResponseParser.
 */
public class XmlResponseParser implements ResponseParser {
	public Map parse(TwilioRestResponse response) {
		Map xmlMap = this.parseXml(response.getResponseText());

		flattenMap(xmlMap, null, null);
		
		return xmlMap;
	}

	/**
	 * Flatten map.
	 *
	 * @param map the map
	 * @param parentMap the parent map
	 * @param parentKey the parent key
	 */
	@SuppressWarnings("unchecked")
	private void flattenMap(Map map,
			Map parentMap, String parentKey) {

		for (String key : map.keySet()) {
			Object data = map.get(key);
			if (data instanceof Map) {
				flattenMap((Map) data, map, key);
			} else if (data instanceof List) {
				parentMap.put(parentKey, data);
			}
		}

	}

	/**
	 * Parses the xml.
	 *
	 * @param xmlString the xml string
	 * @return the map
	 */
	protected Map parseXml(String xmlString) {

		Map ret = new HashMap();

		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder;

		try {
			// Configure the DocumentBuilderFactory to prevent XXE Processing
			// {@link OWASP Documentation}
			factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
			factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
			factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
			factory.setXIncludeAware(false);
			factory.setExpandEntityReferences(false);

			builder = factory.newDocumentBuilder();
			Document d = builder.parse(new InputSource(new StringReader(
					xmlString)));

			Node resp = d.getFirstChild(); // TwilioResponse
			NodeList nodes = resp.getChildNodes();

			for (int i = 0; i < nodes.getLength(); i++) {
				Node node = nodes.item(i);
				buildNode(node, ret);
			}

			if (resp.hasChildNodes() && resp.getFirstChild().hasAttributes()) {
				// Setup paging
				NamedNodeMap attrs = resp.getFirstChild().getAttributes();

				for (PagingProperty p : PagingProperty.values()) {
					String property = this.getPagingPropertyKey(p);
					Node n = attrs.getNamedItem(property);
					ret.put(property, n.getNodeValue());
				}
			}
		} catch (ParserConfigurationException e) {
			// TODO log this
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return ret;
	}

	/**
	 * Builds the node.
	 *
	 * @param currentNode the current node
	 * @param containerMap the container map
	 */
	@SuppressWarnings("unchecked")
	private void buildNode(Node currentNode, Map containerMap) {
		if (currentNode.hasChildNodes()
				&& currentNode.getChildNodes().getLength() == 1
				&& currentNode.getFirstChild().getNodeType() == Node.TEXT_NODE) {
			Node textNode = currentNode.getFirstChild();

			// this should be a list...
			if (containerMap.containsKey(currentNode.getNodeName())) {
				Object oldObject = containerMap.get(currentNode.getNodeName());
				if (oldObject instanceof List) {
					List array = (List) oldObject;
					array.add(textNode.getNodeValue());
				} else {
					List newList = new ArrayList();
					newList.add(oldObject);
					newList.add(textNode.getNodeValue());
					containerMap.put(currentNode.getNodeName(), newList);
				}
			} else {
				containerMap.put(currentNode.getNodeName(),
						textNode.getNodeValue());
			}
		} else if (currentNode.hasChildNodes()) {
			NodeList nodes = currentNode.getChildNodes();
			Map newElement = new HashMap();

			if (containerMap.containsKey(currentNode.getNodeName())) {
				Object oldObject = containerMap.get(currentNode.getNodeName());
				if (oldObject instanceof List) {
					List array = (List) oldObject;
					array.add(newElement);
				} else {
					List newList = new ArrayList();
					newList.add(oldObject);
					newList.add(newElement);
					containerMap.put(currentNode.getNodeName(), newList);
				}
			} else {
				containerMap.put(currentNode.getNodeName(), newElement);
			}

			for (int i = 0; i < nodes.getLength(); i++) {
				Node node = nodes.item(i);
				buildNode(node, newElement);
			}
		}

	}

	/* (non-Javadoc)
	 * @see com.twilio.sdk.parser.ResponseParser#getPagingPropertyKey(com.twilio.sdk.parser.ResponseParser.PagingProperty)
	 */
	public String getPagingPropertyKey(PagingProperty prop) {
		switch (prop) {
		case NEXT_PAGE_URI_KEY:
			return "nextpageuri";
		case START_KEY:
			return "start";
		case END_KEY:
			return "end";
		case PAGE_KEY:
			return "page";
		case NUM_PAGES_KEY:
			return "numpages";
		case TOTAL_KEY:
			return "total";
		}

		return null;
	}
}