From a84ec52d7bcb57af77a2424755e513cd10bc9c57 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Thu, 24 Jul 2014 17:06:09 +0200 Subject: [PATCH] Fix XmlStreamUtils writing attributes. The prefix for attributes was no set. This would result in an exception when no prefix was available by default. Using RandomPrefix now. Change-Id: I6110293b262a77f987534fe98abf51755a066be0 Signed-off-by: Maros Marsalek --- .../data/impl/codec/xml/RandomPrefix.java | 7 +- .../data/impl/codec/xml/XmlStreamUtils.java | 14 ++- .../impl/codec/xml/XmlStreamUtilsTest.java | 86 +++++++++++++++++++ 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtilsTest.java diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java index 223157a223..0251678389 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/RandomPrefix.java @@ -23,6 +23,10 @@ final class RandomPrefix { } String encodeQName(final QName qname) { + return encodePrefix(qname) + ':' + qname.getLocalName(); + } + + String encodePrefix(final QName qname) { String prefix = prefixes.get(qname.getNamespace()); if (prefix == null) { prefix = qname.getPrefix(); @@ -40,7 +44,6 @@ final class RandomPrefix { prefixes.put(qname.getNamespace(), prefix); } - - return prefix + ':' + qname.getLocalName(); + return prefix; } } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtils.java index 1d319a5ace..9471a1be29 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtils.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtils.java @@ -1,9 +1,11 @@ package org.opendaylight.yangtools.yang.data.impl.codec.xml; import com.google.common.annotations.Beta; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Preconditions; import java.net.URI; +import java.util.Map; import java.util.Map.Entry; import javax.annotation.Nonnull; @@ -149,8 +151,9 @@ public class XmlStreamUtils { writer.writeStartElement(pfx, qname.getLocalName(), ns); if (data instanceof AttributesContainer && ((AttributesContainer) data).getAttributes() != null) { + RandomPrefix randomPrefix = new RandomPrefix(); for (Entry attribute : ((AttributesContainer) data).getAttributes().entrySet()) { - writer.writeAttribute(attribute.getKey().getNamespace().toString(), attribute.getKey().getLocalName(), attribute.getValue()); + writeAttribute(writer, attribute, randomPrefix); } } @@ -186,6 +189,15 @@ public class XmlStreamUtils { writer.writeEndElement(); } + @VisibleForTesting + static void writeAttribute(final XMLStreamWriter writer, final Entry attribute, final RandomPrefix randomPrefix) + throws XMLStreamException { + final QName key = attribute.getKey(); + final String prefix = randomPrefix.encodePrefix(key); + writer.writeAttribute("xmlns:" + prefix, key.getNamespace().toString()); + writer.writeAttribute(prefix, key.getNamespace().toString(), key.getLocalName(), attribute.getValue()); + } + /** * Write a value into a XML stream writer. This method assumes the start and end of element is * emitted by the caller. diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtilsTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtilsTest.java new file mode 100644 index 0000000000..1a35875ead --- /dev/null +++ b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtilsTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v1.0 which accompanies this distribution, + * and is available at http://www.eclipse.org/legal/epl-v10.html + */ + +package org.opendaylight.yangtools.yang.data.impl.codec.xml; + +import com.google.common.base.Optional; +import com.google.common.collect.Maps; +import java.io.ByteArrayOutputStream; +import java.net.URI; +import java.util.AbstractMap; +import java.util.Map; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamWriter; +import junit.framework.Assert; +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; +import org.junit.Test; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.w3c.dom.Document; + +public class XmlStreamUtilsTest { + + public static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newFactory(); + + @Test + public void testWriteAttribute() throws Exception { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + final XMLStreamWriter writer = XML_OUTPUT_FACTORY.createXMLStreamWriter(out); + writer.writeStartElement("element"); + + QName name = getAttrQName("namespace", "2012-12-12", "attr", Optional.of("prefix")); + final Map.Entry attributeEntry = new AbstractMap.SimpleEntry<>(name, "value"); + + name = getAttrQName("namespace2", "2012-12-12", "attr", Optional.absent()); + final Map.Entry attributeEntryNoPrefix = new AbstractMap.SimpleEntry<>(name, "value"); + + final RandomPrefix randomPrefix = new RandomPrefix(); + XmlStreamUtils.writeAttribute(writer, attributeEntry, randomPrefix); + XmlStreamUtils.writeAttribute(writer, attributeEntryNoPrefix, randomPrefix); + + writer.writeEndElement(); + writer.close(); + out.close(); + + final String xmlAsString = new String(out.toByteArray()); + + final Map mappedPrefixes = mapPrefixed(randomPrefix.getPrefixes()); + Assert.assertEquals(2, mappedPrefixes.size()); + final String randomPrefixValue = mappedPrefixes.get("namespace2"); + + final String expectedXmlAsString = ""; + + XMLUnit.setIgnoreAttributeOrder(true); + final Document control = XMLUnit.buildControlDocument(expectedXmlAsString); + final Document test = XMLUnit.buildTestDocument(xmlAsString); + final Diff diff = XMLUnit.compareXML(control, test); + + final boolean identical = diff.identical(); + Assert.assertTrue("Xml differs: " + diff.toString(), identical); + } + + private Map mapPrefixed(final Iterable> prefixes) { + final Map mappedPrefixes = Maps.newHashMap(); + for (final Map.Entry prefix : prefixes) { + mappedPrefixes.put(prefix.getKey().toString(), prefix.getValue()); + } + return mappedPrefixes; + } + + private QName getAttrQName(final String namespace, final String revision, final String localName, final Optional prefix) { + + if(prefix.isPresent()) { + final QName moduleQName = QName.create(namespace, revision, "module"); + final QNameModule module = QNameModule.create(moduleQName.getNamespace(), moduleQName.getRevision()); + return QName.create(module, prefix.get(), localName); + } else { + return QName.create(namespace, revision, localName); + } + } +} -- 2.36.6