* 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.codec.xml;
import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
-import java.io.FileNotFoundException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.AbstractMap;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
+import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
-import org.custommonkey.xmlunit.Diff;
-import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.common.Revision;
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.common.XMLNamespace;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
-import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
-import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack;
import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
-import org.w3c.dom.Document;
public class XmlStreamUtilsTest {
+ @FunctionalInterface
+ interface XMLStreamWriterConsumer {
+ void accept(XMLStreamWriter writer) throws XMLStreamException;
+ }
- public static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newFactory();
-
- private static SchemaContext schemaContext;
+ private static EffectiveModelContext schemaContext;
private static Module leafRefModule;
@BeforeClass
- public static void initialize() throws URISyntaxException, FileNotFoundException, ReactorException {
+ public static void initialize() {
schemaContext = YangParserTestUtils.parseYangResource("/leafref-test.yang");
assertNotNull(schemaContext);
assertEquals(1, schemaContext.getModules().size());
assertNotNull(leafRefModule);
}
- @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<QName, String> attributeEntry = new AbstractMap.SimpleEntry<>(name, "value");
-
- name = getAttrQName("namespace2", "2012-12-12", "attr", Optional.empty());
- final Map.Entry<QName, String> attributeEntryNoPrefix = new AbstractMap.SimpleEntry<>(name, "value");
-
- final RandomPrefix randomPrefix = new RandomPrefix(null);
- XMLStreamWriterUtils.writeAttribute(writer, attributeEntry, randomPrefix);
- XMLStreamWriterUtils.writeAttribute(writer, attributeEntryNoPrefix, randomPrefix);
-
- writer.writeEndElement();
- writer.close();
- out.close();
+ @AfterClass
+ public static void cleanup() {
+ leafRefModule = null;
+ schemaContext = null;
+ }
- final String xmlAsString = new String(out.toByteArray());
+ @Test
+ public void testWriteIdentityRef() throws Exception {
+ final QNameModule parent = QNameModule.create(XMLNamespace.of("parent:uri"), Revision.of("2000-01-01"));
- final Map<String, String> mappedPrefixes = mapPrefixed(randomPrefix.getPrefixes());
- assertEquals(2, mappedPrefixes.size());
- final String randomPrefixValue = mappedPrefixes.get("namespace2");
+ String xmlAsString = createXml(writer -> {
+ writer.writeStartElement("element");
+ final StreamWriterFacade facade = new StreamWriterFacade(writer);
+ facade.writeCharacters(XMLStreamWriterUtils.encode(facade, QName.create(parent, "identity"), parent));
+ facade.flush();
+ writer.writeEndElement();
+ });
- final String expectedXmlAsString = "<element xmlns:a=\"namespace\" a:attr=\"value\" xmlns:" + randomPrefixValue
- + "=\"namespace2\" " + randomPrefixValue + ":attr=\"value\"></element>";
+ assertThat(xmlAsString, containsString("element>identity"));
- XMLUnit.setIgnoreAttributeOrder(true);
- final Document control = XMLUnit.buildControlDocument(expectedXmlAsString);
- final Document test = XMLUnit.buildTestDocument(xmlAsString);
- final Diff diff = XMLUnit.compareXML(control, test);
+ xmlAsString = createXml(writer -> {
+ writer.writeStartElement("elementDifferent");
+ final StreamWriterFacade facade = new StreamWriterFacade(writer);
+ facade.writeCharacters(XMLStreamWriterUtils.encode(facade, QName.create("different:namespace", "identity"),
+ parent));
+ facade.flush();
+ writer.writeEndElement();
+ });
- final boolean identical = diff.identical();
- assertTrue("Xml differs: " + diff.toString(), identical);
+ final Pattern prefixedIdentityPattern = Pattern.compile(".*\"different:namespace\">(.*):identity.*");
+ final Matcher matcher = prefixedIdentityPattern.matcher(xmlAsString);
+ assertTrue("Xml: " + xmlAsString + " should match: " + prefixedIdentityPattern, matcher.matches());
}
- @Test
- public void testWriteIdentityRef() throws Exception {
+ private static String createXml(final XMLStreamWriterConsumer consumer) throws XMLStreamException, IOException {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
- final XMLStreamWriter writer = XML_OUTPUT_FACTORY.createXMLStreamWriter(out);
-
- writer.writeStartElement("element");
- final QNameModule parent = QNameModule.create(URI.create("parent:uri"), Revision.of("2000-01-01"));
- XMLStreamWriterUtils.write(writer, null, QName.create(parent, "identity"), parent);
- writer.writeEndElement();
+ final XMLStreamWriter writer = TestFactories.DEFAULT_OUTPUT_FACTORY.createXMLStreamWriter(out);
- writer.writeStartElement("elementDifferent");
- XMLStreamWriterUtils.write(writer, null, QName.create("different:namespace", "identity"), parent);
- writer.writeEndElement();
+ consumer.accept(writer);
writer.close();
out.close();
- final String xmlAsString = new String(out.toByteArray()).replaceAll("\\s*", "");
- assertThat(xmlAsString, containsString("element>identity"));
-
- final Pattern prefixedIdentityPattern = Pattern.compile(".*\"different:namespace\">(.*):identity.*");
- final Matcher matcher = prefixedIdentityPattern.matcher(xmlAsString);
- assertTrue("Xml: " + xmlAsString + " should match: " + prefixedIdentityPattern, matcher.matches());
+ return new String(out.toByteArray()).replaceAll("\\s*", "");
}
/**
*/
@Test
public void testLeafRefRelativeChaining() {
- getTargetNodeForLeafRef("leafname3", StringTypeDefinition.class);
+ getTargetNodeForLeafRef(StringTypeDefinition.class, "cont3", "leafname3");
}
@Test
public void testLeafRefRelative() {
- getTargetNodeForLeafRef("pointToStringLeaf", StringTypeDefinition.class);
+ getTargetNodeForLeafRef(StringTypeDefinition.class, "pointToStringLeaf");
}
@Test
public void testLeafRefAbsoluteWithSameTarget() {
- getTargetNodeForLeafRef("absname", InstanceIdentifierTypeDefinition.class);
+ getTargetNodeForLeafRef(InstanceIdentifierTypeDefinition.class, "absname");
}
/**
@Ignore
@Test
public void testLeafRefWithDoublePointInPath() {
- getTargetNodeForLeafRef("lf-with-double-point-inside", StringTypeDefinition.class);
+ getTargetNodeForLeafRef(StringTypeDefinition.class, "lf-with-double-point-inside");
}
@Test
public void testLeafRefRelativeAndAbsoluteWithSameTarget() {
- final TypeDefinition<?> targetNodeForAbsname = getTargetNodeForLeafRef("absname",
- InstanceIdentifierTypeDefinition.class);
- final TypeDefinition<?> targetNodeForRelname = getTargetNodeForLeafRef("relname",
- InstanceIdentifierTypeDefinition.class);
- assertEquals(targetNodeForAbsname, targetNodeForRelname);
+ assertSame(getTargetNodeForLeafRef(InstanceIdentifierTypeDefinition.class, "absname"),
+ getTargetNodeForLeafRef(InstanceIdentifierTypeDefinition.class, "relname"));
}
- private TypeDefinition<?> getTargetNodeForLeafRef(final String nodeName, final Class<?> clas) {
- final LeafSchemaNode schemaNode = findSchemaNodeWithLeafrefType(leafRefModule, nodeName);
- assertNotNull(schemaNode);
- final LeafrefTypeDefinition leafrefTypedef = findLeafrefType(schemaNode);
- assertNotNull(leafrefTypedef);
- final TypeDefinition<?> targetBaseType = SchemaContextUtil.getBaseTypeForLeafRef(leafrefTypedef, schemaContext,
- schemaNode);
- assertTrue("Wrong class found.", clas.isInstance(targetBaseType));
- return targetBaseType;
- }
-
- private static Map<String, String> mapPrefixed(final Iterable<Map.Entry<URI, String>> prefixes) {
- final Map<String, String> mappedPrefixes = new HashMap<>();
- for (final Map.Entry<URI, String> prefix : prefixes) {
- mappedPrefixes.put(prefix.getKey().toString(), prefix.getValue());
- }
- return mappedPrefixes;
- }
-
- private static QName getAttrQName(final String namespace, final String revision, final String localName,
- final Optional<String> 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, localName);
+ private static TypeDefinition<?> getTargetNodeForLeafRef(final Class<?> clas, final String... names) {
+ final SchemaInferenceStack stack = SchemaInferenceStack.of(schemaContext);
+ stack.enterDataTree(QName.create(leafRefModule.getQNameModule(), "cont2"));
+ for (String name : names) {
+ stack.enterDataTree(QName.create(leafRefModule.getQNameModule(), name));
}
- return QName.create(namespace, revision, localName);
- }
- private LeafSchemaNode findSchemaNodeWithLeafrefType(final DataNodeContainer module, final String nodeName) {
- for (final DataSchemaNode childNode : module.getChildNodes()) {
- if (childNode instanceof DataNodeContainer) {
- LeafSchemaNode leafrefFromRecursion = findSchemaNodeWithLeafrefType((DataNodeContainer) childNode,
- nodeName);
- if (leafrefFromRecursion != null) {
- return leafrefFromRecursion;
- }
- } else if (childNode.getQName().getLocalName().equals(nodeName) && childNode instanceof LeafSchemaNode) {
- final TypeDefinition<?> leafSchemaNodeType = ((LeafSchemaNode) childNode).getType();
- if (leafSchemaNodeType instanceof LeafrefTypeDefinition) {
- return (LeafSchemaNode) childNode;
- }
- }
- }
- return null;
- }
+ final EffectiveStatement<?, ?> leaf = stack.currentStatement();
+ assertThat(leaf, instanceOf(LeafSchemaNode.class));
+ final TypeDefinition<? extends TypeDefinition<?>> type = ((TypedDataSchemaNode) leaf).getType();
+ assertThat(type, instanceOf(LeafrefTypeDefinition.class));
- private static LeafrefTypeDefinition findLeafrefType(final LeafSchemaNode schemaNode) {
- final TypeDefinition<?> type = schemaNode.getType();
- if (type instanceof LeafrefTypeDefinition) {
- return (LeafrefTypeDefinition) type;
- }
- return null;
+ final TypeDefinition<?> resolved = stack.resolveLeafref((LeafrefTypeDefinition) type);
+ assertThat(resolved, instanceOf(clas));
+ return resolved;
}
}