From 4a5d26c9de475a4cff151ee4255e027211c2eeb4 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Wed, 19 Mar 2014 11:31:56 +0100 Subject: [PATCH 1/1] Abstract infrastructure for normalized nodes translation. With implementation for dom <-> normalized nodes. Change-Id: Ic2c08d2955177bc335d6493d64076a77d2cc7d62 Signed-off-by: Maros Marsalek Signed-off-by: Jozef Gloncak Signed-off-by: Ladislav Borak Signed-off-by: Robert Varga --- pom.xml | 2 +- .../yang/data/api/InstanceIdentifier.java | 27 ++ .../impl/codec/TypeDefinitionAwareCodec.java | 16 +- .../data/impl/codec/xml/XmlDocumentUtils.java | 12 +- ...bleAugmentationNodeSchemaAwareBuilder.java | 1 - .../impl/ImmutableChoiceNodeBuilder.java | 1 - ...ImmutableChoiceNodeSchemaAwareBuilder.java | 28 +- .../impl/ImmutableLeafNodeBuilder.java | 8 - .../ImmutableLeafSetEntryNodeBuilder.java | 8 - .../impl/ImmutableLeafSetNodeBuilder.java | 11 +- .../impl/ImmutableMapEntryNodeBuilder.java | 14 +- ...mutableMapEntryNodeSchemaAwareBuilder.java | 1 + .../builder/impl/ImmutableMapNodeBuilder.java | 11 +- .../valid/DataNodeContainerValidator.java | 29 +- .../AbstractImmutableDataContainerNode.java | 12 +- .../AbstractImmutableNormalizedNode.java | 25 +- .../FromNormalizedNodeSerializer.java | 37 +++ .../transform/ToNormalizedNodeParser.java | 39 +++ .../base/AugmentationSchemaProxy.java | 100 ++++++ .../schema/transform/base/SchemaUtils.java | 291 ++++++++++++++++++ .../parser/AugmentationNodeBaseParser.java | 57 ++++ .../base/parser/BaseDispatcherParser.java | 159 ++++++++++ .../base/parser/ChoiceNodeBaseParser.java | 84 +++++ .../base/parser/ContainerNodeBaseParser.java | 65 ++++ .../base/parser/LeafNodeBaseParser.java | 43 +++ .../parser/LeafSetEntryNodeBaseParser.java | 43 +++ .../base/parser/LeafSetNodeBaseParser.java | 49 +++ .../base/parser/MapEntryNodeBaseParser.java | 63 ++++ .../base/parser/MapNodeBaseParser.java | 44 +++ .../base/parser/NodeParserDispatcher.java | 78 +++++ .../AugmentationNodeBaseSerializer.java | 43 +++ .../serializer/BaseDispatcherSerializer.java | 93 ++++++ .../serializer/ChoiceNodeBaseSerializer.java | 57 ++++ .../ContainerNodeBaseSerializer.java | 45 +++ .../serializer/LeafNodeBaseSerializer.java | 38 +++ .../LeafSetEntryNodeBaseSerializer.java | 38 +++ .../serializer/LeafSetNodeBaseSerializer.java | 47 +++ .../MapEntryNodeBaseSerializer.java | 46 +++ .../serializer/MapNodeBaseSerializer.java | 47 +++ .../serializer/NodeSerializerDispatcher.java | 142 +++++++++ .../impl/schema/transform/dom/DomUtils.java | 84 +++++ .../dom/parser/AugmentationNodeDomParser.java | 38 +++ .../dom/parser/ChoiceNodeDomParser.java | 38 +++ .../dom/parser/ContainerNodeDomParser.java | 38 +++ .../dom/parser/DomNodeDispatcher.java | 67 ++++ .../dom/parser/LeafNodeDomParser.java | 29 ++ .../dom/parser/LeafSetEntryNodeDomParser.java | 29 ++ .../dom/parser/LeafSetNodeDomParser.java | 28 ++ .../dom/parser/MapEntryNodeDomParser.java | 39 +++ .../dom/parser/MapNodeDomParser.java | 28 ++ .../AugmentationNodeDomSerializer.java | 29 ++ .../serializer/ChoiceNodeDomSerializer.java | 27 ++ .../ContainerNodeDomSerializer.java | 48 +++ .../DomNodeSerializerDispatcher.java | 99 ++++++ .../dom/serializer/LeafNodeDomSerializer.java | 37 +++ .../LeafSetEntryNodeDomSerializer.java | 39 +++ .../serializer/LeafSetNodeDomSerializer.java | 29 ++ .../serializer/MapEntryNodeDomSerializer.java | 48 +++ .../dom/serializer/MapNodeDomSerializer.java | 28 ++ .../schema/NormalizedDataBuilderTest.java | 231 ++++++-------- .../NormalizedNodeXmlTranslationTest.java | 252 +++++++++++++++ .../data/impl/schema/augment_choice_hell.yang | 109 +++++++ .../impl/schema/augment_choice_hell_ok.xml | 15 + .../impl/schema/augment_choice_hell_ok2.xml | 12 + .../yang/data/impl/schema/simple.xml | 12 +- .../yang/data/impl/schema/simple2.xml | 43 +++ .../yangtools/yang/data/impl/schema/test.yang | 75 ++++- 67 files changed, 3264 insertions(+), 241 deletions(-) create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/AugmentationSchemaProxy.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/SchemaUtils.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/AugmentationNodeBaseParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/BaseDispatcherParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ChoiceNodeBaseParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ContainerNodeBaseParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafNodeBaseParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetEntryNodeBaseParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetNodeBaseParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapEntryNodeBaseParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapNodeBaseParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/NodeParserDispatcher.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/AugmentationNodeBaseSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/BaseDispatcherSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ChoiceNodeBaseSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ContainerNodeBaseSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafNodeBaseSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetEntryNodeBaseSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetNodeBaseSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapEntryNodeBaseSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapNodeBaseSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/NodeSerializerDispatcher.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/DomUtils.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/AugmentationNodeDomParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ChoiceNodeDomParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ContainerNodeDomParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomNodeDispatcher.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafNodeDomParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetEntryNodeDomParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetNodeDomParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapEntryNodeDomParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapNodeDomParser.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/AugmentationNodeDomSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ChoiceNodeDomSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ContainerNodeDomSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomNodeSerializerDispatcher.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafNodeDomSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetEntryNodeDomSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetNodeDomSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapEntryNodeDomSerializer.java create mode 100644 yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapNodeDomSerializer.java create mode 100644 yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java create mode 100644 yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang create mode 100644 yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok.xml create mode 100644 yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok2.xml create mode 100644 yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple2.xml diff --git a/pom.xml b/pom.xml index 37399eff88..68cc427b04 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 2.4.0 - 2.4 + 2.3.2 2.9.1 2.4.2 2.2.1 diff --git a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java index f3a6c3800f..174ae31000 100644 --- a/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java +++ b/yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java @@ -354,6 +354,33 @@ public class InstanceIdentifier implements Path, Immutable, return childNames; } + @Override + public String toString() { + final StringBuffer sb = new StringBuffer("AugmentationIdentifier{"); + sb.append("childNames=").append(childNames); + sb.append('}'); + return sb.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AugmentationIdentifier)) return false; + + AugmentationIdentifier that = (AugmentationIdentifier) o; + + if (childNames != null ? !childNames.equals(that.childNames) : that.childNames != null) return false; + if (nodeType != null ? !nodeType.equals(that.nodeType) : that.nodeType != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = nodeType != null ? nodeType.hashCode() : 0; + result = 31 * result + (childNames != null ? childNames.hashCode() : 0); + return result; + } } private static class BuilderImpl implements InstanceIdentifierBuilder { diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java index a1fa857775..8cb399584d 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java @@ -58,23 +58,23 @@ import com.google.common.collect.ImmutableSet; import com.google.common.io.BaseEncoding; public abstract class TypeDefinitionAwareCodec> implements DataStringCodec { - + private static final Pattern intPattern = Pattern.compile("[+-]?[1-9][0-9]*$"); private static final Pattern hexPattern = Pattern.compile("[+-]?0[xX][0-9a-fA-F]+"); private static final Pattern octalPattern = Pattern.compile("[+-]?0[1-7][0-7]*$"); - + private final Optional typeDefinition; private final Class inputClass; - + private static final int provideBase(final String integer) { if (integer == null) { throw new IllegalArgumentException("String representing integer number cannot be NULL!"); } - + if ((integer.length() == 1) && (integer.charAt(0) == '0')) { return 10; } - + final Matcher intMatcher = intPattern.matcher(integer); if (intMatcher.matches()) { return 10; @@ -87,7 +87,7 @@ public abstract class TypeDefinitionAwareCodec> i if (octMatcher.matches()) { return 8; } else { - throw new NumberFormatException("Incorrect lexical representation of Integer value!" + throw new NumberFormatException("Incorrect lexical representation of Integer value: " + integer + "The Integer value can be defined as Integer Number, Hexadecimal Number or" + "Octal Number. The sign vlues are allowed. " + "Spaces between digits are NOT allowed!"); @@ -95,7 +95,7 @@ public abstract class TypeDefinitionAwareCodec> i } } } - + private static String normalizeHexadecimal(final String hexInt) { if (hexInt == null) { throw new IllegalArgumentException( @@ -111,7 +111,7 @@ public abstract class TypeDefinitionAwareCodec> i } return normalizedString; } - + public static final BinaryCodecStringImpl BINARY_DEFAULT_CODEC = new BinaryCodecStringImpl( Optional. absent()); diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java index 9f034543d7..7345d3dded 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java @@ -23,13 +23,16 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import com.google.common.collect.Maps; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.data.api.*; +import org.opendaylight.yangtools.yang.data.api.AttributesContainer; +import org.opendaylight.yangtools.yang.data.api.CompositeNode; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; +import org.opendaylight.yangtools.yang.data.api.ModifyAction; import org.opendaylight.yangtools.yang.data.api.Node; +import org.opendaylight.yangtools.yang.data.api.SimpleNode; import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode; import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl; import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; @@ -49,7 +52,10 @@ import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.w3c.dom.*; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; import com.google.common.base.Function; import com.google.common.base.Objects; diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeSchemaAwareBuilder.java index 1f07eb5553..33638de640 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeSchemaAwareBuilder.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeSchemaAwareBuilder.java @@ -18,7 +18,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataN import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; -import com.google.common.base.Preconditions; import com.google.common.collect.Sets; public class ImmutableAugmentationNodeSchemaAwareBuilder extends ImmutableAugmentationNodeBuilder { diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeBuilder.java index a5c2d03180..f1ad8d0559 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeBuilder.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeBuilder.java @@ -36,6 +36,5 @@ public class ImmutableChoiceNodeBuilder extends AbstractImmutableDataContainerNo final Map> children) { super(ImmutableMap.copyOf(children), nodeIdentifier); } - } } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeSchemaAwareBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeSchemaAwareBuilder.java index ab73930b40..312361bb41 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeSchemaAwareBuilder.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeSchemaAwareBuilder.java @@ -7,15 +7,14 @@ */ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl; +import com.google.common.base.Supplier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils; import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; - -import com.google.common.base.Preconditions; public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBuilder { @@ -35,9 +34,15 @@ public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBu } @Override - public DataContainerNodeBuilder withChild(DataContainerChild child) { + public DataContainerNodeBuilder withChild(final DataContainerChild child) { if(detectedCase == null) { - detectedCase = detectCase(child); + detectedCase = SchemaUtils.detectCase(schema, child).or(new Supplier() { + @Override + public ChoiceCaseNode get() { + throw new IllegalArgumentException(String.format("Unknown child node: %s, for choice: %s", child.getNodeType(), + schema.getQName())); + } + }); validator = new DataNodeContainerValidator(detectedCase); } @@ -52,19 +57,6 @@ public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBu return super.build(); } - private ChoiceCaseNode detectCase(DataContainerChild child) { - for (ChoiceCaseNode choiceCaseNode : schema.getCases()) { - for (DataSchemaNode childFromCase : choiceCaseNode.getChildNodes()) { - if (childFromCase.getQName().equals(child.getNodeType())) { - return choiceCaseNode; - } - } - } - - throw new IllegalArgumentException(String.format("Unknown child node: %s, for choice: %s", child.getNodeType(), - schema.getQName())); - } - public static DataContainerNodeBuilder create(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) { return new ImmutableChoiceNodeSchemaAwareBuilder(schema); } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeBuilder.java index f466ed3929..60335eb30d 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeBuilder.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeBuilder.java @@ -32,13 +32,5 @@ public class ImmutableLeafNodeBuilder extends AbstractImmutableNormalizedNode super(nodeIdentifier, value); } - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("ImmutableLeafNode{"); - sb.append("nodeIdentifier=").append(nodeIdentifier); - sb.append(", value=").append(value); - sb.append('}'); - return sb.toString(); - } } } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java index 77d23d80a3..2c4e4e89b9 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java @@ -33,13 +33,5 @@ public class ImmutableLeafSetEntryNodeBuilder extends AbstractImmutableNormal "Node identifier contains different value: %s than value itself: %s", nodeIdentifier, value); } - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("ImmutableLeafSetEntryNode{"); - sb.append("nodeIdentifier=").append(nodeIdentifier); - sb.append(", value=").append(value); - sb.append('}'); - return sb.toString(); - } } } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java index f3dd9d0c9b..4cb2d8ee22 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java @@ -21,6 +21,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNo import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; public class ImmutableLeafSetNodeBuilder implements ListNodeBuilder> { @@ -73,7 +74,7 @@ public class ImmutableLeafSetNodeBuilder implements ListNodeBuilder> children) { - super(nodeIdentifier, children.values()); + super(nodeIdentifier, ImmutableList.copyOf(children.values())); this.mappedChildren = children; } @@ -82,14 +83,6 @@ public class ImmutableLeafSetNodeBuilder implements ListNodeBuilder augmentChild = isAugmentChild(child); diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java index f914484831..2cac25dbb8 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java @@ -15,6 +15,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableList; public abstract class AbstractImmutableDataContainerNode // extends AbstractImmutableNormalizedNode>> // @@ -22,9 +23,10 @@ public abstract class AbstractImmutableDataContainerNode protected final Map> children; + public AbstractImmutableDataContainerNode( final Map> children, final K nodeIdentifier) { - super(nodeIdentifier, children.values()); + super(nodeIdentifier, ImmutableList.copyOf(children.values())); this.children = children; } @@ -33,12 +35,4 @@ public abstract class AbstractImmutableDataContainerNode return Optional.> fromNullable(children.get(child)); } - @Override - public String toString() { - final StringBuffer sb = new StringBuffer("ImmutableContainerNode{"); - sb.append("nodeIdentifier=").append(nodeIdentifier); - sb.append(", children=").append(children); - sb.append('}'); - return sb.toString(); - } } diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedNode.java index ceb20124c8..96ff9e5f22 100644 --- a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedNode.java +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedNode.java @@ -13,13 +13,14 @@ import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; +import com.google.common.base.Objects; import com.google.common.base.Preconditions; public abstract class AbstractImmutableNormalizedNode implements NormalizedNode, Immutable { protected final K nodeIdentifier; - protected V value; + protected final V value; protected AbstractImmutableNormalizedNode(K nodeIdentifier, V value) { this.nodeIdentifier = Preconditions.checkNotNull(nodeIdentifier, "nodeIdentifier"); @@ -27,41 +28,49 @@ public abstract class AbstractImmutableNormalizedNode that = (AbstractImmutableNormalizedNode) o; if (!nodeIdentifier.equals(that.nodeIdentifier)) return false; if (!value.equals(that.value)) return false; diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializer.java new file mode 100644 index 0000000000..58d666e327 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializer.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 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.schema.transform; + +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * + * Generic serializer for normalized nodes. NormalizedNodes can be serialized + * e.g. to Dom APIs. + * + * @param + * type of resulting/serialized element from NormalizedNode + * @param + * type of NormalizedNode to be serialized + * @param + * schema belonging to the type N of NormalizedNode + */ +public interface FromNormalizedNodeSerializer, S> { + + /** + * + * Serialize one node of type N as a list of E elements. If the serialization + * process creates only one E element as a result e.g. container node, the + * result element is expected to be wrapped in a list. + * + * @param schema + * @param node + * @return Serialized N node as a list of E elements + */ + Iterable serialize(S schema, N node); +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParser.java new file mode 100644 index 0000000000..25cd3308b9 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParser.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 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.schema.transform; + +import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode; + +/** + * + * Generic parser for normalized nodes. NormalizedNodes can be parsed + * e.g. from Dom APIs. + * + * @param + * type of element to be parsed into NormalizedNode + * @param + * type of NormalizedNode to be the result of parsing + * @param + * schema belonging to the type N of NormalizedNode + */ +public interface ToNormalizedNodeParser, S> { + + /** + * + * Parse a list of E elements as a NormalizedNode of type N. If the parsing + * process expects only one E element as input e.g. container node, the + * input element will be wrapped in a list. + * + * @param xmlDom + * @param schema + * @return NormalizedNode as a result of parsing list of E elements with schema S + */ + N parse(Iterable xmlDom, S schema); + + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/AugmentationSchemaProxy.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/AugmentationSchemaProxy.java new file mode 100644 index 0000000000..726c40c02c --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/AugmentationSchemaProxy.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2013 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.schema.transform.base; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.google.common.collect.Maps; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.model.api.*; + +/** + * Proxy for AugmentationSchema. Child node schemas are replaced with actual schemas from parent. + */ +public final class AugmentationSchemaProxy implements AugmentationSchema { + private final AugmentationSchema delegate; + private final Set realChildSchemas; + private final Map mappedChildSchemas; + + public AugmentationSchemaProxy(AugmentationSchema augmentSchema, Set realChildSchemas) { + this.delegate = augmentSchema; + this.realChildSchemas = realChildSchemas; + + this.mappedChildSchemas = Maps.newHashMap(); + for (DataSchemaNode realChildSchema : realChildSchemas) { + mappedChildSchemas.put(realChildSchema.getQName(), realChildSchema); + } + } + + @Override + public RevisionAwareXPath getWhenCondition() { + return delegate.getWhenCondition(); + } + + @Override + public String getDescription() { + return delegate.getDescription(); + } + + @Override + public String getReference() { + return delegate.getReference(); + } + + @Override + public Status getStatus() { + return delegate.getStatus(); + } + + @Override + public SchemaPath getTargetPath() { + return delegate.getTargetPath(); + } + + @Override + public List getUnknownSchemaNodes() { + return delegate.getUnknownSchemaNodes(); + } + + @Override + public Set> getTypeDefinitions() { + return delegate.getTypeDefinitions(); + } + + @Override + public Set getChildNodes() { + return realChildSchemas; + } + + @Override + public Set getGroupings() { + return delegate.getGroupings(); + } + + @Override + public DataSchemaNode getDataChildByName(QName name) { + if(mappedChildSchemas.containsKey(name)) { + return mappedChildSchemas.get(name); + } + + throw new IllegalArgumentException("Unknown child: " + name + " in: " + delegate); + } + + @Override + public DataSchemaNode getDataChildByName(String name) { + // Unused + throw new UnsupportedOperationException("Unable to retrieve child node by name"); + } + + @Override + public Set getUses() { + return delegate.getUses(); + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/SchemaUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/SchemaUtils.java new file mode 100644 index 0000000000..60cb07601a --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/SchemaUtils.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2013 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.schema.transform.base; + +import com.google.common.base.Function; +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils; +import org.opendaylight.yangtools.yang.model.api.*; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public final class SchemaUtils { + + private SchemaUtils() { + } + + public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname) { + Set childNodes = schema.getChildNodes(); + return findSchemaForChild(schema, qname, childNodes); + } + + public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname, Set childNodes) { + Optional childSchema = XmlDocumentUtils.findFirstSchema(qname, childNodes); + Preconditions.checkState(childSchema.isPresent(), + "Unknown child(ren) node(s) detected, identified by: %s, in: %s", qname, schema); + return childSchema.get(); + } + + public static AugmentationSchema findSchemaForAugment(AugmentationTarget schema, Set qNames) { + Optional schemaForAugment = findAugment(schema, qNames); + Preconditions.checkState(schemaForAugment.isPresent(), "Unknown augmentation node detected, identified by: %s, in: %s", + qNames, schema); + return schemaForAugment.get(); + } + + public static AugmentationSchema findSchemaForAugment(ChoiceNode schema, Set qNames) { + Optional schemaForAugment = Optional.absent(); + + for (ChoiceCaseNode choiceCaseNode : schema.getCases()) { + schemaForAugment = findAugment(choiceCaseNode, qNames); + if(schemaForAugment.isPresent()) { + break; + } + } + + Preconditions.checkState(schemaForAugment.isPresent(), "Unknown augmentation node detected, identified by: %s, in: %s", + qNames, schema); + return schemaForAugment.get(); + } + + private static Optional findAugment(AugmentationTarget schema, Set qNames) { + for (AugmentationSchema augment : schema.getAvailableAugmentations()) { + + HashSet qNamesFromAugment = Sets.newHashSet(Collections2.transform(augment.getChildNodes(), new Function() { + @Override + public QName apply(DataSchemaNode input) { + return input.getQName(); + } + })); + + if(qNamesFromAugment.equals(qNames)) { + return Optional.of(augment); + } + } + + return Optional.absent(); + } + + public static DataSchemaNode findSchemaForChild(ChoiceNode schema, QName childPartialQName) { + for (ChoiceCaseNode choiceCaseNode : schema.getCases()) { + Optional childSchema = XmlDocumentUtils.findFirstSchema(childPartialQName, + choiceCaseNode.getChildNodes()); + if (childSchema.isPresent()) { + return childSchema.get(); + } + } + + + throw new IllegalStateException(String.format("Unknown child(ren) node(s) detected, identified by: %s, in: %s", + childPartialQName, schema)); + } + + /** + * Recursively find all child nodes that come from choices in augment. + * + * @return Map with all child nodes, to their most top augmentation + */ + public static Map mapChildElementsFromChoicesInAugment(AugmentationSchema schema, Set realChildSchemas) { + Map mappedChoices = Maps.newLinkedHashMap(); + + for (DataSchemaNode realChildSchema : realChildSchemas) { + if(realChildSchema instanceof ChoiceNode) + mappedChoices.putAll(mapChildElementsFromChoices(schema, realChildSchemas)); + } + + return mappedChoices; + } + + /** + * Recursively find all child nodes that come from choices. + * + * @return Map with all child nodes, to their most top augmentation + */ + public static Map mapChildElementsFromChoices(DataNodeContainer schema) { + Set childNodes = schema.getChildNodes(); + + return mapChildElementsFromChoices(schema, childNodes); + } + + private static Map mapChildElementsFromChoices(DataNodeContainer schema, Set childNodes) { + Map mappedChoices = Maps.newLinkedHashMap(); + + for (final DataSchemaNode childSchema : childNodes) { + if(childSchema instanceof ChoiceNode) { + for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) childSchema).getCases()) { + + for (QName qName : getChildNodes(choiceCaseNode)) { + mappedChoices.put(qName, (ChoiceNode) childSchema); + } + } + } + } + + // Remove augmented choices + // TODO ineffective, mapping augments one more time is not necessary, the map could be injected + if(schema instanceof AugmentationTarget) { + final Map augments = mapChildElementsFromAugments((AugmentationTarget) schema); + + return Maps.filterKeys(mappedChoices, new Predicate() { + @Override + public boolean apply(QName input) { + return augments.containsKey(input) == false; + } + }); + } + + return mappedChoices; + } + + /** + * Recursively find all child nodes that come from augmentations. + * + * @return Map with all child nodes, to their most top augmentation + */ + public static Map mapChildElementsFromAugments(AugmentationTarget schema) { + + Map childNodesToAugmentation = Maps.newLinkedHashMap(); + + // Find QNames of augmented child nodes + Map augments = Maps.newHashMap(); + for (final AugmentationSchema augmentationSchema : schema.getAvailableAugmentations()) { + for (DataSchemaNode dataSchemaNode : augmentationSchema.getChildNodes()) { + augments.put(dataSchemaNode.getQName(), augmentationSchema); + } + } + + // Augmented nodes have to be looked up directly in augmentationTarget + // because nodes from augment do not contain nodes from other augmentations + if (schema instanceof DataNodeContainer) { + + for (DataSchemaNode child : ((DataNodeContainer) schema).getChildNodes()) { + // If is not augmented child, continue + if (augments.containsKey(child.getQName()) == false) + continue; + + AugmentationSchema mostTopAugmentation = augments.get(child.getQName()); + + // recursively add all child nodes in case of augment, case and choice + if (child instanceof AugmentationSchema || child instanceof ChoiceCaseNode) { + for (QName qName : getChildNodes((DataNodeContainer) child)) { + childNodesToAugmentation.put(qName, mostTopAugmentation); + } + } else if (child instanceof ChoiceNode) { + for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) child).getCases()) { + for (QName qName : getChildNodes(choiceCaseNode)) { + childNodesToAugmentation.put(qName, mostTopAugmentation); + } + } + } else { + childNodesToAugmentation.put(child.getQName(), mostTopAugmentation); + } + } + } + + // Choice Node has to map child nodes from all its cases + if (schema instanceof ChoiceNode) { + for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) schema).getCases()) { + if (augments.containsKey(choiceCaseNode.getQName()) == false) { + continue; + } + + for (QName qName : getChildNodes(choiceCaseNode)) { + childNodesToAugmentation.put(qName, augments.get(choiceCaseNode.getQName())); + } + } + } + + return childNodesToAugmentation; + } + + /** + * Recursively list all child nodes. + * + * In case of choice, augment and cases, step in. + */ + public static Set getChildNodes(DataNodeContainer nodeContainer) { + Set allChildNodes = Sets.newHashSet(); + + for (DataSchemaNode childSchema : nodeContainer.getChildNodes()) { + if(childSchema instanceof ChoiceNode) { + for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) childSchema).getCases()) { + allChildNodes.addAll(getChildNodes(choiceCaseNode)); + } + } else if(childSchema instanceof AugmentationSchema || childSchema instanceof ChoiceCaseNode) { + allChildNodes.addAll(getChildNodes((DataNodeContainer) childSchema)); + } + else { + allChildNodes.add(childSchema.getQName()); + } + } + + return allChildNodes; + } + + /** + * Retrieves real schemas for augmented child node. + * + * Schema of the same child node from augment, and directly from target is not the same. + * Schema of child node from augment is incomplete, therefore its useless for xml <-> normalizedNode translation. + * + */ + public static Set getRealSchemasForAugment(AugmentationTarget targetSchema, AugmentationSchema augmentSchema) { + if(targetSchema.getAvailableAugmentations().contains(augmentSchema) == false) { + return Collections.emptySet(); + } + + Set realChildNodes = Sets.newHashSet(); + + if(targetSchema instanceof DataNodeContainer) { + realChildNodes = getRealSchemasForAugment((DataNodeContainer)targetSchema, augmentSchema); + } else if(targetSchema instanceof ChoiceNode) { + for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) { + for (ChoiceCaseNode choiceCaseNode : ((ChoiceNode) targetSchema).getCases()) { + if(getChildNodes(choiceCaseNode).contains(dataSchemaNode.getQName())) { + realChildNodes.add(choiceCaseNode.getDataChildByName(dataSchemaNode.getQName())); + } + } + } + } + + return realChildNodes; + } + + public static Set getRealSchemasForAugment(DataNodeContainer targetSchema, + AugmentationSchema augmentSchema) { + Set realChildNodes = Sets.newHashSet(); + for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) { + DataSchemaNode realChild = ((DataNodeContainer) targetSchema).getDataChildByName(dataSchemaNode.getQName()); + realChildNodes.add(realChild); + } + + return realChildNodes; + } + + public static Optional detectCase(ChoiceNode schema, DataContainerChild child) { + for (ChoiceCaseNode choiceCaseNode : schema.getCases()) { + for (DataSchemaNode childFromCase : choiceCaseNode.getChildNodes()) { + if (childFromCase.getQName().equals(child.getNodeType())) { + return Optional.of(choiceCaseNode); + } + } + } + + return Optional.absent(); + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/AugmentationNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/AugmentationNodeBaseParser.java new file mode 100644 index 0000000000..804f28c272 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/AugmentationNodeBaseParser.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +/** + * Abstract(base) parser for AugmentationNode, parses elements of type E. + * + * @param type of elements to be parsed + */ +public abstract class AugmentationNodeBaseParser extends + BaseDispatcherParser { + + @Override + protected final DataContainerNodeBuilder getBuilder(AugmentationSchema schema) { + return Builders.augmentationBuilder(schema); + } + + @Override + protected final Set getRealSchemasForAugment(AugmentationSchema schema, AugmentationSchema augmentSchema) { + return SchemaUtils.getRealSchemasForAugment(schema, augmentSchema); + } + + + @Override + protected final DataSchemaNode getSchemaForChild(AugmentationSchema schema, QName childQName) { + return SchemaUtils.findSchemaForChild(schema, childQName); + } + + @Override + protected final Map mapChildElementsFromChoices(AugmentationSchema schema) { + return SchemaUtils.mapChildElementsFromChoices(schema); + } + + @Override + protected final Map mapChildElementsFromAugments(AugmentationSchema schema) { + return Collections.emptyMap(); + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/BaseDispatcherParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/BaseDispatcherParser.java new file mode 100644 index 0000000000..e24a1f7e26 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/BaseDispatcherParser.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; +import com.google.common.collect.LinkedListMultimap; + +/** + * Abstract(base) Parser for DataContainerNodes e.g. ContainerNode, AugmentationNode. + */ +public abstract class BaseDispatcherParser, S> + implements ToNormalizedNodeParser { + + /** + * + * @param schema + * @return New(empty) instance of a builder to build node identified by schema. + */ + protected abstract DataContainerNodeBuilder getBuilder(S schema); + + /** + * + * @param schema + * @param childQName QName of a child being parsed, QName does not continue revision date + * @return schema object for child identified by parent schema: schema and QName childQName + */ + protected abstract DataSchemaNode getSchemaForChild(S schema, QName childQName); + + /** + * + * @param xml + * @return map from QName to child elements. Multiple elements are allowed under QName. + */ + protected abstract LinkedListMultimap mapChildElements(Iterable xml); + + /** + * + * @param schema + * @return map from QName to ChoiceNode schema of child nodes that are + * contained within a choice statement under current schema. + */ + protected abstract Map mapChildElementsFromChoices(S schema); + + /** + * + * @param schema + * @return map from QName to child elements that are added by augmentation + * that targets current schema. + */ + protected abstract Map mapChildElementsFromAugments(S schema); + + /** + * + * @param schema + * @param augmentSchema + * @return Set of real schema objects that represent child nodes of an + * augmentation. Augmentation schema child nodes, if further + * augmented, do not contain further augmented, that are crucial for + * parsing. The real schema object can be retrieved from parent schema: schema. + */ + protected abstract Set getRealSchemasForAugment(S schema, AugmentationSchema augmentSchema); + + /** + * + * @return dispatcher object to dispatch parsing of child elements, might be + * the same instance if provided parsers are immutable. + */ + protected abstract NodeParserDispatcher getDispatcher(); + + @Override + public N parse(Iterable element, S schema) { + + checkAtLeastOneNode(schema, element); + + DataContainerNodeBuilder containerBuilder = getBuilder(schema); + + // Map child nodes to QName + LinkedListMultimap mappedChildElements = mapChildElements(element); + + // Map child nodes from Augments + Map mappedAugmentChildNodes = mapChildElementsFromAugments(schema); + LinkedListMultimap augmentsToElements = LinkedListMultimap.create(); + + // Map child nodes from choices + Map mappedChoiceChildNodes = mapChildElementsFromChoices(schema); + LinkedListMultimap choicesToElements = LinkedListMultimap.create(); + + // process Child nodes + for (QName childPartialQName : mappedChildElements.keySet()) { + DataSchemaNode childSchema = getSchemaForChild(schema, childPartialQName); + List childrenForQName = mappedChildElements.get(childPartialQName); + + // Augment + if (isMarkedAs(mappedAugmentChildNodes, childSchema.getQName())) { + AugmentationSchema augmentationSchema = mappedAugmentChildNodes.get(childSchema.getQName()); + augmentsToElements.putAll(augmentationSchema, childrenForQName); + // Choices + } else if (isMarkedAs(mappedChoiceChildNodes, childSchema.getQName())) { + ChoiceNode choiceSchema = mappedChoiceChildNodes.get(childSchema.getQName()); + choicesToElements.putAll(choiceSchema, childrenForQName); + // Regular child nodes + } else { + DataContainerChild builtChildNode = getDispatcher() + .dispatchChildElement(childSchema, childrenForQName); + containerBuilder.withChild(builtChildNode); + } + } + + // TODO ordering is not preserved for choice and augment elements + for (ChoiceNode choiceSchema : choicesToElements.keySet()) { + containerBuilder.withChild(getDispatcher().dispatchChildElement(choiceSchema, + choicesToElements.get(choiceSchema))); + } + + for (AugmentationSchema augmentSchema : augmentsToElements.keySet()) { + Set realChildSchemas = getRealSchemasForAugment(schema, augmentSchema); + AugmentationSchemaProxy augSchemaProxy = new AugmentationSchemaProxy(augmentSchema, realChildSchemas); + containerBuilder.withChild(getDispatcher().dispatchChildElement(augSchemaProxy, augmentsToElements.get(augmentSchema))); + } + + return containerBuilder.build(); + } + + private boolean isMarkedAs(Map mappedAugmentChildNodes, QName qName) { + return mappedAugmentChildNodes.containsKey(qName); + } + + protected void checkOnlyOneNode(S schema, Iterable childNodes) { + final int size = Iterables.size(childNodes); + Preconditions.checkArgument(size == 1, + "Node detected multiple times, should be 1, identified by: %s, found: %s", schema, childNodes); + } + + private void checkAtLeastOneNode(S schema, Iterable childNodes) { + Preconditions.checkArgument(Iterables.isEmpty(childNodes) == false, + "Node detected 0 times, should be at least 1, identified by: %s, found: %s", schema, childNodes); + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ChoiceNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ChoiceNodeBaseParser.java new file mode 100644 index 0000000000..021efc0e03 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ChoiceNodeBaseParser.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import java.util.Map; +import java.util.Set; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; +import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +/** + * Abstract(base) parser for ChoiceNodes, parses elements of type E. + * + * @param type of elements to be parsed + */ +public abstract class ChoiceNodeBaseParser extends + BaseDispatcherParser { + + @Override + protected final DataContainerNodeBuilder getBuilder( + org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) { + return Builders.choiceBuilder(schema); + } + + @Override + protected final Set getRealSchemasForAugment(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema, + AugmentationSchema augmentSchema) { + Set fromAllCases = Sets.newHashSet(); + + fromAllCases.addAll(SchemaUtils.getRealSchemasForAugment(schema, augmentSchema)); + + for (ChoiceCaseNode choiceCaseNode : schema.getCases()) { + fromAllCases.addAll(SchemaUtils.getRealSchemasForAugment((AugmentationTarget) choiceCaseNode, augmentSchema)); + } + + return fromAllCases; + } + + @Override + protected final DataSchemaNode getSchemaForChild(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema, + QName childQName) { + return SchemaUtils.findSchemaForChild(schema, childQName); + } + + @Override + protected final Map mapChildElementsFromChoices( + org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) { + Map mappedChoices = Maps.newLinkedHashMap(); + + for (ChoiceCaseNode choiceCaseNode : schema.getCases()) { + mappedChoices.putAll(SchemaUtils.mapChildElementsFromChoices(choiceCaseNode)); + } + + return mappedChoices; + } + + @Override + protected final Map mapChildElementsFromAugments( + org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) { + Map mappedAugments = Maps.newLinkedHashMap(); + + for (ChoiceCaseNode choiceCaseNode : schema.getCases()) { + mappedAugments.putAll(SchemaUtils.mapChildElementsFromAugments(choiceCaseNode)); + } + return mappedAugments; + } + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ContainerNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ContainerNodeBaseParser.java new file mode 100644 index 0000000000..f2c335086c --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ContainerNodeBaseParser.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import java.util.Map; +import java.util.Set; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; +import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +/** + * Abstract(base) parser for ContainerNodes, parses elements of type E. + * + * @param type of elements to be parsed + */ +public abstract class ContainerNodeBaseParser extends + BaseDispatcherParser { + + @Override + protected final DataContainerNodeBuilder getBuilder( + ContainerSchemaNode schema) { + return Builders.containerBuilder(schema); + } + + @Override + public final ContainerNode parse(Iterable elements, ContainerSchemaNode schema) { + checkOnlyOneNode(schema, elements); + return super.parse(elements, schema); + } + + @Override + protected final Set getRealSchemasForAugment(ContainerSchemaNode schema, AugmentationSchema augmentSchema) { + return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentSchema); + } + + @Override + protected final DataSchemaNode getSchemaForChild(ContainerSchemaNode schema, QName childQName) { + return SchemaUtils.findSchemaForChild(schema, childQName); + } + + @Override + protected final Map mapChildElementsFromChoices(ContainerSchemaNode schema) { + return SchemaUtils.mapChildElementsFromChoices(schema); + } + + @Override + protected final Map mapChildElementsFromAugments(ContainerSchemaNode schema) { + return SchemaUtils.mapChildElementsFromAugments(schema); + } + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafNodeBaseParser.java new file mode 100644 index 0000000000..8daef7f0db --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafNodeBaseParser.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; + +/** + * Abstract(base) parser for LeafNodes, parses elements of type E. + * + * @param type of elements to be parsed + */ +public abstract class LeafNodeBaseParser implements + ToNormalizedNodeParser, LeafSchemaNode> { + + @Override + public final LeafNode parse(Iterable elements, LeafSchemaNode schema) { + final int size = Iterables.size(elements); + Preconditions.checkArgument(size == 1, "Elements mapped to leaf node illegal count: %s", size); + Object value = parseLeaf(elements.iterator().next(), schema); + return Builders.leafBuilder(schema).withValue(value).build(); + } + + /** + * + * Parse the inner value of a LeafNode from element of type E. + * + * @param element to be parsed + * @param schema schema for leaf + * @return parsed element as an Object + */ + protected abstract Object parseLeaf(E element, LeafSchemaNode schema); +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetEntryNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetEntryNodeBaseParser.java new file mode 100644 index 0000000000..68e2b399e0 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetEntryNodeBaseParser.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; + +/** + * Abstract(base) parser for LeafSetEntryNodes, parses elements of type E. + * + * @param type of elements to be parsed + */ +public abstract class LeafSetEntryNodeBaseParser implements + ToNormalizedNodeParser, LeafListSchemaNode> { + + @Override + public final LeafSetEntryNode parse(Iterable elements, LeafListSchemaNode schema) { + final int size = Iterables.size(elements); + Preconditions.checkArgument(size == 1, "Xml elements mapped to leaf node illegal count: %s", size); + Object value = parseLeafListEntry(elements.iterator().next(),schema); + return Builders.leafSetEntryBuilder(schema).withValue(value).build(); + } + + /** + * + * Parse the inner value of a LeafSetEntryNode from element of type E. + * + * @param element to be parsed + * @param schema schema for leaf-list + * @return parsed element as an Object + */ + protected abstract Object parseLeafListEntry(E element, LeafListSchemaNode schema); +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetNodeBaseParser.java new file mode 100644 index 0000000000..37ff5c95fd --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetNodeBaseParser.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import java.util.Collections; + +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; + +/** + * Abstract(base) parser for LeafSetNodes, parses elements of type E. + * + * @param type of elements to be parsed + */ +public abstract class LeafSetNodeBaseParser implements + ToNormalizedNodeParser, LeafListSchemaNode> { + + @Override + public final LeafSetNode parse(Iterable childNodes, LeafListSchemaNode schema) { + + ListNodeBuilder> leafListBuilder = Builders.leafSetBuilder(schema); + for (E childNode : childNodes) { + LeafSetEntryNode builtChild = getLeafSetEntryNodeBaseParser().parse( + Collections.singletonList(childNode), schema); + + // TODO: can we get rid of this cast/SuppressWarnings somehow? + @SuppressWarnings("unchecked") + final LeafSetEntryNode child = (LeafSetEntryNode) builtChild; + leafListBuilder.withChild(child); + } + + return leafListBuilder.build(); + } + + /** + * + * @return parser for inner LeafSetEntryNodes used to parse every entry of LeafSetNode, might be the same instance in case its immutable + */ + protected abstract ToNormalizedNodeParser, LeafListSchemaNode> getLeafSetEntryNodeBaseParser(); +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapEntryNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapEntryNodeBaseParser.java new file mode 100644 index 0000000000..cc59d771b6 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapEntryNodeBaseParser.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import java.util.Map; +import java.util.Set; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; +import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; + +/** + * Abstract(base) parser for MapEntryNodes, parses elements of type E. + * + * @param type of elements to be parsed + */ +public abstract class MapEntryNodeBaseParser extends BaseDispatcherParser { + + @Override + protected final DataContainerNodeBuilder getBuilder( + ListSchemaNode schema) { + return Builders.mapEntryBuilder(schema); + } + + @Override + public final MapEntryNode parse(Iterable elements, ListSchemaNode schema) { + checkOnlyOneNode(schema, elements); + return super.parse(elements, schema); + } + + @Override + protected final Set getRealSchemasForAugment(ListSchemaNode schema, AugmentationSchema augmentSchema) { + return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentSchema); + } + + @Override + protected final DataSchemaNode getSchemaForChild(ListSchemaNode schema, QName childQName) { + return SchemaUtils.findSchemaForChild(schema, childQName); + } + + @Override + protected final Map mapChildElementsFromChoices(ListSchemaNode schema) { + return SchemaUtils.mapChildElementsFromChoices(schema); + } + + @Override + protected final Map mapChildElementsFromAugments(ListSchemaNode schema) { + return SchemaUtils.mapChildElementsFromAugments(schema); + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapNodeBaseParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapNodeBaseParser.java new file mode 100644 index 0000000000..11ec82cedb --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapNodeBaseParser.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import java.util.Collections; + +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; + +/** + * Abstract(base) parser for MapNodes, parses elements of type E. + * + * @param type of elements to be parsed + */ +public abstract class MapNodeBaseParser implements ToNormalizedNodeParser { + + @Override + public final MapNode parse(Iterable childNodes, ListSchemaNode schema) { + CollectionNodeBuilder listBuilder = Builders.mapBuilder(schema); + + for (E childNode : childNodes) { + MapEntryNode listChild = getMapEntryNodeDomParser().parse(Collections.singletonList(childNode), schema); + listBuilder.withChild(listChild); + } + + return listBuilder.build(); + } + + /** + * + * @return parser for inner MapEntryNodes used to parse every entry of MapNode, might be the same instance in case its immutable + */ + protected abstract ToNormalizedNodeParser getMapEntryNodeDomParser(); + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/NodeParserDispatcher.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/NodeParserDispatcher.java new file mode 100644 index 0000000000..e18db0dba2 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/NodeParserDispatcher.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.parser; + +import java.util.List; + +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; + +import com.google.common.base.Preconditions; + +/** + * + * Dispatches the parsing process of elements according to schema and returns the parsed Node. + * + * @param type of elements parsed + */ +public interface NodeParserDispatcher { + + DataContainerChild dispatchChildElement(Object schema, List childNodes); + + /** + * Abstract implementation that implements the dispatch conditions. Only requires parsers to be provided. + * The same instance of parser can be provided in case it is immutable. + */ + public static abstract class BaseNodeParserDispatcher implements NodeParserDispatcher { + + @Override + public final DataContainerChild dispatchChildElement(Object schema, List childNodes) { + Preconditions.checkArgument(childNodes.isEmpty() == false); + + if (schema instanceof ContainerSchemaNode) { + return getContainerNodeParser().parse(childNodes, (ContainerSchemaNode) schema); + } else if (schema instanceof LeafSchemaNode) { + return getLeafNodeParser().parse(childNodes, (LeafSchemaNode) schema); + } else if (schema instanceof LeafListSchemaNode) { + return getLeafSetNodeParser().parse(childNodes, (LeafListSchemaNode) schema); + } else if (schema instanceof ListSchemaNode) { + return getMapNodeParser().parse(childNodes, (ListSchemaNode) schema); + } else if (schema instanceof ChoiceNode) { + return getChoiceNodeParser().parse(childNodes, (ChoiceNode) schema); + } else if (schema instanceof AugmentationSchema) { + return getAugmentationNodeParser().parse(childNodes, (AugmentationSchema) schema); + } + + throw new IllegalArgumentException("Unable to parse node, unknown schema type: " + schema.getClass()); + } + + protected abstract ToNormalizedNodeParser getContainerNodeParser(); + + protected abstract ToNormalizedNodeParser, LeafSchemaNode> getLeafNodeParser(); + + protected abstract ToNormalizedNodeParser, LeafListSchemaNode> getLeafSetNodeParser(); + + protected abstract ToNormalizedNodeParser getMapNodeParser(); + + protected abstract ToNormalizedNodeParser getChoiceNodeParser(); + + protected abstract ToNormalizedNodeParser getAugmentationNodeParser(); + + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/AugmentationNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/AugmentationNodeBaseSerializer.java new file mode 100644 index 0000000000..35dd342643 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/AugmentationNodeBaseSerializer.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import java.util.Set; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +/** + * Abstract(base) serializer for AugmentationNode, serializes elements of type E. + * + * @param type of serialized elements + */ +public abstract class AugmentationNodeBaseSerializer extends + BaseDispatcherSerializer { + + @Override + protected Set getRealSchemasForAugment(AugmentationSchema schema, AugmentationSchema augmentationSchema) { + return SchemaUtils.getRealSchemasForAugment(schema, augmentationSchema); + } + + @Override + protected DataSchemaNode getSchemaForChild(AugmentationSchema schema, + DataContainerChild childNode) { + return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType()); + } + + @Override + protected AugmentationSchema getAugmentedCase(AugmentationSchema schema, AugmentationNode augmentationNode) { + throw new UnsupportedOperationException(""); + } + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/BaseDispatcherSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/BaseDispatcherSerializer.java new file mode 100644 index 0000000000..053520de03 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/BaseDispatcherSerializer.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import java.util.List; +import java.util.Set; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.AugmentationSchemaProxy; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +/** + * Abstract(base) Serializer for DataContainerNodes e.g. ContainerNode, AugmentationNode. + */ +public abstract class BaseDispatcherSerializer, S> implements + FromNormalizedNodeSerializer { + + /** + * + * @param schema + * @param augmentationSchema + * @return Set of real schema objects that represent child nodes of an + * augmentation. Augmentation schema child nodes, if further + * augmented, do not contain further augmented, that are crucial for + * parsing. The real schema object can be retrieved from parent schema: schema. + */ + protected abstract Set getRealSchemasForAugment(S schema, AugmentationSchema augmentationSchema); + + /** + * + * @param schema + * @param childNode + * @return Schema object associated with child node identified as: childNode. + * Schema should be retrieved from parent schema: schema. + */ + protected abstract DataSchemaNode getSchemaForChild(S schema, + DataContainerChild childNode); + + /** + * + * @param schema + * @param augmentationNode + * @return Schema object associated with augmentation child node identified as: augmentationNode. + * Schema should be retrieved from parent schema: schema. + */ + protected abstract AugmentationSchema getAugmentedCase(S schema, AugmentationNode augmentationNode); + + /** + * + * @return Dispatcher object to dispatch serialization of child elements, might be + * the same instance if provided serializers are immutable. + */ + protected abstract NodeSerializerDispatcher getNodeDispatcher(); + + @Override + public Iterable serialize(S schema, N node) { + List> choiceChildren = Lists.newArrayList(); + + for (DataContainerChild choiceChild : node.getValue()) { + + Object childSchema; + + if (choiceChild instanceof AugmentationNode) { + + AugmentationSchema augSchema = getAugmentedCase(schema, (AugmentationNode) choiceChild); + Set realChildSchemas = getRealSchemasForAugment(schema, augSchema); + childSchema = new AugmentationSchemaProxy(augSchema, realChildSchemas); + + } else { + childSchema = getSchemaForChild(schema, choiceChild); + } + + Iterable childElements = getNodeDispatcher().dispatchChildElement(childSchema, choiceChild); + choiceChildren.add(Preconditions.checkNotNull(childElements)); + } + + return Iterables.concat(choiceChildren); + } +} \ No newline at end of file diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ChoiceNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ChoiceNodeBaseSerializer.java new file mode 100644 index 0000000000..af779b6dfa --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ChoiceNodeBaseSerializer.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import java.util.Set; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; +import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +import com.google.common.collect.Sets; + +/** + * Abstract(base) serializer for ChoiceNodes, serializes elements of type E. + * + * @param type of serialized elements + */ +public abstract class ChoiceNodeBaseSerializer + extends + BaseDispatcherSerializer { + + @Override + protected final DataSchemaNode getSchemaForChild(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema, + DataContainerChild childNode) { + return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType()); + } + + @Override + protected final AugmentationSchema getAugmentedCase(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema, + AugmentationNode augmentationNode) { + return SchemaUtils.findSchemaForAugment(schema, augmentationNode.getIdentifier().getPossibleChildNames()); + } + + @Override + protected final Set getRealSchemasForAugment(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema, AugmentationSchema augmentationSchema) { + Set aggregatedSchemas = Sets.newHashSet(); + + aggregatedSchemas.addAll(SchemaUtils.getRealSchemasForAugment(schema, augmentationSchema)); + + for (ChoiceCaseNode choiceCaseNode : schema.getCases()) { + aggregatedSchemas.addAll(SchemaUtils.getRealSchemasForAugment((AugmentationTarget) choiceCaseNode, augmentationSchema)); + } + + return aggregatedSchemas; + } +} \ No newline at end of file diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ContainerNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ContainerNodeBaseSerializer.java new file mode 100644 index 0000000000..6d0b9f9100 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ContainerNodeBaseSerializer.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import java.util.Set; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; + +/** + * Abstract(base) serializer for ContainerNodes, serializes elements of type E. + * + * @param type of serialized elements + */ +public abstract class ContainerNodeBaseSerializer extends + BaseDispatcherSerializer { + + @Override + protected final DataSchemaNode getSchemaForChild(ContainerSchemaNode schema, + DataContainerChild childNode) { + return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType()); + } + + @Override + protected final AugmentationSchema getAugmentedCase(ContainerSchemaNode schema, AugmentationNode augmentationNode) { + return SchemaUtils.findSchemaForAugment(schema, augmentationNode.getIdentifier().getPossibleChildNames()); + } + + @Override + protected final Set getRealSchemasForAugment(ContainerSchemaNode schema, AugmentationSchema augmentationSchema) { + return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentationSchema); + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafNodeBaseSerializer.java new file mode 100644 index 0000000000..2e137662d6 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafNodeBaseSerializer.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import java.util.Collections; + +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; + +/** + * Abstract(base) serializer for LeafNodes, serializes elements of type E. + * + * @param type of serialized elements + */ +public abstract class LeafNodeBaseSerializer implements + FromNormalizedNodeSerializer, LeafSchemaNode> { + + @Override + public final Iterable serialize(LeafSchemaNode schema, LeafNode node) { + return Collections.singletonList(serializeLeaf(schema, node)); + } + + /** + * + * Serialize the inner value of a LeafNode into element of type E. + * + * @param node to be serialized + * @param schema schema for leaf + * @return serialized inner value as an Element + */ + protected abstract E serializeLeaf(LeafSchemaNode schema, LeafNode node); +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetEntryNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetEntryNodeBaseSerializer.java new file mode 100644 index 0000000000..f6905900a4 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetEntryNodeBaseSerializer.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import java.util.Collections; + +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; + +/** + * Abstract(base) serializer for LeafSetEntryNodes, serializes elements of type E. + * + * @param type of serialized elements + */ +public abstract class LeafSetEntryNodeBaseSerializer implements + FromNormalizedNodeSerializer, LeafListSchemaNode> { + + @Override + public final Iterable serialize(LeafListSchemaNode schema, LeafSetEntryNode node) { + return Collections.singletonList(serializeLeaf(schema, node)); + } + + /** + * + * Serialize the inner value of a LeafSetEntryNode into element of type E. + * + * @param node to be serialized + * @param schema schema for leaf-list + * @return serialized inner value as an Element + */ + protected abstract E serializeLeaf(LeafListSchemaNode schema, LeafSetEntryNode node); +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetNodeBaseSerializer.java new file mode 100644 index 0000000000..302ffbbd58 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetNodeBaseSerializer.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; + +/** + * Abstract(base) serializer for LeafSetNodes, serializes elements of type E. + * + * @param type of serialized elements + */ +public abstract class LeafSetNodeBaseSerializer implements + FromNormalizedNodeSerializer, LeafListSchemaNode> { + + @Override + public final Iterable serialize(final LeafListSchemaNode schema, final LeafSetNode node) { + return Iterables.concat(Iterables.transform(node.getValue(), new Function, Iterable>() { + @Override + public Iterable apply(final LeafSetEntryNode input) { + final Iterable serializedChild = getLeafSetEntryNodeSerializer().serialize(schema, input); + final int size = Iterables.size(serializedChild); + Preconditions.checkState(size == 1, + "Unexpected count of elements for leaf-list entry serialized from: %s, should be 1, was: %s", + input, size); + return serializedChild; + } + })); + } + + /** + * + * @return serializer for inner LeafSetEntryNodes used to serialize every entry of LeafSetNode, might be the same instance in case its immutable + */ + protected abstract FromNormalizedNodeSerializer, LeafListSchemaNode> getLeafSetEntryNodeSerializer(); +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapEntryNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapEntryNodeBaseSerializer.java new file mode 100644 index 0000000000..2f7822aa15 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapEntryNodeBaseSerializer.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import java.util.Set; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.SchemaUtils; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.AugmentationTarget; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; + +/** + * Abstract(base) serializer for MapEntryNodes, serializes elements of type E. + * + * @param type of serialized elements + */ +public abstract class MapEntryNodeBaseSerializer extends + BaseDispatcherSerializer { + + @Override + protected final DataSchemaNode getSchemaForChild(ListSchemaNode schema, + DataContainerChild childNode) { + return SchemaUtils.findSchemaForChild(schema, childNode.getNodeType()); + } + + @Override + protected final AugmentationSchema getAugmentedCase(ListSchemaNode schema, AugmentationNode augmentationNode) { + return SchemaUtils.findSchemaForAugment(schema, augmentationNode.getIdentifier().getPossibleChildNames()); + } + + @Override + protected final Set getRealSchemasForAugment(ListSchemaNode schema, AugmentationSchema augmentationSchema) { + return SchemaUtils.getRealSchemasForAugment((AugmentationTarget) schema, augmentationSchema); + } + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapNodeBaseSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapNodeBaseSerializer.java new file mode 100644 index 0000000000..dba2c5db5c --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapNodeBaseSerializer.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; + +/** + * Abstract(base) serializer for MapNodes, serializes elements of type E. + * + * @param type of serialized elements + */ +public abstract class MapNodeBaseSerializer implements FromNormalizedNodeSerializer { + + @Override + public final Iterable serialize(final ListSchemaNode schema, final MapNode node) { + return Iterables.concat(Iterables.transform(node.getValue(), new Function>() { + @Override + public Iterable apply(MapEntryNode input) { + final Iterable serializedChild = getMapEntryNodeDomSerializer().serialize(schema, input); + final int size = Iterables.size(serializedChild); + + Preconditions.checkState(size == 1, + "Unexpected count of entries for list serialized from: %s, should be 1, was: %s", + input, size); + return serializedChild; + } + })); + } + + /** + * + * @return serializer for inner MapEntryNodes used to serialize every entry of MapNode, might be the same instance in case its immutable + */ + protected abstract FromNormalizedNodeSerializer getMapEntryNodeDomSerializer(); +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/NodeSerializerDispatcher.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/NodeSerializerDispatcher.java new file mode 100644 index 0000000000..e19b625ef2 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/NodeSerializerDispatcher.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2013 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.schema.transform.base.serializer; + +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; +import org.opendaylight.yangtools.yang.data.api.schema.MixinNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Iterables; + +/** + * + * Dispatches the serialization process of nodes according to schema and returns the serialized elements. + * + * @param type of serialized elements + */ +public interface NodeSerializerDispatcher { + + Iterable dispatchChildElement(Object childSchema, + DataContainerChild dataContainerChild); + + /** + * Abstract implementation that implements the dispatch conditions. Only requires serializers to be provided. + * The same instance of serializer can be provided in case it is immutable. + */ + public static abstract class BaseNodeSerializerDispatcher implements NodeSerializerDispatcher { + + @Override + public final Iterable dispatchChildElement(Object childSchema, + DataContainerChild dataContainerChild) { + if (dataContainerChild instanceof ContainerNode) { + return onContainerNode(childSchema, dataContainerChild); + } else if (dataContainerChild instanceof LeafNode) { + return onLeafNode(childSchema, dataContainerChild); + } else if (dataContainerChild instanceof MixinNode) { + if (dataContainerChild instanceof LeafSetNode) { + return onLeafListNode(childSchema, dataContainerChild); + } else if (dataContainerChild instanceof MapNode) { + return onListNode(childSchema, dataContainerChild); + } else if (dataContainerChild instanceof ChoiceNode) { + return onChoiceNode(childSchema, dataContainerChild); + } else if (dataContainerChild instanceof AugmentationNode) { + return onAugmentationSchema(childSchema, dataContainerChild); + } + } + throw new IllegalArgumentException("Unable to serialize " + childSchema); + } + + private Iterable onAugmentationSchema(Object childSchema, + DataContainerChild dataContainerChild) { + checkSchemaCompatibility(childSchema, AugmentationSchema.class, dataContainerChild); + return getAugmentationNodeSerializer().serialize((AugmentationSchema) childSchema, + (AugmentationNode) dataContainerChild); + } + + private Iterable onChoiceNode(Object childSchema, + DataContainerChild dataContainerChild) { + checkSchemaCompatibility(childSchema, org.opendaylight.yangtools.yang.model.api.ChoiceNode.class, + dataContainerChild); + return getChoiceNodeSerializer() + .serialize((org.opendaylight.yangtools.yang.model.api.ChoiceNode) childSchema, + (ChoiceNode) dataContainerChild); + } + + private Iterable onListNode(Object childSchema, + DataContainerChild dataContainerChild) { + checkSchemaCompatibility(childSchema, ListSchemaNode.class, dataContainerChild); + return getMapNodeSerializer().serialize((ListSchemaNode) childSchema, (MapNode) dataContainerChild); + } + + private Iterable onLeafListNode(Object childSchema, + DataContainerChild dataContainerChild) { + checkSchemaCompatibility(childSchema, LeafListSchemaNode.class, dataContainerChild); + return getLeafSetNodeSerializer().serialize((LeafListSchemaNode) childSchema, + (LeafSetNode) dataContainerChild); + } + + private Iterable onLeafNode(Object childSchema, + DataContainerChild dataContainerChild) { + checkSchemaCompatibility(childSchema, LeafSchemaNode.class, dataContainerChild); + Iterable elements = getLeafNodeSerializer().serialize((LeafSchemaNode) childSchema, + (LeafNode) dataContainerChild); + checkOnlyOneSerializedElement(elements, dataContainerChild); + return elements; + } + + private static void checkOnlyOneSerializedElement(Iterable elements, + DataContainerChild dataContainerChild) { + final int size = Iterables.size(elements); + Preconditions.checkArgument(size == 1, + "Unexpected count of elements for entry serialized from: %s, should be 1, was: %s", + dataContainerChild, size); + } + + private Iterable onContainerNode(Object childSchema, + DataContainerChild dataContainerChild) { + checkSchemaCompatibility(childSchema, ContainerSchemaNode.class, dataContainerChild); + + Iterable elements = getContainerNodeSerializer().serialize((ContainerSchemaNode) childSchema, + (ContainerNode) dataContainerChild); + checkOnlyOneSerializedElement(elements, dataContainerChild); + return elements; + } + + private static void checkSchemaCompatibility(Object childSchema, Class containerSchemaNodeClass, + DataContainerChild dataContainerChild) { + Preconditions.checkArgument(containerSchemaNodeClass.isAssignableFrom(childSchema.getClass()), + "Incompatible schema: %s with node: %s, expected: %s", childSchema, dataContainerChild, + containerSchemaNodeClass); + } + + protected abstract FromNormalizedNodeSerializer getContainerNodeSerializer(); + + protected abstract FromNormalizedNodeSerializer, LeafSchemaNode> getLeafNodeSerializer(); + + protected abstract FromNormalizedNodeSerializer, LeafListSchemaNode> getLeafSetNodeSerializer(); + + protected abstract FromNormalizedNodeSerializer getMapNodeSerializer(); + + protected abstract FromNormalizedNodeSerializer getChoiceNodeSerializer(); + + protected abstract FromNormalizedNodeSerializer getAugmentationNodeSerializer(); + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/DomUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/DomUtils.java new file mode 100644 index 0000000000..b8a893e685 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/DomUtils.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom; + +import java.util.List; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils; +import org.opendaylight.yangtools.yang.model.api.TypeDefinition; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import com.google.common.collect.LinkedListMultimap; +import com.google.common.collect.Lists; + +public class DomUtils { + + private DomUtils() { + } + + private static final XmlCodecProvider DEFAULT_XML_VALUE_CODEC_PROVIDER = new XmlCodecProvider() { + + @Override + public TypeDefinitionAwareCodec> codecFor(TypeDefinition baseType) { + return TypeDefinitionAwareCodec.from(baseType); + } + }; + + public static XmlCodecProvider defaultValueCodecProvider() { + return DEFAULT_XML_VALUE_CODEC_PROVIDER; + } + + public static Object parseXmlValue(Element xml, XmlCodecProvider codecProvider, TypeDefinition type) { + TypeDefinitionAwareCodec> codec = codecProvider.codecFor(type); + + String text = xml.getTextContent(); + text = text.trim(); + + Object value; + if (codec != null) { + value = codec.deserialize(text); + } else { + value = text; + } + + return value; + } + + public static void serializeXmlValue(Element itemEl, TypeDefinition> type, XmlCodecProvider codecProvider, Object value) { + XmlDocumentUtils.writeValueByType(itemEl, type, codecProvider, value); + } + + public static LinkedListMultimap mapChildElementsForSingletonNode(Element node) { + List childNodesCollection = Lists.newArrayList(); + NodeList childNodes = node.getChildNodes(); + for (int i = 0; i < childNodes.getLength(); i++) { + if(childNodes.item(i) instanceof Element) { + childNodesCollection.add((Element) childNodes.item(i)); + } + } + + return mapChildElements(childNodesCollection); + } + + public static LinkedListMultimap mapChildElements(Iterable childNodesCollection) { + LinkedListMultimap mappedChildElements = LinkedListMultimap.create(); + + for (Element element : childNodesCollection) { + QName childQName = XmlDocumentUtils.qNameFromElement(element); + mappedChildElements.put(childQName, element); + } + + return mappedChildElements; + } + + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/AugmentationNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/AugmentationNodeDomParser.java new file mode 100644 index 0000000000..0b351f1baf --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/AugmentationNodeDomParser.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.parser; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.AugmentationNodeBaseParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.w3c.dom.Element; + +import com.google.common.base.Preconditions; +import com.google.common.collect.LinkedListMultimap; + +public final class AugmentationNodeDomParser extends AugmentationNodeBaseParser { + + private final XmlCodecProvider codecProvider; + + public AugmentationNodeDomParser(XmlCodecProvider codecProvider) { + this.codecProvider = Preconditions.checkNotNull(codecProvider); + } + + @Override + protected LinkedListMultimap mapChildElements(Iterable elements) { + return DomUtils.mapChildElements(elements); + } + + @Override + protected NodeParserDispatcher getDispatcher() { + return DomNodeDispatcher.getInstance(codecProvider); + } + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ChoiceNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ChoiceNodeDomParser.java new file mode 100644 index 0000000000..5e077207aa --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ChoiceNodeDomParser.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.parser; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ChoiceNodeBaseParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.w3c.dom.Element; + +import com.google.common.base.Preconditions; +import com.google.common.collect.LinkedListMultimap; + +public final class ChoiceNodeDomParser extends ChoiceNodeBaseParser { + + private final XmlCodecProvider codecProvider; + + public ChoiceNodeDomParser(XmlCodecProvider codecProvider) { + this.codecProvider = Preconditions.checkNotNull(codecProvider); + } + + @Override + protected LinkedListMultimap mapChildElements(Iterable xml) { + return DomUtils.mapChildElements(xml); + } + + @Override + protected NodeParserDispatcher getDispatcher() { + return DomNodeDispatcher.getInstance(codecProvider); + } + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ContainerNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ContainerNodeDomParser.java new file mode 100644 index 0000000000..cb31015d84 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ContainerNodeDomParser.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.parser; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.ContainerNodeBaseParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.w3c.dom.Element; + +import com.google.common.base.Preconditions; +import com.google.common.collect.LinkedListMultimap; + +public final class ContainerNodeDomParser extends ContainerNodeBaseParser { + + private final XmlCodecProvider codecProvider; + + public ContainerNodeDomParser(XmlCodecProvider codecProvider) { + this.codecProvider = Preconditions.checkNotNull(codecProvider); + } + + @Override + protected NodeParserDispatcher getDispatcher() { + return DomNodeDispatcher.getInstance(codecProvider); + } + + @Override + protected LinkedListMultimap mapChildElements(Iterable elements) { + return DomUtils.mapChildElementsForSingletonNode(elements.iterator().next()); + } + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomNodeDispatcher.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomNodeDispatcher.java new file mode 100644 index 0000000000..ae725f5eea --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomNodeDispatcher.java @@ -0,0 +1,67 @@ +package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser; + +import org.opendaylight.yangtools.yang.data.api.schema.*; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher; +import org.opendaylight.yangtools.yang.model.api.*; +import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.w3c.dom.Element; + +public class DomNodeDispatcher extends NodeParserDispatcher.BaseNodeParserDispatcher { + + private final ContainerNodeDomParser containerNodeDomParser; + private final LeafNodeDomParser leafNodeDomParser; + private final LeafSetNodeDomParser leafSetNodeDomParser; + private final MapNodeDomParser mapNodeDomParser; + private final ChoiceNodeDomParser choiceNodeDomParser; + private final AugmentationNodeDomParser augmentationNodeDomParser; + + private static DomNodeDispatcher instance = null; + + private DomNodeDispatcher(XmlCodecProvider codecProvider) { + leafNodeDomParser = new LeafNodeDomParser(codecProvider); + containerNodeDomParser = new ContainerNodeDomParser(codecProvider); + leafSetNodeDomParser = new LeafSetNodeDomParser(new LeafSetEntryNodeDomParser(codecProvider)); + mapNodeDomParser = new MapNodeDomParser(new MapEntryNodeDomParser(codecProvider)); + choiceNodeDomParser = new ChoiceNodeDomParser(codecProvider); + augmentationNodeDomParser = new AugmentationNodeDomParser(codecProvider); + } + + @Override + protected ToNormalizedNodeParser getContainerNodeParser() { + return containerNodeDomParser; + } + + @Override + protected ToNormalizedNodeParser, LeafSchemaNode> getLeafNodeParser() { + return leafNodeDomParser; + } + + @Override + protected ToNormalizedNodeParser, LeafListSchemaNode> getLeafSetNodeParser() { + return leafSetNodeDomParser; + } + + @Override + protected ToNormalizedNodeParser getMapNodeParser() { + return mapNodeDomParser; + } + + @Override + protected ToNormalizedNodeParser getChoiceNodeParser() { + return choiceNodeDomParser; + } + + @Override + protected ToNormalizedNodeParser getAugmentationNodeParser() { + return augmentationNodeDomParser; + } + + public static NodeParserDispatcher getInstance(XmlCodecProvider codecProvider) { + if (instance == null) { + instance = new DomNodeDispatcher(codecProvider); + } + return instance; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafNodeDomParser.java new file mode 100644 index 0000000000..723bc8186f --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafNodeDomParser.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.parser; + +import com.google.common.base.Preconditions; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafNodeBaseParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.w3c.dom.Element; + +public class LeafNodeDomParser extends LeafNodeBaseParser { + + private final XmlCodecProvider codecProvider; + + public LeafNodeDomParser(XmlCodecProvider codecProvider) { + this.codecProvider = Preconditions.checkNotNull(codecProvider); + } + + @Override + protected Object parseLeaf(Element xmlElement, LeafSchemaNode schema) { + return DomUtils.parseXmlValue(xmlElement, codecProvider, schema.getType()); + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetEntryNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetEntryNodeDomParser.java new file mode 100644 index 0000000000..b048049ae6 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetEntryNodeDomParser.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.parser; + +import com.google.common.base.Preconditions; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetEntryNodeBaseParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.w3c.dom.Element; + +public class LeafSetEntryNodeDomParser extends LeafSetEntryNodeBaseParser { + + private final XmlCodecProvider codecProvider; + + public LeafSetEntryNodeDomParser(XmlCodecProvider codecProvider) { + this.codecProvider = Preconditions.checkNotNull(codecProvider); + } + + @Override + protected Object parseLeafListEntry(Element xmlElement, LeafListSchemaNode schema) { + return DomUtils.parseXmlValue(xmlElement, codecProvider, schema.getType()); + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetNodeDomParser.java new file mode 100644 index 0000000000..8a771aac9c --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetNodeDomParser.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.parser; + +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetNodeBaseParser; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.w3c.dom.Element; + +public class LeafSetNodeDomParser extends LeafSetNodeBaseParser { + + private final LeafSetEntryNodeDomParser leafSetEntryNodeBaseParser; + + public LeafSetNodeDomParser(LeafSetEntryNodeDomParser leafSetEntryNodeBaseParser) { + this.leafSetEntryNodeBaseParser = leafSetEntryNodeBaseParser; + } + + @Override + protected ToNormalizedNodeParser, LeafListSchemaNode> getLeafSetEntryNodeBaseParser() { + return leafSetEntryNodeBaseParser; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapEntryNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapEntryNodeDomParser.java new file mode 100644 index 0000000000..b52176059f --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapEntryNodeDomParser.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.parser; + +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.MapEntryNodeBaseParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.w3c.dom.Element; + +import com.google.common.base.Preconditions; +import com.google.common.collect.LinkedListMultimap; + +public final class MapEntryNodeDomParser extends MapEntryNodeBaseParser { + + private final XmlCodecProvider codecProvider; + + public MapEntryNodeDomParser(XmlCodecProvider codecProvider) { + this.codecProvider = Preconditions.checkNotNull(codecProvider); + } + + @Override + protected LinkedListMultimap mapChildElements(Iterable elements) { + return DomUtils.mapChildElementsForSingletonNode(elements.iterator().next()); + } + + @Override + protected NodeParserDispatcher getDispatcher() { + return DomNodeDispatcher.getInstance(codecProvider); + } + + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapNodeDomParser.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapNodeDomParser.java new file mode 100644 index 0000000000..1549269aaf --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapNodeDomParser.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.parser; + +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.MapNodeBaseParser; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.w3c.dom.Element; + +public final class MapNodeDomParser extends MapNodeBaseParser { + + private final MapEntryNodeDomParser mapEntryParser; + + public MapNodeDomParser(MapEntryNodeDomParser mapEntryParser) { + this.mapEntryParser = mapEntryParser; + } + + @Override + protected ToNormalizedNodeParser getMapEntryNodeDomParser() { + return mapEntryParser; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/AugmentationNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/AugmentationNodeDomSerializer.java new file mode 100644 index 0000000000..fbffc03abb --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/AugmentationNodeDomSerializer.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.AugmentationNodeBaseSerializer; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher; +import org.w3c.dom.Element; + +import com.google.common.base.Preconditions; + +public class AugmentationNodeDomSerializer extends + AugmentationNodeBaseSerializer { + + private final NodeSerializerDispatcher dispatcher; + + public AugmentationNodeDomSerializer(NodeSerializerDispatcher dispatcher) { + this.dispatcher = Preconditions.checkNotNull(dispatcher); + } + + @Override + protected NodeSerializerDispatcher getNodeDispatcher() { + return dispatcher; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ChoiceNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ChoiceNodeDomSerializer.java new file mode 100644 index 0000000000..1db6a8b663 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ChoiceNodeDomSerializer.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ChoiceNodeBaseSerializer; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher; +import org.w3c.dom.Element; + +import com.google.common.base.Preconditions; + +public class ChoiceNodeDomSerializer extends ChoiceNodeBaseSerializer { + private final NodeSerializerDispatcher dispatcher; + + public ChoiceNodeDomSerializer(final NodeSerializerDispatcher dispatcher) { + this.dispatcher = Preconditions.checkNotNull(dispatcher); + } + + @Override + protected NodeSerializerDispatcher getNodeDispatcher() { + return dispatcher; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ContainerNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ContainerNodeDomSerializer.java new file mode 100644 index 0000000000..c5641a038a --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ContainerNodeDomSerializer.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import java.util.Collections; + +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.ContainerNodeBaseSerializer; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.google.common.base.Preconditions; + +public class ContainerNodeDomSerializer extends + ContainerNodeBaseSerializer { + + private final Document doc; + private final NodeSerializerDispatcher dispatcher; + + public ContainerNodeDomSerializer(final Document doc, final NodeSerializerDispatcher dispatcher) { + this.doc = Preconditions.checkNotNull(doc); + this.dispatcher = Preconditions.checkNotNull(dispatcher); + } + + @Override + public Iterable serialize(ContainerSchemaNode schema, ContainerNode containerNode) { + Element itemEl = XmlDocumentUtils.createElementFor(doc, containerNode); + + for (Element element : super.serialize(schema, containerNode)) { + itemEl.appendChild(element); + } + return Collections.singletonList(itemEl); + } + + @Override + protected NodeSerializerDispatcher getNodeDispatcher() { + return dispatcher; + } + +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomNodeSerializerDispatcher.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomNodeSerializerDispatcher.java new file mode 100644 index 0000000000..9dee6026dc --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomNodeSerializerDispatcher.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; + +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; + +final class DomNodeSerializerDispatcher extends NodeSerializerDispatcher.BaseNodeSerializerDispatcher { + private static final Cache dispatcherCache = + CacheBuilder.newBuilder().weakKeys().build(); + + private final FromNormalizedNodeSerializer containerSerializer; + private final FromNormalizedNodeSerializer choiceSerializer; + private final FromNormalizedNodeSerializer augmentSerializer; + private final FromNormalizedNodeSerializer, LeafSchemaNode> leafNodeSerializer; + private final FromNormalizedNodeSerializer, LeafListSchemaNode> leafSetSerializer; + private final FromNormalizedNodeSerializer mapNodeSerializer; + + DomNodeSerializerDispatcher(Document doc, XmlCodecProvider codecProvider) { + containerSerializer = new ContainerNodeDomSerializer(doc, this); + choiceSerializer = new ChoiceNodeDomSerializer(this); + augmentSerializer = new AugmentationNodeDomSerializer(this); + leafNodeSerializer = new LeafNodeDomSerializer(doc, codecProvider); + leafSetSerializer = new LeafSetNodeDomSerializer(new LeafSetEntryNodeDomSerializer(doc, codecProvider)); + mapNodeSerializer = new MapNodeDomSerializer(new MapEntryNodeDomSerializer(doc, this)); + } + + // FIXME: Callers should really grow a proper (per-document) lifecycle and not rely on this + @Deprecated + static DomNodeSerializerDispatcher getInstance(final Document doc, final XmlCodecProvider codecProvider) { + // DOM does not allow to add elements to one document from another, so maintain a cache + // on a per-document case. + try { + return dispatcherCache.get(doc, new Callable() { + @Override + public DomNodeSerializerDispatcher call() { + return new DomNodeSerializerDispatcher(doc, codecProvider); + } + }); + } catch (ExecutionException e) { + throw new IllegalStateException("Failed to instantiated a dispatcher", e); + } + } + + @Override + protected FromNormalizedNodeSerializer getContainerNodeSerializer() { + return containerSerializer; + } + + @Override + protected FromNormalizedNodeSerializer, LeafSchemaNode> getLeafNodeSerializer() { + return leafNodeSerializer; + } + + @Override + protected FromNormalizedNodeSerializer, LeafListSchemaNode> getLeafSetNodeSerializer() { + return leafSetSerializer; + } + + @Override + protected FromNormalizedNodeSerializer getMapNodeSerializer() { + return mapNodeSerializer; + } + + @Override + protected FromNormalizedNodeSerializer getChoiceNodeSerializer() { + return choiceSerializer; + } + + @Override + protected FromNormalizedNodeSerializer getAugmentationNodeSerializer() { + return augmentSerializer; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafNodeDomSerializer.java new file mode 100644 index 0000000000..acdb7eb738 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafNodeDomSerializer.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import com.google.common.base.Preconditions; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafNodeBaseSerializer; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class LeafNodeDomSerializer extends LeafNodeBaseSerializer { + + private final Document doc; + private final XmlCodecProvider codecProvider; + + public LeafNodeDomSerializer(Document doc, XmlCodecProvider codecProvider) { + this.doc = Preconditions.checkNotNull(doc); + this.codecProvider = Preconditions.checkNotNull(codecProvider); + } + + @Override + protected Element serializeLeaf(LeafSchemaNode schema, LeafNode node) { + Element itemEl = XmlDocumentUtils.createElementFor(doc, node); + DomUtils.serializeXmlValue(itemEl, schema.getType(), codecProvider, node.getValue()); + + return itemEl; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetEntryNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetEntryNodeDomSerializer.java new file mode 100644 index 0000000000..98908cca54 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetEntryNodeDomSerializer.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import com.google.common.base.Preconditions; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlCodecProvider; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetEntryNodeBaseSerializer; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +public class LeafSetEntryNodeDomSerializer extends + LeafSetEntryNodeBaseSerializer { + + private final Document doc; + private final XmlCodecProvider codecProvider; + + public LeafSetEntryNodeDomSerializer(Document doc, XmlCodecProvider codecProvider) { + this.doc = Preconditions.checkNotNull(doc); + this.codecProvider = Preconditions.checkNotNull(codecProvider); + } + + @Override + protected Element serializeLeaf(LeafListSchemaNode schema, LeafSetEntryNode node) { + Element itemEl = XmlDocumentUtils.createElementFor(doc, node); + + DomUtils.serializeXmlValue(itemEl, schema.getType(), codecProvider, node.getValue()); + + return itemEl; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetNodeDomSerializer.java new file mode 100644 index 0000000000..ae49d68aa5 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetNodeDomSerializer.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetNodeBaseSerializer; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.w3c.dom.Element; + +public class LeafSetNodeDomSerializer extends + LeafSetNodeBaseSerializer { + + private final FromNormalizedNodeSerializer, LeafListSchemaNode> leafSetEntryNodeSerializer; + + public LeafSetNodeDomSerializer(LeafSetEntryNodeDomSerializer leafSetEntryNodeSerializer) { + this.leafSetEntryNodeSerializer = leafSetEntryNodeSerializer; + } + + @Override + protected FromNormalizedNodeSerializer, LeafListSchemaNode> getLeafSetEntryNodeSerializer() { + return leafSetEntryNodeSerializer; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapEntryNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapEntryNodeDomSerializer.java new file mode 100644 index 0000000000..5e65dd8d89 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapEntryNodeDomSerializer.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import java.util.Collections; + +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.MapEntryNodeBaseSerializer; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import com.google.common.base.Preconditions; + +public class MapEntryNodeDomSerializer extends + MapEntryNodeBaseSerializer { + + private final Document doc; + private final NodeSerializerDispatcher dispatcher; + + public MapEntryNodeDomSerializer(final Document doc, final NodeSerializerDispatcher dispatcher) { + this.doc = Preconditions.checkNotNull(doc); + this.dispatcher = Preconditions.checkNotNull(dispatcher); + } + + @Override + public Iterable serialize(ListSchemaNode schema, MapEntryNode node) { + Element itemEl = XmlDocumentUtils.createElementFor(doc, node); + + for (Element element : super.serialize(schema, node)) { + itemEl.appendChild(element); + } + + return Collections.singletonList(itemEl); + } + + @Override + protected NodeSerializerDispatcher getNodeDispatcher() { + return dispatcher; + } +} diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapNodeDomSerializer.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapNodeDomSerializer.java new file mode 100644 index 0000000000..d1486f0d70 --- /dev/null +++ b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapNodeDomSerializer.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.MapNodeBaseSerializer; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.w3c.dom.Element; + +public class MapNodeDomSerializer extends MapNodeBaseSerializer { + + private final FromNormalizedNodeSerializer mapEntrySerializer; + + public MapNodeDomSerializer(MapEntryNodeDomSerializer mapEntrySerializer) { + this.mapEntrySerializer = mapEntrySerializer; + } + + @Override + protected FromNormalizedNodeSerializer getMapEntryNodeDomSerializer() { + return mapEntrySerializer; + } +} diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedDataBuilderTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedDataBuilderTest.java index 60b93cef80..5cea3b84dd 100644 --- a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedDataBuilderTest.java +++ b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedDataBuilderTest.java @@ -7,54 +7,57 @@ */ package org.opendaylight.yangtools.yang.data.impl.schema; -import com.google.common.base.Function; -import com.google.common.base.Preconditions; -import com.google.common.collect.Collections2; -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; +import java.io.InputStream; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Set; + import org.junit.Before; import org.junit.Test; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; -import org.opendaylight.yangtools.yang.data.api.schema.*; +import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafNode; +import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode; +import org.opendaylight.yangtools.yang.data.api.schema.MapNode; import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeSchemaAwareBuilder; import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeSchemaAwareBuilder; -import org.opendaylight.yangtools.yang.model.api.*; +import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.xml.sax.SAXException; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.*; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import java.io.IOException; -import java.io.InputStream; -import java.io.StringWriter; -import java.net.URI; -import java.util.Collections; -import java.util.List; -import java.util.Set; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; public class NormalizedDataBuilderTest { private ContainerSchemaNode containerNode; private SchemaContext schema; - SchemaContext parseTestSchema() { + SchemaContext parseTestSchema(String... yangPath) { YangParserImpl yangParserImpl = new YangParserImpl(); - Set modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs()); + Set modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs(yangPath)); return yangParserImpl.resolveSchemaContext(modules); } - List getTestYangs() { + List getTestYangs(String... yangPaths) { - return Lists.newArrayList(Collections2.transform(Lists.newArrayList("test.yang"), + return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths), new Function() { @Override public InputStream apply(String input) { @@ -67,126 +70,125 @@ public class NormalizedDataBuilderTest { @Before public void setUp() throws Exception { - schema = parseTestSchema(); + schema = parseTestSchema("test.yang"); containerNode = (ContainerSchemaNode) getSchemaNode(schema, "test", "container"); } @Test public void testSchemaUnaware() throws Exception { // Container - DataContainerNodeBuilder builder = Builders.containerBuilder().withNodeIdentifier( - getNodeIdentifier("container")); + DataContainerNodeBuilder builder = Builders + .containerBuilder().withNodeIdentifier(getNodeIdentifier("container")); // leaf - LeafNode leafChild = Builders.leafBuilder() - .withNodeIdentifier(getNodeIdentifier("leaf")).withValue("String").build(); + LeafNode leafChild = Builders. leafBuilder().withNodeIdentifier(getNodeIdentifier("leaf")) + .withValue("String").build(); builder.withChild(leafChild); // leafList - LeafSetNode leafList = Builders.leafSetBuilder() + LeafSetNode leafList = Builders + . leafSetBuilder() .withNodeIdentifier(getNodeIdentifier("leaf")) .withChildValue(1) - .withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(getNodeWithValueIdentifier("leaf", 3)).withValue(3).build()) + .withChild( + Builders. leafSetEntryBuilder() + .withNodeIdentifier(getNodeWithValueIdentifier("leaf", 3)).withValue(3).build()) .build(); builder.withChild(leafList); // list - MapEntryNode listChild1 = Builders.mapEntryBuilder() - .withChild( - Builders.leafBuilder() - .withNodeIdentifier(getNodeIdentifier("uint32InList")).withValue(1).build()) + MapEntryNode listChild1 = Builders + .mapEntryBuilder() .withChild( - Builders.containerBuilder().withNodeIdentifier( - getNodeIdentifier("containerInList")) - .build()) + Builders. leafBuilder().withNodeIdentifier(getNodeIdentifier("uint32InList")) + .withValue(1).build()) + .withChild(Builders.containerBuilder().withNodeIdentifier(getNodeIdentifier("containerInList")).build()) .withNodeIdentifier( new InstanceIdentifier.NodeIdentifierWithPredicates(getNodeIdentifier("list").getNodeType(), Collections.singletonMap(getNodeIdentifier("uint32InList").getNodeType(), (Object) 1))) .build(); - MapNode list = Builders.mapBuilder().withChild(listChild1).withNodeIdentifier(getNodeIdentifier("list")).build(); + MapNode list = Builders.mapBuilder().withChild(listChild1).withNodeIdentifier(getNodeIdentifier("list")) + .build(); builder.withChild(list); - AugmentationNode augmentation = Builders.augmentationBuilder() - .withNodeIdentifier(new InstanceIdentifier.AugmentationIdentifier(null, Sets.newHashSet(getQName("augmentUint32")))) + AugmentationNode augmentation = Builders + .augmentationBuilder() + .withNodeIdentifier( + new InstanceIdentifier.AugmentationIdentifier(null, Sets.newHashSet(getQName("augmentUint32")))) .withChild( - Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")).withValue(11).build()) - .build(); + Builders. leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")) + .withValue(11).build()).build(); builder.withChild(augmentation); - // This works without schema (adding child from augment as a direct child) - builder.withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")).withValue(11).build()); - - System.out.println(builder.build()); + // This works without schema (adding child from augment as a direct + // child) + builder.withChild(Builders. leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")) + .withValue(11).build()); } @Test public void testSchemaAware() throws Exception { - DataContainerNodeBuilder builder = Builders.containerBuilder(containerNode); + DataContainerNodeBuilder builder = Builders + .containerBuilder(containerNode); LeafSchemaNode schemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "uint32"); - LeafNode leafChild = Builders.leafBuilder(schemaNode) - .withValue("String").build(); + LeafNode leafChild = Builders. leafBuilder(schemaNode).withValue("String").build(); builder.withChild(leafChild); LeafListSchemaNode leafListSchemaNode = (LeafListSchemaNode) getSchemaNode(schema, "test", "leafList"); - LeafSetNode leafList = Builders.leafSetBuilder(leafListSchemaNode) - .withChildValue(1) - .withChild(Builders.leafSetEntryBuilder(leafListSchemaNode).withValue(3).build()) - .build(); + LeafSetNode leafList = Builders. leafSetBuilder(leafListSchemaNode).withChildValue(1) + .withChild(Builders. leafSetEntryBuilder(leafListSchemaNode).withValue(3).build()).build(); builder.withChild(leafList); ListSchemaNode listSchema = (ListSchemaNode) getSchemaNode(schema, "test", "list"); LeafSchemaNode uint32InListSchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "uint32InList"); - ContainerSchemaNode containerInListSchemaNode = (ContainerSchemaNode) getSchemaNode(schema, "test", "containerInList"); + ContainerSchemaNode containerInListSchemaNode = (ContainerSchemaNode) getSchemaNode(schema, "test", + "containerInList"); MapEntryNode listChild1 = Builders.mapEntryBuilder(listSchema) - .withChild( - Builders.leafBuilder(uint32InListSchemaNode).withValue(1).build()) - .withChild( - Builders.containerBuilder(containerInListSchemaNode).build()) - .build(); + .withChild(Builders. leafBuilder(uint32InListSchemaNode).withValue(1).build()) + .withChild(Builders.containerBuilder(containerInListSchemaNode).build()).build(); MapNode list = ImmutableMapNodeSchemaAwareBuilder.create(listSchema).withChild(listChild1).build(); builder.withChild(list); LeafSchemaNode augmentUint32SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentUint32"); - AugmentationSchema augmentationSchema = getAugmentationSchemaForChild(containerNode, augmentUint32SchemaNode.getQName()); + AugmentationSchema augmentationSchema = getAugmentationSchemaForChild(containerNode, + augmentUint32SchemaNode.getQName()); - AugmentationNode augmentation = Builders.augmentationBuilder(augmentationSchema).withChild( - Builders.leafBuilder(augmentUint32SchemaNode).withValue(11).build()) - .build(); + AugmentationNode augmentation = Builders.augmentationBuilder(augmentationSchema) + .withChild(Builders.leafBuilder(augmentUint32SchemaNode).withValue(11).build()).build(); builder.withChild(augmentation); // This should fail with schema, since the leaf comes from augmentation -// builder.withChild(ImmutableLeafNodeSchemaAwareBuilder.get(augmentUint32SchemaNode).withValue(11).build()); + // builder.withChild(ImmutableLeafNodeSchemaAwareBuilder.get(augmentUint32SchemaNode).withValue(11).build()); LeafSchemaNode augumentString1SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentString1"); LeafSchemaNode augumentString2SchemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "augmentString2"); ChoiceNode choice1SchemaNode = (ChoiceNode) getSchemaNode(schema, "test", "choice"); - org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode choice = ImmutableChoiceNodeSchemaAwareBuilder.create(choice1SchemaNode) - .withChild(Builders.leafBuilder(augumentString1SchemaNode).withValue("case1") - .build()) - // This should fail, since child node belongs to different case -// .withChild(Builders.leafBuilder(augumentString2SchemaNode).withValue("case2") -// .build()) + org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode choice = ImmutableChoiceNodeSchemaAwareBuilder + .create(choice1SchemaNode) + .withChild(Builders. leafBuilder(augumentString1SchemaNode).withValue("case1").build()) + // This should fail, since child node belongs to different case + // .withChild(Builders.leafBuilder(augumentString2SchemaNode).withValue("case2") + // .build()) .build(); -; builder.withChild(choice); + ; + builder.withChild(choice); // This should fail, child from case -// builder.withChild(Builders.leafBuilder(augumentString1SchemaNode).withValue("case1") -// .build()); - - System.out.println(builder.build()); + // builder.withChild(Builders.leafBuilder(augumentString1SchemaNode).withValue("case1") + // .build()); } private AugmentationSchema getAugmentationSchemaForChild(ContainerSchemaNode containerNode, QName qName) { for (AugmentationSchema augmentationSchema : containerNode.getAvailableAugmentations()) { - if(augmentationSchema.getDataChildByName(qName) != null) { + if (augmentationSchema.getDataChildByName(qName) != null) { return augmentationSchema; } } @@ -202,92 +204,37 @@ public class NormalizedDataBuilderTest { return new QName(URI.create(namespace), localName); } - private InstanceIdentifier.NodeWithValue getNodeWithValueIdentifier(QName q, Object value) { - return new InstanceIdentifier.NodeWithValue(q, value); - } - private InstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName) { return new InstanceIdentifier.NodeIdentifier(getQName(localName)); } - private InstanceIdentifier.NodeIdentifier getNodeIdentifier(QName q) { - return new InstanceIdentifier.NodeIdentifier(q); - } - - private Document loadDocument(String xmlPath) throws Exception { - InputStream resourceAsStream = getClass().getResourceAsStream(xmlPath); - - Document currentConfigElement = readXmlToDocument(resourceAsStream); - Preconditions.checkNotNull(currentConfigElement); - return currentConfigElement; - } - - private static final DocumentBuilderFactory BUILDERFACTORY; - - static { - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - factory.setNamespaceAware(true); - factory.setCoalescing(true); - factory.setIgnoringElementContentWhitespace(true); - factory.setIgnoringComments(true); - BUILDERFACTORY = factory; - } - - private Document readXmlToDocument(InputStream xmlContent) throws IOException, SAXException { - DocumentBuilder dBuilder; - try { - dBuilder = BUILDERFACTORY.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - throw new RuntimeException("Failed to parse XML document", e); - } - Document doc = dBuilder.parse(xmlContent); - - doc.getDocumentElement().normalize(); - return doc; - } - - public static String toString(Element xml) { - try { - Transformer transformer = TransformerFactory.newInstance().newTransformer(); - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - - StreamResult result = new StreamResult(new StringWriter()); - DOMSource source = new DOMSource(xml); - transformer.transform(source, result); - - return result.getWriter().toString(); - } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) { - throw new RuntimeException("Unable to serialize xml element " + xml, e); - } - } - - DataSchemaNode getSchemaNode(SchemaContext context, String moduleName, String childNodeName) { + public static DataSchemaNode getSchemaNode(SchemaContext context, String moduleName, String childNodeName) { for (Module module : context.getModules()) { if (module.getName().equals(moduleName)) { DataSchemaNode found = findChildNode(module.getChildNodes(), childNodeName); - Preconditions.checkState(found!=null, "Unable to find %s", childNodeName); + Preconditions.checkState(found != null, "Unable to find %s", childNodeName); return found; } } throw new IllegalStateException("Unable to find child node " + childNodeName); } - DataSchemaNode findChildNode(Set children, String name) { + static DataSchemaNode findChildNode(Set children, String name) { List containers = Lists.newArrayList(); for (DataSchemaNode dataSchemaNode : children) { if (dataSchemaNode.getQName().getLocalName().equals(name)) return dataSchemaNode; - if(dataSchemaNode instanceof DataNodeContainer) { + if (dataSchemaNode instanceof DataNodeContainer) { containers.add((DataNodeContainer) dataSchemaNode); - } else if(dataSchemaNode instanceof ChoiceNode) { + } else if (dataSchemaNode instanceof ChoiceNode) { containers.addAll(((ChoiceNode) dataSchemaNode).getCases()); } } for (DataNodeContainer container : containers) { DataSchemaNode retVal = findChildNode(container.getChildNodes(), name); - if(retVal != null) { + if (retVal != null) { return retVal; } } diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java new file mode 100644 index 0000000000..a22993225b --- /dev/null +++ b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2013 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.schema.transform.dom.serializer; + +import java.io.IOException; +import java.io.InputStream; +import java.io.StringWriter; +import java.net.URI; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Set; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode; +import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.Builders; +import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedDataBuilderTest; +import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.NodeSerializerDispatcher; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils; +import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.ContainerNodeDomParser; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; +import org.opendaylight.yangtools.yang.model.api.SchemaContext; +import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.xml.sax.SAXException; + +import com.google.common.base.Function; +import com.google.common.base.Preconditions; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; + +@RunWith(Parameterized.class) +public class NormalizedNodeXmlTranslationTest { + private static final Logger logger = LoggerFactory.getLogger(NormalizedNodeXmlTranslationTest.class); + + @Parameterized.Parameters() + public static Collection data() { + return Arrays.asList(new Object[][]{ + {"augment_choice_hell.yang", "augment_choice_hell_ok.xml", augmentChoiceHell()}, + {"augment_choice_hell.yang", "augment_choice_hell_ok2.xml", null}, + {"test.yang", "simple.xml", null}, + {"test.yang", "simple2.xml", null} + }); + } + + public static final String NAMESPACE = "urn:opendaylight:params:xml:ns:yang:controller:test"; + private static Date revision; + static { + try { + revision = new SimpleDateFormat("yyyy-MM-dd").parse("2014-03-13"); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + private static ContainerNode augmentChoiceHell() { + + DataContainerNodeBuilder b = Builders.containerBuilder(); + b.withNodeIdentifier(getNodeIdentifier("container")); + + b.withChild( + Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch2")) + .withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c2Leaf")).withValue("2").build()) + .withChild( + Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("c2DeepChoice")) + .withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c2DeepChoiceCase1Leaf2")).withValue("2").build()) + .build() + ) + .build() + ); + + b.withChild( + Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch3")).withChild( + Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c3Leaf")).withValue("3").build()) + .build()); + + b.withChild( + Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("augLeaf")).withChild( + Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("augLeaf")).withValue("augment").build()) + .build()); + + b.withChild( + Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("ch")).withChild( + Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("ch")) + .withChild( + Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c1Leaf")).withValue("1").build()) + .withChild( + Builders.augmentationBuilder().withNodeIdentifier(getAugmentIdentifier("c1Leaf_AnotherAugment", "deepChoice")) + .withChild( + Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("c1Leaf_AnotherAugment")).withValue("1").build()) + .withChild( + Builders.choiceBuilder().withNodeIdentifier(getNodeIdentifier("deepChoice")) + .withChild( + Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("deepLeafc1")).withValue("1").build() + ).build() + ).build() + ).build() + ).build()); + + return b.build(); + } + + private static InstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName) { + return new InstanceIdentifier.NodeIdentifier(new QName(URI.create(NAMESPACE), revision, localName)); + } + + public static InstanceIdentifier.AugmentationIdentifier getAugmentIdentifier(String... childNames) { + Set qn = Sets.newHashSet(); + + for (String childName : childNames) { + qn.add(getNodeIdentifier(childName).getNodeType()); + } + + return new InstanceIdentifier.AugmentationIdentifier(null, qn); + } + + public NormalizedNodeXmlTranslationTest(String yangPath, String xmlPath, ContainerNode expectedNode) { + this.schema = parseTestSchema(yangPath); + this.xmlPath = xmlPath; + this.containerNode = (ContainerSchemaNode) NormalizedDataBuilderTest.getSchemaNode(schema, "test", "container"); + this.expectedNode = expectedNode; + } + + private final ContainerNode expectedNode; + private final ContainerSchemaNode containerNode; + private final SchemaContext schema; + private final String xmlPath; + + + SchemaContext parseTestSchema(String... yangPath) { + YangParserImpl yangParserImpl = new YangParserImpl(); + Set modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs(yangPath)); + return yangParserImpl.resolveSchemaContext(modules); + } + + List getTestYangs(String... yangPaths) { + + return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths), + new Function() { + @Override + public InputStream apply(String input) { + InputStream resourceAsStream = NormalizedDataBuilderTest.class.getResourceAsStream(input); + Preconditions.checkNotNull(resourceAsStream, "File %s was null", resourceAsStream); + return resourceAsStream; + } + })); + } + + @Test + public void testTranslation() throws Exception { + Document doc = loadDocument(xmlPath); + + ContainerNode built = new ContainerNodeDomParser(DomUtils.defaultValueCodecProvider()).parse( + Collections.singletonList(doc.getDocumentElement()), containerNode); + + if (expectedNode != null) + junit.framework.Assert.assertEquals(expectedNode, built); + + logger.info("{}", built); + + final Document newDoc = XmlDocumentUtils.getDocument(); + final NodeSerializerDispatcher dispatcher = new DomNodeSerializerDispatcher(newDoc, DomUtils.defaultValueCodecProvider()); + + Iterable els = new ContainerNodeDomSerializer(newDoc, + dispatcher).serialize(containerNode, built); + + Element el = els.iterator().next(); + + Assert.assertEquals(toString(doc.getDocumentElement()).replaceAll("\\s*", ""), + toString(el).replaceAll("\\s*", "")); + } + + + private Document loadDocument(String xmlPath) throws Exception { + InputStream resourceAsStream = NormalizedDataBuilderTest.class.getResourceAsStream(xmlPath); + + Document currentConfigElement = readXmlToDocument(resourceAsStream); + Preconditions.checkNotNull(currentConfigElement); + return currentConfigElement; + } + + private static final DocumentBuilderFactory BUILDERFACTORY; + + static { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + factory.setCoalescing(true); + factory.setIgnoringElementContentWhitespace(true); + factory.setIgnoringComments(true); + BUILDERFACTORY = factory; + } + + private Document readXmlToDocument(InputStream xmlContent) throws IOException, SAXException { + DocumentBuilder dBuilder; + try { + dBuilder = BUILDERFACTORY.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new RuntimeException("Failed to parse XML document", e); + } + Document doc = dBuilder.parse(xmlContent); + + doc.getDocumentElement().normalize(); + return doc; + } + + public static String toString(Element xml) { + try { + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + + StreamResult result = new StreamResult(new StringWriter()); + DOMSource source = new DOMSource(xml); + transformer.transform(source, result); + + return result.getWriter().toString(); + } catch (IllegalArgumentException | TransformerFactoryConfigurationError | TransformerException e) { + throw new RuntimeException("Unable to serialize xml element " + xml, e); + } + } +} diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang new file mode 100644 index 0000000000..c2a57f667c --- /dev/null +++ b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang @@ -0,0 +1,109 @@ +// vi: set smarttab et sw=4 tabstop=4: +module test { + yang-version 1; + namespace "urn:opendaylight:params:xml:ns:yang:controller:test"; + prefix "test"; + + organization "Cisco Systems, Inc."; + + revision "2014-3-13" { + description + "Initial revision"; + } + + + container container { + choice ch2{} + choice ch3{ + case c3 { + leaf c3Leaf { + type string; + } + } + } + } + + augment "/container/" { + leaf augLeaf { + type string; + } + } + + augment "/container/" { + choice ch{} + } + + augment "/container/ch/" { + case c1 { + leaf c1Leaf { + type string; + } + } + + leaf c12 { + type string; + } + } + augment "/container/ch/c1/" { + leaf c1Leaf_AnotherAugment { + type string; + } + + choice deepChoice{} + } + + augment "/container/ch3/" { + case c32 { + leaf c32Leaf { + type string; + } + } + + leaf c34LeafS { + type string; + } + } + + + augment "/container/ch/c1/deepChoice/" { + case deepCase1 { + leaf deepLeafc1 { + type string; + } + } + case deepCase2 { + leaf deepLeafc2 { + type string; + } + } + } + + augment "/container/ch2/" { + case c2 { + leaf c2Leaf { + type string; + } + + choice c2DeepChoice { + case c2DeepChoiceCase1 { + leaf c2DeepChoiceCase1Leaf1 { + type string; + } + } + case c2DeepChoiceCase2 { + leaf c2DeepChoiceCase1Leaf2 { + type string; + } + } + } + } + } + + augment "/container/ch2/" { + leaf c22Leaf { + type string; + } + } + + +} \ No newline at end of file diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok.xml new file mode 100644 index 0000000000..c5a581cecc --- /dev/null +++ b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok.xml @@ -0,0 +1,15 @@ + + + 2 + 2 + + + 3 + + augment + + 1 + 1 + 1 + + \ No newline at end of file diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok2.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok2.xml new file mode 100644 index 0000000000..8332d218bc --- /dev/null +++ b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok2.xml @@ -0,0 +1,12 @@ + + + 2 + + 3 + + augment + + 1 + 1 + 1 + \ No newline at end of file diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple.xml index 014688e567..579f79ae57 100644 --- a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple.xml +++ b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple.xml @@ -12,6 +12,8 @@ 32 16 + augmentInList + augmentInListCase1 2 @@ -19,19 +21,25 @@ 32 16 + + augmentInListCase2 3 - 999 - choice1Case1 + 41 + + deep choice2Case1 + 999 + + \ No newline at end of file diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple2.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple2.xml new file mode 100644 index 0000000000..9bb8aff059 --- /dev/null +++ b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple2.xml @@ -0,0 +1,43 @@ + + choice1Case1 + + 41 + + deep + + + aug1 + + + + aug2 + + + 66 + + + + + + 661 + + + 662 + + + + + + 6621 + + + + + + aug3 + + + + + + \ No newline at end of file diff --git a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/test.yang b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/test.yang index 4ad6e78625..ef9e8d67a7 100644 --- a/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/test.yang +++ b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/test.yang @@ -72,7 +72,33 @@ module test { type string; } - uses listGroup; + uses listGroup { + augment "list/" { + leaf stringAugmentedToList{ + type string; + } + + choice choiceInList { + case caseInList1 { + leaf stringAugmentedToListInCase1 { + type string; + } + } + case caseInList2 { + leaf stringAugmentedToListInCase2 { + type string; + } + } + } + } + } + + list directList { + leaf stringInDirectList { + type string; + } + } + uses innerContainerGrouping; choice choice{} @@ -101,6 +127,12 @@ module test { } } + augment "/container/directList/" { + leaf augmentedString { + type uint32; + } + } + augment "/container/choice/" { case test-identity-augment { when "/container/identityRef = 'test-identity'"; @@ -124,6 +156,32 @@ module test { } } + augment "/container/choice/test-identity-augment/" { + + choice augmentedChoiceInCase { + + case augmentedCaseInAugmentedChoice { + leaf stringInAugmentedCaseInAugmentedChoice { + type string; + } + } + + case augmentedCaseInAugmentedChoice2 { + leaf stringInAugmentedCaseInAugmentedChoice2 { + type string; + } + } + } + } + + augment "/container/choice/test-identity-augment/augmentedChoiceInCase/" { + case augmentedCaseInAugmentedChoiceFromAugment { + leaf stringInAugmentedCaseInAugmentedChoiceFromAugment { + type string; + } + } + } + augment "/container/choice2/" { case test-identity-augment { when "/container/identityRef = 'test-identity'"; @@ -144,6 +202,21 @@ module test { } + augment "/container/choice2/test-identity-augment2/augmentedList/" { + + container augmentedContainerInAugmentedListInAugmentedCase { + leaf-list leafInAugmentedContainerInAugmentedListInAugmentedCase { + type uint32; + } + } + + list augmentedListInAugmentedListInAugmentedCase { + leaf-list leafInAugmentedListInAugmentedListInAugmentedCase { + type uint32; + } + } + } + identity test-identity {} identity test-identity2 { base test-identity; -- 2.36.6