1 package org.opendaylight.controller.sal.rest.impl;
3 import static com.google.common.base.Preconditions.checkArgument;
5 import java.io.InputStream;
7 import java.util.Stack;
9 import javax.xml.stream.XMLEventReader;
10 import javax.xml.stream.XMLInputFactory;
11 import javax.xml.stream.XMLStreamException;
12 import javax.xml.stream.events.Characters;
13 import javax.xml.stream.events.StartElement;
14 import javax.xml.stream.events.XMLEvent;
16 import org.opendaylight.controller.sal.restconf.impl.CompositeNodeWrapper;
17 import org.opendaylight.controller.sal.restconf.impl.EmptyNodeWrapper;
18 import org.opendaylight.controller.sal.restconf.impl.NodeWrapper;
19 import org.opendaylight.controller.sal.restconf.impl.SimpleNodeWrapper;
20 import org.opendaylight.yangtools.yang.data.api.Node;
22 public class XmlReader {
24 private final static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
25 private XMLEventReader eventReader;
27 public CompositeNodeWrapper read(InputStream entityStream) throws XMLStreamException, UnsupportedFormatException {
28 eventReader = xmlInputFactory.createXMLEventReader(entityStream);
30 if (eventReader.hasNext()) {
31 XMLEvent element = eventReader.peek();
32 if (element.isStartDocument()) {
33 eventReader.nextEvent();
37 if (eventReader.hasNext() && !isCompositeNodeEvent(eventReader.peek())) {
38 throw new UnsupportedFormatException("Root element of XML has to be composite element.");
41 final Stack<NodeWrapper<?>> processingQueue = new Stack<>();
42 CompositeNodeWrapper root = null;
43 NodeWrapper<?> element = null;
44 while (eventReader.hasNext()) {
45 final XMLEvent event = eventReader.nextEvent();
47 if (event.isStartElement()) {
48 final StartElement startElement = event.asStartElement();
49 CompositeNodeWrapper compParentNode = null;
50 if (!processingQueue.isEmpty() && processingQueue.peek() instanceof CompositeNodeWrapper) {
51 compParentNode = (CompositeNodeWrapper) processingQueue.peek();
53 NodeWrapper<?> newNode = null;
54 if (isCompositeNodeEvent(event)) {
56 root = resolveCompositeNodeFromStartElement(startElement);
59 newNode = resolveCompositeNodeFromStartElement(startElement);
61 } else if (isSimpleNodeEvent(event)) {
63 throw new UnsupportedFormatException("Root element of XML has to be composite element.");
65 newNode = resolveSimpleNodeFromStartElement(startElement);
68 if (newNode != null) {
69 processingQueue.push(newNode);
70 if (compParentNode != null) {
71 compParentNode.addValue(newNode);
74 } else if (event.isEndElement()) {
75 element = processingQueue.pop();
79 if (!root.getLocalName().equals(element.getLocalName())) {
80 throw new UnsupportedFormatException("XML should contain only one root element");
86 private boolean isSimpleNodeEvent(final XMLEvent event) throws XMLStreamException {
87 checkArgument(event != null, "XML Event cannot be NULL!");
88 if (event.isStartElement()) {
89 if (eventReader.hasNext()) {
90 final XMLEvent innerEvent;
91 innerEvent = eventReader.peek();
92 if (innerEvent.isCharacters()) {
93 final Characters chars = innerEvent.asCharacters();
94 if (!chars.isWhiteSpace()) {
97 } else if (innerEvent.isEndElement()) {
105 private boolean isCompositeNodeEvent(final XMLEvent event) throws XMLStreamException {
106 checkArgument(event != null, "XML Event cannot be NULL!");
107 if (event.isStartElement()) {
108 if (eventReader.hasNext()) {
110 innerEvent = eventReader.peek();
111 if (innerEvent.isCharacters()) {
112 Characters chars = innerEvent.asCharacters();
113 if (chars.isWhiteSpace()) {
114 eventReader.nextEvent();
115 innerEvent = eventReader.peek();
118 if (innerEvent.isStartElement()) {
126 private NodeWrapper<? extends Node<?>> resolveSimpleNodeFromStartElement(final StartElement startElement)
127 throws XMLStreamException {
128 checkArgument(startElement != null, "Start Element cannot be NULL!");
131 if (eventReader.hasNext()) {
132 final XMLEvent innerEvent = eventReader.peek();
133 if (innerEvent.isCharacters()) {
134 final Characters chars = innerEvent.asCharacters();
135 if (!chars.isWhiteSpace()) {
136 data = innerEvent.asCharacters().getData();
138 } else if (innerEvent.isEndElement()) {
139 if (startElement.getLocation().getCharacterOffset() == innerEvent.getLocation().getCharacterOffset()) {
147 return new EmptyNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
149 return new SimpleNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement), data);
152 private CompositeNodeWrapper resolveCompositeNodeFromStartElement(final StartElement startElement) {
153 checkArgument(startElement != null, "Start Element cannot be NULL!");
154 return new CompositeNodeWrapper(getNamespaceFrom(startElement), getLocalNameFrom(startElement));
157 private String getLocalNameFrom(StartElement startElement) {
158 return startElement.getName().getLocalPart();
161 private URI getNamespaceFrom(StartElement startElement) {
162 String namespaceURI = startElement.getName().getNamespaceURI();
163 return namespaceURI.isEmpty() ? null : URI.create(namespaceURI);