X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fnetconf%2Fnetconf-util%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fnetconf%2Futil%2Fxml%2FXmlElement.java;h=4529f81e575e9245013319ab75fd43a9974c5a16;hp=66603fb6c2d60b90cf2e17c277e65420d3c0b8b1;hb=e9ada4abe7f68175775e0ca9a12a6ab3c47fd329;hpb=3e20a64a21d5b7bced26b03108aedcd025dd8be6 diff --git a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java index 66603fb6c2..4529f81e57 100644 --- a/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java +++ b/opendaylight/netconf/netconf-util/src/main/java/org/opendaylight/controller/netconf/util/xml/XmlElement.java @@ -10,9 +10,16 @@ package org.opendaylight.controller.netconf.util.xml; import com.google.common.base.Optional; import com.google.common.base.Predicate; +import com.google.common.base.Strings; import com.google.common.collect.Collections2; import com.google.common.collect.Lists; import com.google.common.collect.Maps; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; import org.opendaylight.controller.netconf.util.exception.UnexpectedElementException; @@ -28,18 +35,12 @@ import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xml.sax.SAXException; -import javax.annotation.Nullable; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - public final class XmlElement { + public static final String DEFAULT_NAMESPACE_PREFIX = ""; + private final Element element; - private static final Logger logger = LoggerFactory.getLogger(XmlElement.class); + private static final Logger LOG = LoggerFactory.getLogger(XmlElement.class); private XmlElement(Element element) { this.element = element; @@ -73,16 +74,16 @@ public final class XmlElement { return xmlElement; } - private static Map extractNamespaces(Element typeElement) throws NetconfDocumentedException { + private Map extractNamespaces() throws NetconfDocumentedException { Map namespaces = new HashMap<>(); - NamedNodeMap attributes = typeElement.getAttributes(); + NamedNodeMap attributes = element.getAttributes(); for (int i = 0; i < attributes.getLength(); i++) { Node attribute = attributes.item(i); String attribKey = attribute.getNodeName(); if (attribKey.startsWith(XmlUtil.XMLNS_ATTRIBUTE_KEY)) { String prefix; if (attribKey.equals(XmlUtil.XMLNS_ATTRIBUTE_KEY)) { - prefix = ""; + prefix = DEFAULT_NAMESPACE_PREFIX; } else { if (!attribKey.startsWith(XmlUtil.XMLNS_ATTRIBUTE_KEY + ":")){ throw new NetconfDocumentedException("Attribute doesn't start with :", @@ -95,6 +96,15 @@ public final class XmlElement { namespaces.put(prefix, attribute.getNodeValue()); } } + + // namespace does not have to be defined on this element but inherited + if(!namespaces.containsKey(DEFAULT_NAMESPACE_PREFIX)) { + Optional namespaceOptionally = getNamespaceOptionally(); + if(namespaceOptionally.isPresent()) { + namespaces.put(DEFAULT_NAMESPACE_PREFIX, namespaceOptionally.get()); + } + } + return namespaces; } @@ -111,7 +121,7 @@ public final class XmlElement { public void checkNamespaceAttribute(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException { if (!getNamespaceAttribute().equals(expectedNamespace)) { - throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s", + throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s should be %s", getNamespaceAttribute(), expectedNamespace), NetconfDocumentedException.ErrorType.application, @@ -122,8 +132,8 @@ public final class XmlElement { public void checkNamespace(String expectedNamespace) throws UnexpectedNamespaceException, MissingNameSpaceException { if (!getNamespace().equals(expectedNamespace)) - { - throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s for element %s, should be %s", + { + throw new UnexpectedNamespaceException(String.format("Unexpected namespace %s should be %s", getNamespace(), expectedNamespace), NetconfDocumentedException.ErrorType.application, @@ -133,7 +143,7 @@ public final class XmlElement { } public String getName() { - if (element.getLocalName()!=null && !element.getLocalName().equals("")){ + if (element.getLocalName()!=null && !element.getLocalName().equals(DEFAULT_NAMESPACE_PREFIX)){ return element.getLocalName(); } return element.getTagName(); @@ -204,7 +214,7 @@ public final class XmlElement { return Lists.newArrayList(Collections2.filter(getChildElementsWithinNamespace(namespace), new Predicate() { @Override - public boolean apply(@Nullable XmlElement xmlElement) { + public boolean apply(XmlElement xmlElement) { return xmlElement.getName().equals(childName); } })); @@ -224,11 +234,17 @@ public final class XmlElement { }); } + /** + * + * @param tagName tag name without prefix + * @return List of child elements + */ public List getChildElements(final String tagName) { return getChildElementsInternal(new ElementFilteringStrategy() { @Override public boolean accept(Element e) { - return e.getTagName().equals(tagName); + // localName returns pure localName without prefix + return e.getLocalName().equals(tagName); } }); } @@ -245,31 +261,47 @@ public final class XmlElement { } public Optional getOnlyChildElementOptionally(String childName) { - try { - return Optional.of(getOnlyChildElement(childName)); - } catch (Exception e) { + List nameElements = getChildElements(childName); + if (nameElements.size() != 1) { return Optional.absent(); } + return Optional.of(nameElements.get(0)); } - public Optional getOnlyChildElementOptionally(String childName, String namespace) { - try { - return Optional.of(getOnlyChildElement(childName, namespace)); - } catch (Exception e) { + public Optional getOnlyChildElementOptionally(final String childName, final String namespace) { + List children = getChildElementsWithinNamespace(namespace); + children = Lists.newArrayList(Collections2.filter(children, new Predicate() { + @Override + public boolean apply(XmlElement xmlElement) { + return xmlElement.getName().equals(childName); + } + })); + if (children.size() != 1){ return Optional.absent(); } + return Optional.of(children.get(0)); } public XmlElement getOnlyChildElementWithSameNamespace(String childName) throws NetconfDocumentedException { return getOnlyChildElement(childName, getNamespace()); } - public Optional getOnlyChildElementWithSameNamespaceOptionally(String childName) { - try { - return Optional.of(getOnlyChildElement(childName, getNamespace())); - } catch (Exception e) { - return Optional.absent(); + public Optional getOnlyChildElementWithSameNamespaceOptionally(final String childName) { + Optional namespace = getNamespaceOptionally(); + if (namespace.isPresent()) { + List children = getChildElementsWithinNamespace(namespace.get()); + children = Lists.newArrayList(Collections2.filter(children, new Predicate() { + @Override + public boolean apply(XmlElement xmlElement) { + return xmlElement.getName().equals(childName); + } + })); + if (children.size() != 1){ + return Optional.absent(); + } + return Optional.of(children.get(0)); } + return Optional.absent(); } public XmlElement getOnlyChildElementWithSameNamespace() throws NetconfDocumentedException { @@ -279,20 +311,21 @@ public final class XmlElement { } public Optional getOnlyChildElementWithSameNamespaceOptionally() { - try { - XmlElement childElement = getOnlyChildElement(); - childElement.checkNamespace(getNamespace()); - return Optional.of(childElement); - } catch (Exception e) { - return Optional.absent(); + Optional child = getOnlyChildElementOptionally(); + if (child.isPresent() + && child.get().getNamespaceOptionally().isPresent() + && getNamespaceOptionally().isPresent() + && getNamespaceOptionally().get().equals(child.get().getNamespaceOptionally().get())) { + return child; } + return Optional.absent(); } public XmlElement getOnlyChildElement(final String childName, String namespace) throws NetconfDocumentedException { List children = getChildElementsWithinNamespace(namespace); children = Lists.newArrayList(Collections2.filter(children, new Predicate() { @Override - public boolean apply(@Nullable XmlElement xmlElement) { + public boolean apply(XmlElement xmlElement) { return xmlElement.getName().equals(childName); } })); @@ -319,29 +352,47 @@ public final class XmlElement { return children.get(0); } + public Optional getOnlyChildElementOptionally() { + List children = getChildElements(); + if (children.size() != 1) { + return Optional.absent(); + } + return Optional.of(children.get(0)); + } + public String getTextContent() throws NetconfDocumentedException { - Node textChild = element.getFirstChild(); - if (null == textChild){ - throw new NetconfDocumentedException(String.format( "Child node expected, got null for " + getName() + " : " + element), - NetconfDocumentedException.ErrorType.application, - NetconfDocumentedException.ErrorTag.invalid_value, - NetconfDocumentedException.ErrorSeverity.error); + NodeList childNodes = element.getChildNodes(); + if (childNodes.getLength() == 0) { + return DEFAULT_NAMESPACE_PREFIX; } - if (!(textChild instanceof Text)){ - throw new NetconfDocumentedException(String.format(getName() + " should contain text." + - Text.class.getName() + " expected, got " + textChild), - NetconfDocumentedException.ErrorType.application, - NetconfDocumentedException.ErrorTag.invalid_value, - NetconfDocumentedException.ErrorSeverity.error); + for(int i = 0; i < childNodes.getLength(); i++) { + Node textChild = childNodes.item(i); + if (textChild instanceof Text) { + String content = textChild.getTextContent(); + return content.trim(); + } + } + throw new NetconfDocumentedException(getName() + " should contain text.", + NetconfDocumentedException.ErrorType.application, + NetconfDocumentedException.ErrorTag.invalid_value, + NetconfDocumentedException.ErrorSeverity.error + ); + } + + public Optional getOnlyTextContentOptionally() { + // only return text content if this node has exactly one Text child node + if (element.getChildNodes().getLength() == 1) { + Node item = element.getChildNodes().item(0); + if (item instanceof Text) { + return Optional.of(((Text) item).getWholeText()); + } } - String content = textChild.getTextContent(); - // Trim needed - return content.trim(); + return Optional.absent(); } public String getNamespaceAttribute() throws MissingNameSpaceException { String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY); - if (attribute == null || attribute.equals("")){ + if (attribute == null || attribute.equals(DEFAULT_NAMESPACE_PREFIX)){ throw new MissingNameSpaceException(String.format("Element %s must specify namespace", toString()), NetconfDocumentedException.ErrorType.application, @@ -351,15 +402,32 @@ public final class XmlElement { return attribute; } - public String getNamespace() throws MissingNameSpaceException { + public Optional getNamespaceAttributeOptionally(){ + String attribute = element.getAttribute(XmlUtil.XMLNS_ATTRIBUTE_KEY); + if (attribute == null || attribute.equals(DEFAULT_NAMESPACE_PREFIX)){ + return Optional.absent(); + } + return Optional.of(attribute); + } + + public Optional getNamespaceOptionally() { String namespaceURI = element.getNamespaceURI(); - if (namespaceURI == null || namespaceURI.equals("")){ + if (Strings.isNullOrEmpty(namespaceURI)) { + return Optional.absent(); + } else { + return Optional.of(namespaceURI); + } + } + + public String getNamespace() throws MissingNameSpaceException { + Optional namespaceURI = getNamespaceOptionally(); + if (!namespaceURI.isPresent()){ throw new MissingNameSpaceException(String.format("No namespace defined for %s", this), NetconfDocumentedException.ErrorType.application, NetconfDocumentedException.ErrorTag.operation_failed, NetconfDocumentedException.ErrorSeverity.error); } - return namespaceURI; + return namespaceURI.get(); } @Override @@ -370,7 +438,7 @@ public final class XmlElement { try { sb.append(", namespace='").append(getNamespace()).append('\''); } catch (MissingNameSpaceException e) { - logger.trace("Missing namespace for element."); + LOG.trace("Missing namespace for element."); } } sb.append('}'); @@ -391,14 +459,14 @@ public final class XmlElement { * is found value will be null. */ public Map.Entry findNamespaceOfTextContent() throws NetconfDocumentedException { - Map namespaces = extractNamespaces(element); + Map namespaces = extractNamespaces(); String textContent = getTextContent(); int indexOfColon = textContent.indexOf(':'); String prefix; if (indexOfColon > -1) { prefix = textContent.substring(0, indexOfColon); } else { - prefix = ""; + prefix = DEFAULT_NAMESPACE_PREFIX; } if (!namespaces.containsKey(prefix)) { throw new IllegalArgumentException("Cannot find namespace for " + XmlUtil.toString(element) + ". Prefix from content is " @@ -411,7 +479,7 @@ public final class XmlElement { List children = getChildElementsWithinNamespace(getNamespace()); return Lists.newArrayList(Collections2.filter(children, new Predicate() { @Override - public boolean apply(@Nullable XmlElement xmlElement) { + public boolean apply(XmlElement xmlElement) { return xmlElement.getName().equals(childName); } })); @@ -447,11 +515,8 @@ public final class XmlElement { XmlElement that = (XmlElement) o; - if (!element.isEqualNode(that.element)) { - return false; - } + return element.isEqualNode(that.element); - return true; } @Override @@ -460,15 +525,10 @@ public final class XmlElement { } public boolean hasNamespace() { - try { - getNamespaceAttribute(); - } catch (MissingNameSpaceException e) { - try { - getNamespace(); - } catch (MissingNameSpaceException e1) { + if (!getNamespaceAttributeOptionally().isPresent()) { + if (!getNamespaceOptionally().isPresent()) { return false; } - return true; } return true; }