Merge changes Iaac9f7e2,I9c336a30
authorTony Tkacik <ttkacik@cisco.com>
Tue, 8 Apr 2014 11:44:55 +0000 (11:44 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 8 Apr 2014 11:44:55 +0000 (11:44 +0000)
* changes:
  Fix for Bug 364.
  Fix for Bug 394.

314 files changed:
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.xtend
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/CodecMapping.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/InstanceIdentifierCodecImpl.xtend
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGenerator.xtend
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTest.java
code-generator/binding-java-api-generator/src/test/resources/compilation/bug586/foo.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/DocumentationGeneratorImpl.java
code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/DocGenTest.java
code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/wadl/generator/maven/WadlGenTest.java
code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/config.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/netty.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/odl-protocol-framework-cfg.yang [new file with mode: 0644]
common/concepts/pom.xml [moved from concepts/pom.xml with 91% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/AbstractListenerRegistration.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/AbstractListenerRegistration.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/AbstractObjectRegistration.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/AbstractObjectRegistration.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/AbstractRegistration.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/AbstractRegistration.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Builder.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Builder.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/ClassBasedPropertyBuilder.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/ClassBasedPropertyBuilder.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Codec.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Codec.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/CompositeObjectRegistration.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/CompositeObjectRegistration.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Delegator.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Delegator.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Deserializer.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Deserializer.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Identifiable.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Identifiable.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Identifier.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Identifier.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Immutable.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Immutable.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/InvertibleTransformator.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/InvertibleTransformator.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/ListenerRegistration.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/ListenerRegistration.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Mutable.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Mutable.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/MutationBehaviour.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/MutationBehaviour.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Namespace.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Namespace.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/ObjectRegistration.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/ObjectRegistration.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/OrderedSet.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/OrderedSet.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Path.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Path.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/ProductAwareBuilder.java [new file with mode: 0644]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Registration.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Registration.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Serializer.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Serializer.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/Transformator.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/Transformator.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/ValueWrapper.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/ValueWrapper.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/util/ClassLoaderUtils.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/util/ClassLoaderUtils.java with 100% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/util/Immutables.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/util/Immutables.java with 83% similarity]
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/util/ListenerRegistry.java [moved from concepts/src/main/java/org/opendaylight/yangtools/concepts/util/ListenerRegistry.java with 100% similarity]
common/mockito-configuration/pom.xml [moved from mockito-configuration/pom.xml with 96% similarity]
common/mockito-configuration/src/main/java/org/mockito/configuration/ArgumentsExtractorVerifier.java [moved from mockito-configuration/src/main/java/org/mockito/configuration/ArgumentsExtractorVerifier.java with 100% similarity]
common/mockito-configuration/src/main/java/org/mockito/configuration/MockitoConfiguration.java [moved from mockito-configuration/src/main/java/org/mockito/configuration/MockitoConfiguration.java with 100% similarity]
common/mockito-configuration/src/main/java/org/mockito/configuration/ThrowsUnstubbedMethodException.java [moved from mockito-configuration/src/main/java/org/mockito/configuration/ThrowsUnstubbedMethodException.java with 100% similarity]
common/mockito-configuration/src/main/java/org/mockito/configuration/UnstubbedMethodException.java [moved from mockito-configuration/src/main/java/org/mockito/configuration/UnstubbedMethodException.java with 100% similarity]
common/mockito-configuration/src/main/resources/logback-test.xml [moved from mockito-configuration/src/main/resources/logback-test.xml with 100% similarity]
common/mockito-configuration/src/test/java/org/mockito/configuration/ArgumentsExtractorVerifierTest.java [moved from mockito-configuration/src/test/java/org/mockito/configuration/ArgumentsExtractorVerifierTest.java with 100% similarity]
common/mockito-configuration/src/test/java/org/mockito/configuration/DefaultAnswerTest.java [moved from mockito-configuration/src/test/java/org/mockito/configuration/DefaultAnswerTest.java with 100% similarity]
common/object-cache-api/pom.xml [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/ObjectCache.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/ObjectCacheFactory.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/impl/StaticObjectCacheBinder.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/impl/package-info.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/package-info.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/AbstractObjectCache.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/AbstractObjectCacheBinder.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/IObjectCacheFactory.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/NoopObjectCache.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/ObjectCacheFactoryBinder.java [new file with mode: 0644]
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/package-info.java [new file with mode: 0644]
common/object-cache-guava/pom.xml [new file with mode: 0644]
common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/guava/GuavaObjectCache.java [new file with mode: 0644]
common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/guava/GuavaObjectCacheFactory.java [new file with mode: 0644]
common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/guava/package-info.java [new file with mode: 0644]
common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/impl/StaticObjectCacheBinder.java [new file with mode: 0644]
common/object-cache-noop/pom.xml [new file with mode: 0644]
common/object-cache-noop/src/main/java/org/opendaylight/yangtools/objcache/impl/StaticObjectCacheBinder.java [new file with mode: 0644]
common/pom.xml [new file with mode: 0644]
integration-test/bug527-test-model/pom.xml [new file with mode: 0644]
integration-test/bug527-test-model/src/main/yang/bar.yang [new file with mode: 0644]
integration-test/bug527-test-model/src/main/yang/foo.yang [new file with mode: 0644]
integration-test/pom.xml
pom.xml
restconf/pom.xml
restconf/restconf-client-api/pom.xml
restconf/restconf-client-impl/src/main/java/org/opendaylight/yangtools/restconf/client/BindingToRestRpc.java
restconf/restconf-client-impl/src/main/java/org/opendaylight/yangtools/restconf/client/RestListenableEventStreamContext.java
restconf/restconf-common/pom.xml
restconf/restconf-jaxrs-api/pom.xml
restconf/restconf-util/pom.xml
restconf/restconf-util/src/main/java/org/opendaylight/yangtools/restconf/utils/RestconfUtils.java
restconf/restconf-util/src/test/java/org/opendaylight/yangtools/restconf/utils/Bug527Test.java [new file with mode: 0644]
restconf/restconf-util/src/test/resources/topology-bug527.xml [new file with mode: 0644]
websocket/websocket-client/pom.xml
websocket/websocket-client/src/test/java/org/opendaylight/yangtools/websocket/WebSocketClientTest.java
websocket/websocket-client/src/test/java/org/opendaylight/yangtools/websocket/server/WebSocketServer.java
yang/pom.xml
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/InstanceIdentifierTest.java
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeChildKey.java
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeKey.java
yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/QName.java
yang/yang-common/src/test/java/org/opendaylight/yangtools/yang/common/QNameTest.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/MutableCompositeNode.java [changed mode: 0755->0644]
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/MutableNode.java [changed mode: 0755->0644]
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/MutableSimpleNode.java [changed mode: 0755->0644]
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/NodeModification.java [changed mode: 0755->0644]
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/NodeModificationBuilder.java [changed mode: 0755->0644]
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/ContainerNode.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafNode.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/LeafSetEntryNode.java
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/schema/MapEntryNode.java
yang/yang-data-impl/pom.xml
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/CompositeNodeModificationTOImpl.java [changed mode: 0755->0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/SimpleNodeModificationTOImpl.java [changed mode: 0755->0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/Builders.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/ImmutableNodes.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedNodeUtils.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/AttributesBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/CollectionNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/DataContainerNodeAttrBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/DataContainerNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/ListNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/NormalizedNodeAttrBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/NormalizedNodeContainerBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeAttrBuilder.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableNormalizedNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableAugmentationNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableChoiceNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableContainerNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableContainerNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapEntryNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/valid/DataNodeContainerValidator.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerAttrNode.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedAttrNode.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializerFactory.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParserFactory.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/AugmentationSchemaProxy.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/SchemaUtils.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/AugmentationNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/BaseDispatcherParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ChoiceNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/ContainerNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetEntryNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/LeafSetNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapEntryNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/MapNodeBaseParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/parser/NodeParserDispatcher.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/AugmentationNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/BaseDispatcherSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ChoiceNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/ContainerNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetEntryNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/LeafSetNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapEntryNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/MapNodeBaseSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/base/serializer/NodeSerializerDispatcher.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/DomUtils.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/AugmentationNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ChoiceNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/ContainerNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomToNormalizedNodeParserFactory.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetEntryNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/LeafSetNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapEntryNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/MapNodeDomParser.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/AugmentationNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ChoiceNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/ContainerNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomFromNormalizedNodeSerializerFactory.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetEntryNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/LeafSetNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapEntryNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/MapNodeDomSerializer.java [new file with mode: 0644]
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/LazyNodeToNodeMapTest.java [changed mode: 0755->0644]
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedDataBuilderTest.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/test/NormalizedNodeUtilsTest.java [new file with mode: 0644]
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/NormalizedNodeXmlTranslationTest.java [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell.yang [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/augment_choice_hell_ok2.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple.xml
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple2.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple_xml_with_attributes.xml [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/test.yang
yang/yang-data-json/pom.xml [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/AugmentationNodeCnSnParser.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/ChoiceNodeCnSnParser.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/CnSnToNormalizedNodeParserFactory.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/ContainerNodeCnSnParser.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/LeafNodeCnSnParser.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/LeafSetEntryNodeCnSnParser.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/LeafSetNodeCnSnParser.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/MapEntryNodeCnSnParser.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/MapNodeCnSnParser.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/AugmentationNodeCnSnSerializer.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/ChoiceNodeCnSnSerializer.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/CnSnFromNormalizedNodeSerializerFactory.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/ContainerNodeCnSnSerializer.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/LeafNodeCnSnSerializer.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/LeafSetEntryNodeCnSnSerializer.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/LeafSetNodeCnSnSerializer.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/MapEntryNodeCnSnSerializer.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/MapNodeCnSnSerializer.java [new file with mode: 0644]
yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/json/CnSnToNormalizedNodesUtils.java [new file with mode: 0644]
yang/yang-data-json/src/test/java/org/opendaylight/yangtools/yang/data/json/schema/TestUtils.java [new file with mode: 0644]
yang/yang-data-json/src/test/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/ParseCnSnStructToNormalizedStructTest.java [new file with mode: 0644]
yang/yang-data-json/src/test/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/SerializeNormalizedStructToCnSnStructTest.java [new file with mode: 0644]
yang/yang-data-json/src/test/resources/cnsn-to-normalized-node/json/simple-container.json [new file with mode: 0644]
yang/yang-data-json/src/test/resources/cnsn-to-normalized-node/yang/augment-simple-container.yang [new file with mode: 0644]
yang/yang-data-json/src/test/resources/cnsn-to-normalized-node/yang/simple-container.yang [new file with mode: 0644]
yang/yang-data-operations/pom.xml [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/AbstractContainerNodeModification.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/AugmentationNodeModification.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/ChoiceNodeModification.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/ContainerNodeModification.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/DataModificationException.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/DataOperations.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/LeafNodeModification.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/LeafSetNodeModification.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/MapEntryNodeModification.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/MapNodeModification.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/Modification.java [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/OperationStack.java [new file with mode: 0644]
yang/yang-data-operations/src/test/java/org/opendaylight/yangtools/yang/data/operations/YangDataOperationsNegativeTest.java [new file with mode: 0644]
yang/yang-data-operations/src/test/java/org/opendaylight/yangtools/yang/data/operations/YangDataOperationsTest.java [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/schemas/test.yang [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_choiceModificationMultipleCasesReferenced/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_choiceModificationMultipleCasesReferenced/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_createContainerActualPresent/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_createContainerActualPresent/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_deleteContainerActualMissing/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_noneContainerActualMissing/defaultOperation.txt [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_noneContainerActualMissing/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_createLeafActualPresent/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_createLeafActualPresent/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_deleteLeafActualMissing/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_deleteLeafActualMissing/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_createLeafActualPresent/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_createLeafActualPresent/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_deleteLeafActualMissing/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_deleteLeafActualMissing/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/listTest_createListActualPresent/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/listTest_createListActualPresent/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/listTest_deleteListActualMissing/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/listTest_deleteListActualMissing/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/listTest_noneListActualMissing/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/listTest_noneListActualMissing/defaultOperation.txt [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls-negative/listTest_noneListActualMissing/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationDifferentCases/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationDifferentCases/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationDifferentCases/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationSameCase/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationSameCase/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationSameCase/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualOneCaseModificationOtherCase/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualOneCaseModificationOtherCase/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualOneCaseModificationOtherCase/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_createContainer/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_createContainer/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_deleteContainer/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_deleteContainer/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_innerContainerContainer/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_innerContainerContainer/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_innerContainerContainer/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_innerLeavesBaseOperationsContainer/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_innerLeavesBaseOperationsContainer/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_innerLeavesBaseOperationsContainer/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/defaultOperation.txt [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_removeContainer/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_removeContainer/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_replaceContainer/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_replaceContainer/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/containerTest_replaceContainer/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/leafListTest/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/leafListTest/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/leafListTest/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/listTest/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/listTest/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/listTest/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/defaultOperation.txt [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/result.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/none_NoChange/current.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/none_NoChange/defaultOperation.txt [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/none_NoChange/merge.xml [new file with mode: 0644]
yang/yang-data-operations/src/test/resources/xmls/none_NoChange/result.xml [new file with mode: 0644]
yang/yang-model-util/pom.xml
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java [new file with mode: 0644]
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.xtend [deleted file]
yang/yang-parser-impl/pom.xml
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserUtils.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserUtils.xtend [deleted file]

index 94d4812cd039f3c5e72b6f46d85f503d51f761fb..2ee88f3678d1d28c99114c6959dffb2c2054d7e3 100644 (file)
@@ -69,7 +69,6 @@ import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder
 import org.opendaylight.yangtools.yang.model.api.ModuleImport
 import org.opendaylight.yangtools.yang.binding.DataContainer
-import org.opendaylight.yangtools.yang.model.api.AugmentationTarget
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil
 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
@@ -80,8 +79,6 @@ import org.opendaylight.yangtools.yang.binding.BindingMapping
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase
 
 import com.google.common.collect.Sets
-import java.net.URI
-import java.util.Date
 
 public class BindingGeneratorImpl implements BindingGenerator {
 
@@ -745,7 +742,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
         if (targetSchemaNode instanceof DataSchemaNode && (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
-            targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
+            targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode, schemaContext);
             if (targetSchemaNode == null) {
                 throw new NullPointerException(
                     "Failed to find target node from grouping in augmentation " + augSchema + " in module " +
@@ -814,228 +811,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
         }
     }
 
-    /**
-     * Utility method which search for original node defined in grouping.
-     */
-    private def DataSchemaNode findOriginal(DataSchemaNode node) {
-        var DataSchemaNode result = findCorrectTargetFromGrouping(node);
-        if (result == null) {
-            result = findCorrectTargetFromAugment(node);
-            if (result != null) {
-                if (result.addedByUses) {
-                    result = findOriginal(result);
-                }
-            }
-        }
-        return result;
-    }
-
-    private def DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node) {
-        if (!node.augmenting) {
-            return null
-        }
-
-        var QName currentName = node.QName
-        var Object currentNode = node
-        var Object parent = node;
-        val tmpPath = new ArrayList<QName>()
-        val tmpTree = new ArrayList<SchemaNode>()
-
-        var AugmentationSchema augment = null;
-        do {
-            val SchemaPath sp = (parent as SchemaNode).path
-            val List<QName> names = sp.path
-            val List<QName> newNames = new ArrayList(names)
-            newNames.remove(newNames.size - 1)
-            val SchemaPath newSp = new SchemaPath(newNames, sp.absolute)
-            parent = findDataSchemaNode(schemaContext, newSp)
-            if (parent instanceof AugmentationTarget) {
-                tmpPath.add(currentName);
-                tmpTree.add(currentNode as SchemaNode)
-                augment = findNodeInAugment((parent as AugmentationTarget).availableAugmentations, currentName);
-                if (augment == null) {
-                    currentName = (parent as DataSchemaNode).QName
-                    currentNode = parent
-                }
-            }
-        } while ((parent as DataSchemaNode).augmenting && augment == null);
-
-        if (augment == null) {
-            return null;
-        } else {
-            Collections.reverse(tmpPath);
-            Collections.reverse(tmpTree);
-            var Object actualParent = augment;
-            var DataSchemaNode result = null;
-            for (name : tmpPath) {
-                if (actualParent instanceof DataNodeContainer) {
-                    result = (actualParent as DataNodeContainer).getDataChildByName(name.localName);
-                    actualParent = (actualParent as DataNodeContainer).getDataChildByName(name.localName);
-                } else {
-                    if (actualParent instanceof ChoiceNode) {
-                        result = (actualParent as ChoiceNode).getCaseNodeByName(name.localName);
-                        actualParent = (actualParent as ChoiceNode).getCaseNodeByName(name.localName);
-                    }
-                }
-            }
-
-            if (result.addedByUses) {
-                result = findCorrectTargetFromAugmentGrouping(result, augment, tmpTree);
-            }
-
-            return result;
-        }
-    }
-
-    private def AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, QName name) {
-        for (augment : augments) {
-            val DataSchemaNode node = augment.getDataChildByName(name);
-            if (node != null) {
-                return augment;
-            }
-        }
-        return null;
-    }
-
-    private def DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node) {
-        if (node.path.path.size == 1) {
-            // uses is under module statement
-            val Module m = findParentModule(schemaContext, node);
-            var DataSchemaNode result = null;
-            for (u : m.uses) {
-                var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path);
-                if (!(targetGrouping instanceof GroupingDefinition)) {
-                    throw new IllegalArgumentException("Failed to generate code for augment in " + u);
-                }
-                var gr = targetGrouping as GroupingDefinition;
-                result = gr.getDataChildByName(node.QName.localName);
-            }
-            if (result == null) {
-                throw new IllegalArgumentException("Failed to generate code for augment")
-            }
-            return result
-        } else {
-            var DataSchemaNode result = null;
-            var QName currentName = node.QName
-            var tmpPath = new ArrayList<QName>()
-            var Object parent = null
-
-            val SchemaPath sp = node.path
-            val List<QName> names = sp.path
-            val List<QName> newNames = new ArrayList(names)
-            newNames.remove(newNames.size - 1)
-            val SchemaPath newSp = new SchemaPath(newNames, sp.absolute)
-            parent = findDataSchemaNode(schemaContext, newSp)
-
-            do {
-                tmpPath.add(currentName);
-                if (parent instanceof DataNodeContainer) {
-                    val dataNodeParent = parent as DataNodeContainer;
-                    for (u : dataNodeParent.uses) {
-                        if (result == null) {
-                            result = getResultFromUses(u, currentName.localName)
-                        }
-                    }
-                }
-                if (result == null) {
-                    currentName = (parent as SchemaNode).QName
-                    if (parent instanceof SchemaNode) {
-                        val SchemaPath nodeSp = (parent as SchemaNode).path
-                        val List<QName> nodeNames = nodeSp.path
-                        val List<QName> nodeNewNames = new ArrayList(nodeNames)
-                        nodeNewNames.remove(nodeNewNames.size - 1)
-                        if (nodeNewNames.empty) {
-                            parent = getParentModule(parent as SchemaNode)
-                        } else {
-                            val SchemaPath nodeNewSp = new SchemaPath(nodeNewNames, nodeSp.absolute)
-                            parent = findDataSchemaNode(schemaContext, nodeNewSp)
-                        }
-                    } else {
-                        throw new IllegalArgumentException("Failed to generate code for augment")
-                    }
-                }
-            } while (result == null && !(parent instanceof Module));
-
-            if (result != null) {
-                result = getTargetNode(tmpPath, result)
-            }
-            return result;
-        }
-    }
-
-    private def DataSchemaNode findCorrectTargetFromAugmentGrouping(DataSchemaNode node, AugmentationSchema parentNode,
-        List<SchemaNode> dataTree) {
-
-        var DataSchemaNode result = null;
-        var QName currentName = node.QName
-        var tmpPath = new ArrayList<QName>()
-        tmpPath.add(currentName)
-        var int i = 1;
-        var Object parent = null
-
-        do {
-            if (dataTree.size < 2 || dataTree.size == i) {
-                parent = parentNode
-            } else {
-                parent = dataTree.get(dataTree.size - (i+1))
-                tmpPath.add((parent as SchemaNode).QName)
-            }
-
-            val dataNodeParent = parent as DataNodeContainer;
-            for (u : dataNodeParent.uses) {
-                if (result == null) {
-                    result = getResultFromUses(u, currentName.localName)
-                }
-            }
-            if (result == null) {
-                i = i + 1
-                currentName = (parent as SchemaNode).QName
-            }
-        } while (result == null);
-
-        if (result != null) {
-            result = getTargetNode(tmpPath, result)
-        }
-        return result;
-    }
-
-    private def getResultFromUses(UsesNode u, String currentName) {
-        var SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, u.groupingPath.path)
-        if (!(targetGrouping instanceof GroupingDefinition)) {
-            throw new IllegalArgumentException("Failed to generate code for augment in " + u)
-        }
-        var gr = targetGrouping as GroupingDefinition
-        return gr.getDataChildByName(currentName)
-    }
-
-    private def getTargetNode(List<QName> tmpPath, DataSchemaNode node) {
-        var DataSchemaNode result = node
-        if (tmpPath.size == 1) {
-            if (result != null && result.addedByUses) {
-                result = findOriginal(result);
-            }
-            return result;
-        } else {
-            var DataSchemaNode newParent = result;
-            Collections.reverse(tmpPath);
-
-            tmpPath.remove(0);
-            for (name : tmpPath) {
-                // searching by local name is must, because node has different namespace in its original location
-                if (newParent instanceof DataNodeContainer) {
-                    newParent = (newParent as DataNodeContainer).getDataChildByName(name.localName);
-                } else {
-                    newParent = (newParent as ChoiceNode).getCaseNodeByName(name.localName);
-                }
-            }
-            if (newParent != null && newParent.addedByUses) {
-                newParent = findOriginal(newParent);
-            }
-            return newParent;
-        }
-    }
-
-
     /**
      * Convenient method to find node added by uses statement.
      */
@@ -1356,7 +1131,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                         var targetSchemaNode = findDataSchemaNode(schemaContext, targetPath)
                         if (targetSchemaNode instanceof DataSchemaNode &&
                             (targetSchemaNode as DataSchemaNode).isAddedByUses()) {
-                            targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode);
+                            targetSchemaNode = findOriginal(targetSchemaNode as DataSchemaNode, schemaContext);
                             if (targetSchemaNode == null) {
                                 throw new NullPointerException(
                                     "Failed to find target node from grouping for augmentation " + augSchema +
@@ -1478,7 +1253,8 @@ public class BindingGeneratorImpl implements BindingGenerator {
      *         <li>true - in other cases</li>
      *         </ul>
      */
-    private def boolean resolveLeafSchemaNodeAsMethod(GeneratedTypeBuilder typeBuilder, LeafSchemaNode leaf) {
+    private def Type resolveLeafSchemaNodeAsMethod(GeneratedTypeBuilder typeBuilder, LeafSchemaNode leaf) {
+        var Type returnType = null;
         if ((leaf !== null) && (typeBuilder !== null)) {
             val leafName = leaf.QName.localName;
             var String leafDesc = leaf.description;
@@ -1490,7 +1266,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
             if (leafName !== null && !leaf.isAddedByUses()) {
                 val TypeDefinition<?> typeDef = leaf.type;
 
-                var Type returnType = null;
                 var GeneratedTOBuilder genTOBuilder;
                 if (typeDef instanceof EnumTypeDefinition) {
                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
@@ -1518,11 +1293,10 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 if (returnType !== null) {
                     val MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType);
                     processContextRefExtension(leaf, getter, parentModule);
-                    return true;
                 }
             }
         }
-        return false;
+        return returnType;
     }
 
     private def void processContextRefExtension(LeafSchemaNode leaf, MethodSignatureBuilder getter, Module module) {
@@ -1581,25 +1355,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return null;
     }
 
-    /**
-     * Converts <code>leaf</code> schema node to property of generated TO
-     * builder.
-     *
-     * @param toBuilder
-     *            generated TO builder to which is <code>leaf</code> added as
-     *            property
-     * @param leaf
-     *            leaf schema node which is added to <code>toBuilder</code> as
-     *            property
-     * @param isReadOnly
-     *            boolean value which says if leaf property is|isn't read only
-     * @return boolean value
-     *         <ul>
-     *         <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf
-     *         name equals null or if leaf is added by <i>uses</i>.</li>
-     *         <li>true - other cases</li>
-     *         </ul>
-     */
     private def boolean resolveLeafSchemaNodeAsProperty(GeneratedTOBuilder toBuilder, LeafSchemaNode leaf,
         boolean isReadOnly, Module module) {
         if ((leaf !== null) && (toBuilder !== null)) {
@@ -1626,22 +1381,49 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 } else {
                     returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
                 }
-
-                if (returnType !== null) {
-                    val propBuilder = toBuilder.addProperty(parseToValidParamName(leafName));
-                    propBuilder.setReadOnly(isReadOnly);
-                    propBuilder.setReturnType(returnType);
-                    propBuilder.setComment(leafDesc);
-                    toBuilder.addEqualsIdentity(propBuilder);
-                    toBuilder.addHashIdentity(propBuilder);
-                    toBuilder.addToStringProperty(propBuilder);
-                    return true;
-                }
+                return resolveLeafSchemaNodeAsProperty(toBuilder, leaf, returnType, isReadOnly)
             }
         }
         return false;
     }
 
+    /**
+     * Converts <code>leaf</code> schema node to property of generated TO
+     * builder.
+     *
+     * @param toBuilder
+     *            generated TO builder to which is <code>leaf</code> added as
+     *            property
+     * @param leaf
+     *            leaf schema node which is added to <code>toBuilder</code> as
+     *            property
+     * @param returnType property type
+     * @param isReadOnly
+     *            boolean value which says if leaf property is|isn't read only
+     * @return boolean value
+     *         <ul>
+     *         <li>false - if <code>leaf</code>, <code>toBuilder</code> or leaf
+     *         name equals null or if leaf is added by <i>uses</i>.</li>
+     *         <li>true - other cases</li>
+     *         </ul>
+     */
+    private def resolveLeafSchemaNodeAsProperty(GeneratedTOBuilder toBuilder, LeafSchemaNode leaf, Type returnType,
+        boolean isReadOnly) {
+        if (returnType == null) {
+            return false;
+        }
+        val leafName = leaf.QName.localName
+        val leafDesc = leaf.description
+        val propBuilder = toBuilder.addProperty(parseToValidParamName(leafName));
+        propBuilder.setReadOnly(isReadOnly);
+        propBuilder.setReturnType(returnType);
+        propBuilder.setComment(leafDesc);
+        toBuilder.addEqualsIdentity(propBuilder);
+        toBuilder.addHashIdentity(propBuilder);
+        toBuilder.addToStringProperty(propBuilder);
+        return true;
+    }
+
     /**
      * Converts <code>node</code> leaf list schema node to getter method of
      * <code>typeBuilder</code>.
@@ -1919,9 +1701,13 @@ public class BindingGeneratorImpl implements BindingGenerator {
         if (schemaNode instanceof LeafSchemaNode) {
             val leaf = schemaNode as LeafSchemaNode;
             val leafName = leaf.QName.localName;
-            resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
+            val Type type = resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
             if (listKeys.contains(leafName)) {
-                resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true, module)
+                if (type == null) {
+                    resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true, module)
+                } else {
+                    resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, type, true)
+                }
             }
         } else if (!schemaNode.addedByUses) {
             if (schemaNode instanceof LeafListSchemaNode) {
@@ -2114,13 +1900,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
         return null
     }
 
-    private def Module getParentModule(SchemaNode node) {
-        val QName qname = node.getPath().getPath().get(0);
-        val URI namespace = qname.getNamespace();
-        val Date revision = qname.getRevision();
-        return schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
-    }
-
     public def getModuleContexts() {
         genCtx;
     }
index a09a3bf926219e8457a2d445aec7738ce6dac360..9a4ce78541f13ed7461bf66153a99a51b2fad3a2 100644 (file)
@@ -32,7 +32,7 @@ public class CodecMapping {
         Field instanceIdField;
         try {
             instanceIdField = obj.getField(INSTANCE_IDENTIFIER_CODEC);
-            if(obj != null) {
+            if (instanceIdField != null) {
                 instanceIdField.set(null, codec);
             }
         } catch (NoSuchFieldException e) {
@@ -42,12 +42,11 @@ public class CodecMapping {
         }
     }
 
-
     public static void setIdentityRefCodec(Class<?> obj,IdentityCodec<?> codec) {
         Field instanceIdField;
         try {
             instanceIdField = obj.getField(IDENTITYREF_CODEC);
-            if(obj != null) {
+            if (instanceIdField != null) {
                 instanceIdField.set(null, codec);
             }
         } catch (NoSuchFieldException e) {
index d563b29de11383ba3200703d2b26a88d7edcc9d5..3396f4e3f8c41857e8a8a9e4f75658cf1ca2e431 100644 (file)
@@ -7,34 +7,33 @@
  */
 package org.opendaylight.yangtools.sal.binding.generator.impl
 
+import com.google.common.collect.ImmutableList
+import java.util.ArrayList
+import java.util.Collections
+import java.util.HashMap
+import java.util.List
+import java.util.Map
+import java.util.WeakHashMap
+import java.util.concurrent.ConcurrentHashMap
+import org.opendaylight.yangtools.yang.binding.Augmentation
+import org.opendaylight.yangtools.yang.binding.DataObject
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier
-import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem
-import org.opendaylight.yangtools.yang.common.QName
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item
-import java.util.Map
-import java.util.WeakHashMap
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.data.api.CompositeNode
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates
-import java.util.ArrayList
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument
+import org.opendaylight.yangtools.yang.data.api.Node
+import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
+import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentifierCodec
 import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec
 import org.opendaylight.yangtools.yang.data.impl.codec.ValueWithQName
-import java.util.HashMap
 import org.slf4j.LoggerFactory
-import java.util.List
-import org.opendaylight.yangtools.yang.binding.DataObject
-import org.opendaylight.yangtools.yang.data.impl.codec.IdentifierCodec
-import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl
-import org.opendaylight.yangtools.yang.data.api.Node
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl
-import org.opendaylight.yangtools.yang.data.api.CompositeNode
-import org.opendaylight.yangtools.yang.binding.Augmentable
-import com.google.common.collect.ImmutableList
-import org.opendaylight.yangtools.yang.binding.Augmentation
-import java.util.concurrent.ConcurrentHashMap
-import org.opendaylight.yangtools.yang.binding.util.BindingReflections
-import java.util.Collections
 
 class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
 
@@ -52,7 +51,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         var Class<?> baType = null
         val biArgs = input.path
         val scannedPath = new ArrayList<QName>(biArgs.size);
-        val baArgs = new ArrayList<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>(biArgs.size)
+        val baArgs = new ArrayList<InstanceIdentifier.PathArgument>(biArgs.size)
         for(biArg : biArgs) {
             scannedPath.add(biArg.nodeType);
             val baArg = deserializePathArgument(biArg,scannedPath)
@@ -71,13 +70,13 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         return ret;
     }
 
-    private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifier argument,List<QName> processedPath) {
+    private def dispatch InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifier argument,List<QName> processedPath) {
         val Class cls = codecRegistry.getClassForPath(processedPath);
         return new Item(cls);
     }
 
 
-    private def dispatch org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifierWithPredicates argument,List<QName> processedPath) {
+    private def dispatch InstanceIdentifier.PathArgument deserializePathArgument(NodeIdentifierWithPredicates argument,List<QName> processedPath) {
         val Class type = codecRegistry.getClassForPath(processedPath);
         val IdentifierCodec codec = codecRegistry.getIdentifierCodecForIdentifiable(type);
         val value = codec.deserialize(argument.toCompositeNode())?.value;
@@ -93,9 +92,9 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         return new CompositeNodeTOImpl(predicates.nodeType,null,values);
     }
 
-    override serialize(InstanceIdentifier input) {
+    override serialize(InstanceIdentifier<?> input) {
         var Class<?> previousAugmentation = null
-        val pathArgs = input.path as List<org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument>
+        val pathArgs = input.path as List<InstanceIdentifier.PathArgument>
         var QName previousQName = null;
         val components = new ArrayList<PathArgument>(pathArgs.size);
         val qnamePath = new ArrayList<QName>(pathArgs.size);
@@ -114,7 +113,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
 
                 previousAugmentation = null;
             } else {
-                previousQName = codecRegistry.getQNameForAugmentation(baArg.type as Class);
+                previousQName = codecRegistry.getQNameForAugmentation(baArg.type as Class<?>);
                 previousAugmentation = baArg.type;
             }
         }
@@ -130,7 +129,7 @@ class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec {
         classToPreviousAugment.get(class1).put(list,augmentation);
     }
 
-    private def dispatch PathArgument serializePathArgument(Item argument, QName previousQname) {
+    private def dispatch PathArgument serializePathArgument(Item<?> argument, QName previousQname) {
         val type = argument.type;
         val qname = BindingReflections.findQName(type);
         if(previousQname == null || (BindingReflections.isAugmentationChild(argument.type))) {
index 93969b798c1a756468189a6568dd8164fcc14fe4..a761f9aa90d47683b65f327034eedde4a2c2e6e0 100644 (file)
@@ -478,8 +478,16 @@ public class LazyGeneratedCodecRegistry implements //
     }
 
     private void tryToCreateCasesCodecs(ChoiceNode schema) {
-        for (ChoiceCaseNode caseNode : schema.getCases()) {
+        for (ChoiceCaseNode choiceCase : schema.getCases()) {
+            ChoiceCaseNode caseNode = choiceCase;
+            if (caseNode.isAddedByUses()) {
+                DataSchemaNode origCaseNode = SchemaContextUtil.findOriginal(caseNode, currentSchema);
+                if (origCaseNode instanceof ChoiceCaseNode) {
+                    caseNode = (ChoiceCaseNode) origCaseNode;
+                }
+            }
             SchemaPath path = caseNode.getPath();
+
             GeneratedTypeBuilder type;
             if (path != null && (type = pathToType.get(path)) != null) {
                 ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
@@ -640,6 +648,7 @@ public class LazyGeneratedCodecRegistry implements //
     private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
             Delegator<BindingCodec> {
         private boolean augmenting;
+        private boolean uses;
         private BindingCodec delegate;
 
         private Set<String> validNames;
@@ -656,6 +665,7 @@ public class LazyGeneratedCodecRegistry implements //
                 validNames.add(qname.getLocalName());
             }
             augmenting = caseNode.isAugmenting();
+            uses = caseNode.isAddedByUses();
         }
 
         public ChoiceCaseCodecImpl() {
@@ -693,7 +703,7 @@ public class LazyGeneratedCodecRegistry implements //
         @Override
         public boolean isAcceptable(Node<?> input) {
             if (input instanceof CompositeNode) {
-                if (augmenting) {
+                if (augmenting && !uses) {
                     return checkAugmenting((CompositeNode) input);
                 } else {
                     return checkLocal((CompositeNode) input);
index 9b3a516cbe6a647b17114e669cbe06b0957869a0..cd5d93a5648b1d187708ad91f4c7bf2fa5c2c1db 100644 (file)
@@ -160,13 +160,10 @@ class TransformerGenerator {
             if (typeSpecBuilder == null) {
                 typeSpecBuilder = pathToType.get(node.path);
             }
-            var schemaNode = typeToSchemaNode.get(ref);
-            if (schemaNode === null) {
-                schemaNode = node;
-            }
+
             checkState(typeSpecBuilder !== null, "Could not find TypeDefinition for %s, $s", inputType.name, node);
             val typeSpec = typeSpecBuilder.toInstance();
-            val newret = generateTransformerFor(inputType, typeSpec, schemaNode);
+            val newret = generateTransformerFor(inputType, typeSpec, node);
             listener.onClassProcessed(inputType);
             return newret as Class<? extends BindingCodec<Map<QName,Object>, Object>>;
         ]
index 3469b716257595690424faf1a48ab28e03bd5804..5f19a4e8f64b1de6b402e9b9869969121bc59ce7 100644 (file)
@@ -48,12 +48,7 @@ public class CompilationTest extends BaseCompilationTest {
         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "list-gen");
         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
 
-        final List<File> sourceFiles = getSourceFiles("/compilation/list-gen");
-        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
-        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
-        final List<Type> types = bindingGenerator.generateTypes(context);
-        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
-        generator.generateToFile(sourcesOutputDir);
+        generateTestSources("/compilation/list-gen", sourcesOutputDir);
 
         // Test if all sources are generated
         File parent = new File(sourcesOutputDir, NS_TEST);
@@ -123,12 +118,7 @@ public class CompilationTest extends BaseCompilationTest {
         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-under-uses");
         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
 
-        final List<File> sourceFiles = getSourceFiles("/compilation/augment-under-uses");
-        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
-        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
-        final List<Type> types = bindingGenerator.generateTypes(context);
-        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
-        generator.generateToFile(sourcesOutputDir);
+        generateTestSources("/compilation/augment-under-uses", sourcesOutputDir);
 
         // Test if all sources were generated from 'module foo'
         File parent = new File(sourcesOutputDir, NS_FOO);
@@ -233,12 +223,7 @@ public class CompilationTest extends BaseCompilationTest {
         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "aug-of-aug");
         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
 
-        final List<File> sourceFiles = getSourceFiles("/compilation/augment-of-augment");
-        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
-        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
-        final List<Type> types = bindingGenerator.generateTypes(context);
-        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
-        generator.generateToFile(sourcesOutputDir);
+        generateTestSources("/compilation/augment-of-augment", sourcesOutputDir);
 
         // Test if all sources were generated from 'module foo'
         File parent = new File(sourcesOutputDir, NS_FOO);
@@ -378,12 +363,7 @@ public class CompilationTest extends BaseCompilationTest {
         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "leaf-return-types");
         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
 
-        final List<File> sourceFiles = getSourceFiles("/compilation/leaf-return-types");
-        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
-        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
-        final List<Type> types = bindingGenerator.generateTypes(context);
-        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
-        generator.generateToFile(sourcesOutputDir);
+        generateTestSources("/compilation/leaf-return-types", sourcesOutputDir);
 
         File parent = new File(sourcesOutputDir, NS_TEST);
         assertTrue(new File(parent, "TestData.java").exists());
@@ -449,12 +429,7 @@ public class CompilationTest extends BaseCompilationTest {
         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "context-reference");
         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
 
-        final List<File> sourceFiles = getSourceFiles("/compilation/context-reference");
-        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
-        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
-        final List<Type> types = bindingGenerator.generateTypes(context);
-        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
-        generator.generateToFile(sourcesOutputDir);
+        generateTestSources("/compilation/context-reference", sourcesOutputDir);
 
         // Test if all sources are generated
         File fooParent = new File(sourcesOutputDir, NS_FOO);
@@ -505,12 +480,7 @@ public class CompilationTest extends BaseCompilationTest {
         final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "yang");
         assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
 
-        final List<File> sourceFiles = getSourceFiles("/yang");
-        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
-        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
-        final List<Type> types = bindingGenerator.generateTypes(context);
-        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
-        generator.generateToFile(sourcesOutputDir);
+        generateTestSources("/yang", sourcesOutputDir);
 
         // Test if sources are compilable
         testCompilation(sourcesOutputDir, compiledOutputDir);
@@ -518,6 +488,29 @@ public class CompilationTest extends BaseCompilationTest {
         cleanUp(sourcesOutputDir, compiledOutputDir);
     }
 
+    @Test
+    public void bug586Test() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug586");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug586");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/bug586", sourcesOutputDir);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+        final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
+        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+        generator.generateToFile(sourcesOutputDir);
+    }
 
     private void testReturnTypeIdentityref(Class<?> clazz, String methodName, String returnTypeStr) throws Exception {
         Method method;
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/bug586/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/bug586/foo.yang
new file mode 100644 (file)
index 0000000..fcf4891
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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
+ */
+module foo {
+    yang-version 1;
+    namespace "urn:yang.foo";
+    prefix "foo";
+
+    revision "2014-03-28" {
+    }
+
+
+    container services {
+        list service {
+            key "permission";
+
+            leaf permission {
+                type enumeration {
+                    enum permit;
+                    enum deny;
+                }
+            }
+        }
+    }
+
+}
index 2a65150480d3a61c19c017a7a509b5d6479f2c6e..3b35de381e017df6de77db10784db10a081fd19b 100644 (file)
@@ -35,7 +35,6 @@ import org.slf4j.LoggerFactory
 import org.slf4j.Logger
 import java.util.List
 import org.opendaylight.yangtools.yang.common.QName
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition
 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
 import java.util.ArrayList
 import java.util.Map
@@ -54,6 +53,9 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifie
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode\rimport java.util.HashMap
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
+import org.opendaylight.yangtools.yang.model.api.UsesNode
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget
 
 class GeneratorImpl {
 
@@ -62,7 +64,8 @@ class GeneratorImpl {
     static val Logger LOG = LoggerFactory.getLogger(GeneratorImpl)
     static val BuildContext CTX = new DefaultBuildContext();
     var Module currentModule;
-
+    val Map<String, String> imports = new HashMap();
+    var SchemaContext ctx;
 
     def generate(SchemaContext context, File targetPath, Set<Module> modulesToGen) throws IOException {
         path = targetPath;
@@ -76,6 +79,8 @@ class GeneratorImpl {
 
     def generateDocumentation(Module module, SchemaContext ctx) {
         val destination = new File(path, '''«module.name».html''')
+        this.ctx = ctx;
+        module.imports.forEach[importModule | this.imports.put(importModule.prefix, importModule.moduleName)]
         try {
             val fw = new OutputStreamWriter(CTX.newFileOutputStream(destination))
             val bw = new BufferedWriter(fw)
@@ -104,6 +109,16 @@ class GeneratorImpl {
     def body(Module module, SchemaContext ctx) '''
         Â«header(module)»
 
+        Â«typeDefinitionsSummary(module)»
+        Â«identitiesSummary(module)»
+        Â«groupingsSummary(module)»
+        Â«augmentationsSummary(module, ctx)»
+        Â«objectsSummary(module)»
+        Â«notificationsSummary(module)»
+        Â«rpcsSummary(module)»
+        Â«extensionsSummary(module)»
+        Â«featuresSummary(module)»
+
         Â«typeDefinitions(module)»
 
         Â«identities(module)»
@@ -127,6 +142,34 @@ class GeneratorImpl {
     '''
 
 
+    private def typeDefinitionsSummary(Module module) {
+        val Set<TypeDefinition<?>> typedefs = module.typeDefinitions
+        if (typedefs.empty) {
+            return '';
+        }
+        return '''
+        <div>
+            <h3>Type Definitions Summary</h3>
+            <table>
+                <tr>
+                    <th>Name</th>
+                    <th>Description</th>
+                </tr>
+                Â«FOR typedef : typedefs»
+                <tr>
+                    <td>
+                    Â«anchorLink(typedef.QName.localName, strong(typedef.QName.localName))»
+                    </td>
+                    <td>
+                    Â«typedef.description»
+                    </td>
+                </tr>
+                Â«ENDFOR»
+            </table>
+        </div>
+        '''
+    }
+
     def typeDefinitions(Module module) {
         val Set<TypeDefinition<?>> typedefs = module.typeDefinitions
         if (typedefs.empty) {
@@ -137,7 +180,7 @@ class GeneratorImpl {
             <ul>
             Â«FOR typedef : typedefs»
                 <li>
-                    Â«strong("typedef " + typedef.QName.localName)»
+                    <h3 id="«typedef.QName.localName»">«typedef.QName.localName»</h3>
                     <ul>
                     Â«typedef.descAndRefLi»
                     Â«typedef.restrictions»
@@ -157,10 +200,10 @@ class GeneratorImpl {
             <ul>
             Â«FOR identity : module.identities»
                 <li>
-                    Â«strong("identity " + identity.QName.localName)»
+                    <h3 id="«identity.QName.localName»">«identity.QName.localName»</h3>
                     <ul>
                     Â«identity.descAndRefLi»
-                    Â«IF identity.baseIdentity != null»
+                    Â«IF identity.baseIdentity !== null»
                         Â«listItem("base", identity.baseIdentity.QName.localName)»
                     Â«ENDIF»
                     </ul>
@@ -170,6 +213,31 @@ class GeneratorImpl {
         '''
     }
 
+    private def identitiesSummary(Module module) {
+        if (module.identities.empty) {
+            return '';
+        }
+        return '''
+        <h3>Identities Summary</h3>
+        <table>
+            <tr>
+                <th>Name</th>
+                <th>Description</th>
+            </tr>
+            Â«FOR identity : module.identities»
+            <tr>
+                <td>
+                Â«anchorLink(identity.QName.localName, strong(identity.QName.localName))»
+                </td>
+                <td>
+                Â«identity.description»
+                </td>
+            </tr>
+            Â«ENDFOR»
+        </table>
+        '''
+    }
+
     private def groupings(Module module) {
         if (module.groupings.empty) {
             return '';
@@ -179,9 +247,12 @@ class GeneratorImpl {
             <ul>
             Â«FOR grouping : module.groupings»
                 <li>
-                    Â«strong("grouping " + grouping.QName.localName)»
+                    <h3 id="«grouping.QName.localName»">«grouping.QName.localName»</h3>
                     <ul>
                         Â«grouping.descAndRefLi»
+                        Â«FOR childNode : grouping.childNodes»
+                            Â«childNode.printSchemaNodeInfo»
+                        Â«ENDFOR»
                     </ul>
                 </li>
             Â«ENDFOR»
@@ -189,6 +260,31 @@ class GeneratorImpl {
         '''
     }
 
+    private def groupingsSummary(Module module) {
+        if (module.groupings.empty) {
+            return '';
+        }
+        return '''
+        <h3>Groupings Summary</h3>
+        <table>
+            <tr>
+                <th>Name</th>
+                <th>Description</th>
+            </tr>
+            Â«FOR grouping : module.groupings»
+            <tr>
+                <td>
+                Â«anchorLink(grouping.QName.localName, strong(grouping.QName.localName))»
+                </td>
+                <td>
+                Â«grouping.description»
+                </td>
+            </tr>
+            Â«ENDFOR»
+        </table>
+        '''
+    }
+
     def dataStore(Module module) {
         if (module.childNodes.empty) {
             return '';
@@ -209,7 +305,8 @@ class GeneratorImpl {
             <ul>
             Â«FOR augment : module.augmentations»
                 <li>
-                    <h3>Target [«schemaPathAsRestconfPath(module, augment.targetPath, context)»]</h3>
+                    <h3 id="«schemaPathToString(module, augment.targetPath, context, augment)»">
+                    Target [«typeAnchorLink(augment.targetPath,schemaPathToString(module, augment.targetPath, context, augment))»]</h3>
                     Â«augment.description»
                     Â«IF augment.reference !== null»
                         Reference Â«augment.reference»
@@ -217,13 +314,41 @@ class GeneratorImpl {
                     Â«IF augment.whenCondition !== null»
                         When Â«augment.whenCondition.toString»
                     Â«ENDIF»
-                    Â«augment.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»
+                    Â«FOR childNode : augment.childNodes»
+                        Â«childNode.printSchemaNodeInfo»
+                    Â«ENDFOR»
                 </li>
             Â«ENDFOR»
             </ul>
         '''
     }
 
+    private def augmentationsSummary(Module module, SchemaContext context) {
+        if (module.augmentations.empty) {
+            return '';
+        }
+        return '''
+        <h3>Augmentations Summary</h3>
+        <table>
+            <tr>
+                <th>Target</th>
+                <th>Description</th>
+            </tr>
+            Â«FOR augment : module.augmentations»
+            <tr>
+                <td>
+                Â«anchorLink(schemaPathToString(module, augment.targetPath, context, augment),
+                strong(schemaPathToString(module, augment.targetPath, context, augment)))»
+                </td>
+                <td>
+                Â«augment.description»
+                </td>
+            </tr>
+            Â«ENDFOR»
+        </table>
+        '''
+    }
+
     def notifications(Module module) {
         val Set<NotificationDefinition> notificationdefs = module.notifications
         if (notificationdefs.empty) {
@@ -234,10 +359,37 @@ class GeneratorImpl {
             <h2>Notifications</h2>
             Â«FOR notificationdef : notificationdefs»
 
-                <h3>«notificationdef.nodeName»</h3>
+                <h3 id="«notificationdef.path.schemaPathToId»">«notificationdef.nodeName»</h3>
                     Â«notificationdef.descAndRef»
-                    Â«notificationdef.childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»
+                    Â«FOR childNode : notificationdef.childNodes»
+                        Â«childNode.printSchemaNodeInfo»
+                    Â«ENDFOR»
+            Â«ENDFOR»
+        '''
+    }
+
+    private def notificationsSummary(Module module) {
+        if (module.notifications.empty) {
+            return '';
+        }
+        return '''
+        <h3>Notifications Summary</h3>
+        <table>
+            <tr>
+                <th>Name</th>
+                <th>Description</th>
+            </tr>
+            Â«FOR notification : module.notifications»
+            <tr>
+                <td>
+                Â«anchorLink(notification.path.schemaPathToId, strong(notification.QName.localName))»
+                </td>
+                <td>
+                Â«notification.description»
+                </td>
+            </tr>
             Â«ENDFOR»
+        </table>
         '''
     }
 
@@ -249,13 +401,42 @@ class GeneratorImpl {
         return '''
             <h2>RPC Definitions</h2>
             Â«FOR rpc : module.rpcs»
-                <h3>«rpc.nodeName»</h3>
-                    Â«rpc.rpcInfo(InstanceIdentifier.builder().node(rpc.QName).toInstance())»
+                <h3 id="«rpc.QName.localName»">«rpc.nodeName»</h3>
+                    <ul>
+                        Â«rpc.descAndRefLi»
+                        Â«rpc.input.printSchemaNodeInfo»
+                        Â«rpc.output.printSchemaNodeInfo»
+                    </ul>
             Â«ENDFOR»
             </ul>
         '''
     }
 
+    private def rpcsSummary(Module module) {
+        if (module.rpcs.empty) {
+            return '';
+        }
+        return '''
+        <h3>RPCs Summary</h3>
+        <table>
+            <tr>
+                <th>Name</th>
+                <th>Description</th>
+            </tr>
+            Â«FOR rpc : module.rpcs»
+            <tr>
+                <td>
+                Â«anchorLink(rpc.QName.localName, strong(rpc.QName.localName))»
+                </td>
+                <td>
+                Â«rpc.description»
+                </td>
+            </tr>
+            Â«ENDFOR»
+        </table>
+        '''
+    }
+
     def extensions(Module module) {
         if (module.extensionSchemaNodes.empty) {
             return '';
@@ -264,13 +445,38 @@ class GeneratorImpl {
             <h2>Extensions</h2>
             Â«FOR ext : module.extensionSchemaNodes»
                 <li>
-                    <h3>«ext.nodeName»</h3>
+                    <h3 id="«ext.QName.localName»">«ext.nodeName»</h3>
                 </li>
                 Â«extensionInfo(ext)»
             Â«ENDFOR»
         '''
     }
 
+    private def extensionsSummary(Module module) {
+        if (module.extensionSchemaNodes.empty) {
+            return '';
+        }
+        return '''
+        <h3>Extensions Summary</h3>
+        <table>
+            <tr>
+                <th>Name</th>
+                <th>Description</th>
+            </tr>
+            Â«FOR ext : module.extensionSchemaNodes»
+            <tr>
+                <td>
+                Â«anchorLink(ext.QName.localName, strong(ext.QName.localName))»
+                </td>
+                <td>
+                Â«ext.description»
+                </td>
+            </tr>
+            Â«ENDFOR»
+        </table>
+        '''
+    }
+
     def features(Module module) {
         if (module.features.empty) {
             return '';
@@ -281,7 +487,7 @@ class GeneratorImpl {
             <ul>
             Â«FOR feature : module.features»
                 <li>
-                    Â«strong("feature " + feature.QName.localName)»
+                    <h3 id="«feature.QName.localName»">«feature.QName.localName»</h3>
                     <ul>
                         Â«feature.descAndRefLi»
                     </ul>
@@ -291,24 +497,96 @@ class GeneratorImpl {
         '''
     }
 
-    def header(Module module) '''
+    private def featuresSummary(Module module) {
+        if (module.features.empty) {
+            return '';
+        }
+        return '''
+        <h3>Features Summary</h3>
+        <table>
+            <tr>
+                <th>Name</th>
+                <th>Description</th>
+            </tr>
+            Â«FOR feature : module.features»
+            <tr>
+                <td>
+                Â«anchorLink(feature.QName.localName, strong(feature.QName.localName))»
+                </td>
+                <td>
+                Â«feature.description»
+                </td>
+            </tr>
+            Â«ENDFOR»
+        </table>
+        '''
+    }
+
+    private def objectsSummary(Module module) {
+        if (module.childNodes.empty) {
+            return '';
+        }
+        return '''
+        <h3>Child Nodes Summary</h3>
+        <table>
+            <tr>
+                <th>Name</th>
+                <th>Description</th>
+            </tr>
+            Â«FOR childNode : module.childNodes»
+            <tr>
+                <td>
+                Â«anchorLink(childNode.QName.localName, strong(childNode.QName.localName))»
+                </td>
+                <td>
+                Â«childNode.description»
+                </td>
+            </tr>
+            Â«ENDFOR»
+        </table>
+        '''
+    }
+
+    def header(Module module)
+    '''
         <h1>«module.name»</h1>
 
         <h2>Base Information</h2>
-        <dl>
-            <dt>Prefix</dt>
-            <dd>«pre(module.prefix)»</dd>
-            <dt>Namespace</dt>
-            <dd>«pre(module.namespace.toString)»</dd>
-            <dt>Revision</dt>
-            <dd>«pre(REVISION_FORMAT.format(module.revision))»</dd>
-
-            Â«FOR imp : module.imports BEFORE "<dt>Imports</dt>" Â»
-                <dd>«code(imp.prefix)» = Â«code(imp.moduleName)»</dd>
-            Â«ENDFOR»
-        </dl>
+        <table>
+            <tr>
+                <td>«strong("prefix")»</td>
+                <td>«module.prefix»</td>
+            </tr>
+            <tr>
+                <td>«strong("namespace")»</td>
+                <td>«module.namespace»</td>
+            </tr>
+            <tr>
+                <td>«strong("revision")»</td>
+                <td>«REVISION_FORMAT.format(module.revision)»</td>
+            </tr>
+            <tr>
+                <td>«strong("description")»</td>
+                <td>«module.description»</td>
+            </tr>
+            <tr>
+                <td>«strong("yang-version")»</td>
+                <td>«module.yangVersion»</td>
+            </tr>
+            <tr>
+                Â«FOR imp : module.imports BEFORE '''<td>«strong("imports")»</td><td>''' AFTER '''</td>'''»
+                    Â«imp.prefix»:«imp.moduleName»«IF imp.revision !== null» Â«REVISION_FORMAT.format(imp.revision)»«ENDIF»;
+                Â«ENDFOR»
+            </tr>
+        </table>
     '''
 
+    def CharSequence schemaPathToId(SchemaPath path) {
+        if(path !== null) {
+            return '''«FOR qName : path.path SEPARATOR "/"»«qName.localName»«ENDFOR»'''
+        }
+    }
+
     def code(String string) '''<code>«string»</code>'''
 
     def process(Module module) {
@@ -316,7 +594,7 @@ class GeneratorImpl {
     }
 
     def CharSequence tree(Module module) '''
-        Â«strong("module " + module.name)»
+        Â«strong(module.name)»
         Â«module.childNodes.treeSet(InstanceIdentifier.builder.toInstance())»
     '''
 
@@ -354,62 +632,211 @@ class GeneratorImpl {
 
     def CharSequence childNodes(Module module) '''
         Â«val childNodes = module.childNodes»
-        Â«IF childNodes !== null && !childNodes.empty»
+        Â«IF !childNodes.nullOrEmpty»
             <h2>Child nodes</h2>
 
             Â«childNodes.printChildren(3,InstanceIdentifier.builder().toInstance())»
         Â«ENDIF»
     '''
 
+    def CharSequence printSchemaNodeInfo(DataSchemaNode node) {
+        return '''
+            <ul>
+            Â«node.printBaseInfo»
+            Â«IF node instanceof DataNodeContainer»
+                Â«val dataNode = node as DataNodeContainer»
+                <ul>
+                Â«FOR usesNode : dataNode.uses»
+                    Â«usesNode.printUses»
+                Â«ENDFOR»
+                </ul>
+                <ul>
+                Â«FOR typeDef : dataNode.typeDefinitions»
+                    Â«typeDef.restrictions»
+                Â«ENDFOR»
+                </ul>
+                <ul>
+                Â«FOR grouping : dataNode.groupings»
+                    Â«grouping.printGrouping»
+                Â«ENDFOR»
+                </ul>
+                <ul>
+                Â«FOR child : dataNode.childNodes»
+                    Â«child.printSchemaNodeInfo»
+                Â«ENDFOR»
+                </ul>
+            Â«ENDIF»
+            </ul>
+        '''
+    }
+
+    def String typeAnchorLink(SchemaPath path, CharSequence text) {
+        if(path !== null) {
+            val prefix = path.path.last.prefix
+            if(prefix == this.currentModule.prefix) {
+                return '''<a href="#«path.schemaPathToId»">«text»</a>'''
+            } else if(!prefix.nullOrEmpty){
+                val String module = imports.get(prefix)
+                if(!module.nullOrEmpty) {
+                    return '''«prefix»:«text»'''
+                    //to enable external (import) links
+                    //return '''<a href="«module».html#«path.schemaPathToId»">«prefix»:«text»</a>'''
+                }
+            }
+            return text.toString
+        }
+    }
+
+    def CharSequence printBaseInfo(SchemaNode node) {
+        if(node instanceof LeafSchemaNode) {
+            val LeafSchemaNode leafNode = (node as LeafSchemaNode)
+            return '''
+                Â«printInfo(node, "leaf")»
+                Â«listItem("type", typeAnchorLink(leafNode.type?.path, leafNode.type.QName.localName))»
+                Â«listItem("units", leafNode.units)»
+                Â«listItem("default", leafNode.^default)»
+                </ul>
+            '''
+        } else if(node instanceof LeafListSchemaNode) {
+            val LeafListSchemaNode leafListNode = (node as LeafListSchemaNode)
+            return '''
+                Â«printInfo(node, "leaf-list")»
+                Â«listItem("type", leafListNode.type?.QName.localName)»
+                </ul>
+            '''
+        } else if(node instanceof ListSchemaNode) {
+            val ListSchemaNode listNode = (node as ListSchemaNode)
+            return '''
+                Â«printInfo(node, "list")»
+                Â«FOR keyDef : listNode.keyDefinition»
+                    Â«listItem("key definition", keyDef.localName)»
+                Â«ENDFOR»
+                </ul>
+            '''
+        } else if(node instanceof ChoiceNode) {
+            val ChoiceNode choiceNode = (node as ChoiceNode)
+            return '''
+                Â«printInfo(node, "choice")»
+                Â«listItem("default case", choiceNode.defaultCase)»
+                Â«FOR caseNode : choiceNode.cases»
+                    Â«caseNode.printSchemaNodeInfo»
+                Â«ENDFOR»
+                </ul>
+            '''
+        } else if(node instanceof ChoiceCaseNode) {
+            return '''
+                Â«printInfo(node, "case")»
+                </ul>
+            '''
+        } else if(node instanceof ContainerSchemaNode) {
+            return '''
+                Â«printInfo(node, "container")»
+                </ul>
+            '''
+        } else if(node instanceof AnyXmlSchemaNode) {
+            return '''
+                Â«printInfo(node, "anyxml")»
+                </ul>
+            '''
+        }
+    }
+
+    def CharSequence printInfo(SchemaNode node, String nodeType) {
+        return '''
+            Â«IF node instanceof AugmentationTarget»
+                Â«IF node !== null»
+                    <strong>
+                    <li id="«node.path.schemaPathToId»">
+                        Â«nodeType»: Â«node.QName.localName»
+                    </li>
+                    </strong>
+                Â«ENDIF»
+            Â«ELSE»
+                Â«strong(listItem(nodeType, node.QName.localName))»
+            Â«ENDIF»
+            <ul>
+            Â«listItem("description", node.description)»
+            Â«listItem("reference", node.reference)»
+            Â«IF node instanceof DataSchemaNode»
+                Â«listItem("when condition", (node as DataSchemaNode).constraints.whenCondition?.toString)»
+                Â«listItem("min elements", (node as DataSchemaNode).constraints.minElements?.toString)»
+                Â«listItem("max elements", (node as DataSchemaNode).constraints.maxElements?.toString)»
+            Â«ENDIF»
+        '''
+    }
+
+    def CharSequence printUses(UsesNode usesNode) {
+        return '''
+            Â«strong(listItem("uses", typeAnchorLink(usesNode.groupingPath, usesNode.groupingPath.path.last.localName)))»
+            <ul>
+            <li>refines:
+                <ul>
+                Â«FOR sp : usesNode.refines.keySet»
+                    Â«listItem("node name", usesNode.refines.get(sp).QName.localName)»
+                Â«ENDFOR»
+                </ul>
+            </li>
+            Â«FOR augment : usesNode.augmentations»
+                Â«typeAnchorLink(augment.targetPath,schemaPathToString(currentModule, augment.targetPath, ctx, augment))»
+            Â«ENDFOR»
+            </ul>
+        '''
+    }
+
+    def CharSequence printGrouping(GroupingDefinition grouping) {
+        return '''
+            Â«strong(listItem("grouping", grouping.QName.localName))»
+        '''
+    }
+
     def CharSequence printChildren(Set<DataSchemaNode> nodes, int level, InstanceIdentifier path) {
-    val anyxmlNodes = nodes.filter(AnyXmlSchemaNode)
-    val leafNodes = nodes.filter(LeafSchemaNode)
-    val leafListNodes = nodes.filter(LeafListSchemaNode)
-    val choices = nodes.filter(ChoiceNode)
-    val cases = nodes.filter(ChoiceCaseNode)
-    val containers = nodes.filter(ContainerSchemaNode)
-    val lists = nodes.filter(ListSchemaNode)
-    return '''
-        Â«IF ((anyxmlNodes.size + leafNodes.size + leafListNodes.size + containers.size + lists.size) > 0)»
-        <h3>Direct children</h3>
-        <ul>
-        Â«FOR childNode : anyxmlNodes»
-            Â«childNode.printShortInfo(level,path)»
-        Â«ENDFOR»
-        Â«FOR childNode : leafNodes»
-            Â«childNode.printShortInfo(level,path)»
-        Â«ENDFOR»
-        Â«FOR childNode : leafListNodes»
-            Â«childNode.printShortInfo(level,path)»
-        Â«ENDFOR»
-        Â«FOR childNode : containers»
-            Â«childNode.printShortInfo(level,path)»
-        Â«ENDFOR»
-        Â«FOR childNode : lists»
-            Â«childNode.printShortInfo(level,path)»
-        Â«ENDFOR»
-        </ul>
-        Â«ENDIF»
+        val anyxmlNodes = nodes.filter(AnyXmlSchemaNode)
+        val leafNodes = nodes.filter(LeafSchemaNode)
+        val leafListNodes = nodes.filter(LeafListSchemaNode)
+        val choices = nodes.filter(ChoiceNode)
+        val cases = nodes.filter(ChoiceCaseNode)
+        val containers = nodes.filter(ContainerSchemaNode)
+        val lists = nodes.filter(ListSchemaNode)
+        return '''
+            Â«IF ((anyxmlNodes.size + leafNodes.size + leafListNodes.size + containers.size + lists.size) > 0)»
+            <h3>Direct children</h3>
+            <ul>
+            Â«FOR childNode : anyxmlNodes»
+                Â«childNode.printShortInfo(level,path)»
+            Â«ENDFOR»
+            Â«FOR childNode : leafNodes»
+                Â«childNode.printShortInfo(level,path)»
+            Â«ENDFOR»
+            Â«FOR childNode : leafListNodes»
+                Â«childNode.printShortInfo(level,path)»
+            Â«ENDFOR»
+            Â«FOR childNode : containers»
+                Â«childNode.printShortInfo(level,path)»
+            Â«ENDFOR»
+            Â«FOR childNode : lists»
+                Â«childNode.printShortInfo(level,path)»
+            Â«ENDFOR»
+            </ul>
+            Â«ENDIF»
 
-        Â«IF !path.path.empty»
-        <h3>XML example</h3>
-        Â«nodes.xmlExample(path.path.last.nodeType,path)»
-        </h3>
-        Â«ENDIF»
-        Â«FOR childNode : containers»
-            Â«childNode.printInfo(level,path)»
-        Â«ENDFOR»
-        Â«FOR childNode : lists»
-            Â«childNode.printInfo(level,path)»
-        Â«ENDFOR»
-        Â«FOR childNode : choices»
-            Â«childNode.printInfo(level,path)»
-        Â«ENDFOR»
-        Â«FOR childNode : cases»
-            Â«childNode.printInfo(level,path)»
-        Â«ENDFOR»
-        
-    '''
+            Â«IF !path.path.empty»
+            <h3>XML example</h3>
+            Â«nodes.xmlExample(path.path.last.nodeType,path)»
+            </h3>
+            Â«ENDIF»
+            Â«FOR childNode : containers»
+                Â«childNode.printInfo(level,path)»
+            Â«ENDFOR»
+            Â«FOR childNode : lists»
+                Â«childNode.printInfo(level,path)»
+            Â«ENDFOR»
+            Â«FOR childNode : choices»
+                Â«childNode.printInfo(level,path)»
+            Â«ENDFOR»
+            Â«FOR childNode : cases»
+                Â«childNode.printInfo(level,path)»
+            Â«ENDFOR»
+        '''
     }
 
     def CharSequence xmlExample(Set<DataSchemaNode> nodes, QName name,InstanceIdentifier path) '''
@@ -540,6 +967,12 @@ class GeneratorImpl {
         '''
     }
 
+    def CharSequence anchorLink(CharSequence anchor, CharSequence text) {
+        return '''
+            <a href="#«anchor»">«text»</a>
+        '''
+    }
+
     def CharSequence localLink(InstanceIdentifier identifier, CharSequence text) '''
         <a href="#«FOR cmp : identifier.path SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">«text»</a>
     '''
@@ -554,7 +987,7 @@ class GeneratorImpl {
     private def dispatch InstanceIdentifier append(InstanceIdentifier identifier, ListSchemaNode node) {
         val pathArguments = new ArrayList(identifier.path)
         val keyValues = new LinkedHashMap<QName,Object>();
-        if(node.keyDefinition != null) {
+        if(node.keyDefinition !== null) {
             for(definition : node.keyDefinition) {
                 keyValues.put(definition,new Object);
             }
@@ -590,13 +1023,8 @@ class GeneratorImpl {
         return it.toString;
     }
 
-    private def String schemaPathAsRestconfPath(Module module, SchemaPath schemaPath, SchemaContext ctx) {
-        val Map<String, String> imports = new HashMap();
-        for (mImport : module.imports) {
-            imports.put(mImport.prefix, mImport.moduleName)
-        }
-
-        val List<QName> path = schemaPath.path
+    private def String schemaPathToString(Module module, SchemaPath schemaPath, SchemaContext ctx, DataNodeContainer dataNode) {
+            val List<QName> path = schemaPath.path
         val StringBuilder pathString = new StringBuilder()
         if (schemaPath.absolute) {
             pathString.append("/")
@@ -625,22 +1053,25 @@ class GeneratorImpl {
                     }
                 }
 
-                if (!(node instanceof ChoiceNode) && !(node instanceof ChoiceCaseNode)) {
-                    var String prefix = name.prefix
-                    var String moduleName
-                    if (prefix == null || "".equals(prefix) || prefix.equals(module.prefix)) {
-                        moduleName = module.name
-                    } else {
-                        moduleName = imports.get(prefix)
+                var String prefix = name.prefix
+                var String moduleName
+                if (prefix == null || "".equals(prefix) || prefix.equals(module.prefix)) {
+                    moduleName = module.name
+                } else {
+                    moduleName = imports.get(prefix)
+                }
+                pathString.append(moduleName)
+                pathString.append(":")
+                pathString.append(name.localName)
+                pathString.append("/")
+                if(node instanceof ChoiceNode && dataNode !== null) {
+                    val DataSchemaNode caseNode = dataNode.childNodes.findFirst[DataSchemaNode e | e instanceof ChoiceCaseNode];
+                    if(caseNode !== null) {
+                        pathString.append("(case)");
+                        pathString.append(caseNode.QName.localName);
                     }
-                    pathString.append(moduleName)
-                    pathString.append(":")
-                    pathString.append(name.localName)
-                    pathString.append("/")
                 }
                 parent = node
-            } else if (parent instanceof ChoiceNode) {
-                parent = (parent as ChoiceNode).getCaseNodeByName(qname.localName)
             }
         }
         return pathString.toString;
@@ -683,18 +1114,6 @@ class GeneratorImpl {
         [«FOR key : node.keyDefinition SEPARATOR " "»«key.localName»«ENDFOR»]
     '''
 
-    private def CharSequence rpcInfo(RpcDefinition rpc,InstanceIdentifier path) '''
-        <ul>
-            Â«rpc.descAndRefLi»
-            <li>
-                Â«rpc.input.tree(path)»
-            </li>
-            <li>
-                Â«rpc.output.tree(path)»
-            </li>
-        </ul>
-    '''
-
     private def CharSequence extensionInfo(ExtensionDefinition ext) '''
         <ul>
             Â«ext.descAndRefLi»
@@ -709,6 +1128,7 @@ class GeneratorImpl {
 
     /* #################### RESTRICTIONS #################### */
     private def restrictions(TypeDefinition<?> type) '''
+        Â«type.baseType.toBaseStmt»
         Â«type.toLength»
         Â«type.toRange»
     '''
@@ -749,7 +1169,7 @@ class GeneratorImpl {
 
     def toLengthStmt(Collection<LengthConstraint> lengths) '''
         Â«IF lengths != null && !lengths.empty»
-            Â«listItem("Length restrictions")»
+            Â«listItem("Length restrictions:")»
             <ul>
             Â«FOR length : lengths»
                 <li>
@@ -766,7 +1186,7 @@ class GeneratorImpl {
 
     def toRangeStmt(Collection<RangeConstraint> ranges) '''
         Â«IF ranges != null && !ranges.empty»
-            Â«listItem("Range restrictions")»
+            Â«listItem("Range restrictions:")»
             <ul>
             Â«FOR range : ranges»
                 <li>
@@ -781,15 +1201,20 @@ class GeneratorImpl {
         Â«ENDIF»
     '''
 
+    def toBaseStmt(TypeDefinition<?> baseType) '''
+        Â«IF baseType != null»
+        Â«listItem("Base type", typeAnchorLink(baseType?.path, baseType.QName.localName))»
+        Â«ENDIF»
+    '''
+
 
 
     /* #################### UTILITY #################### */
     private def String strong(CharSequence str) '''<strong>«str»</strong>'''
     private def italic(CharSequence str) '''<i>«str»</i>'''
-    private def pre(CharSequence str) '''<pre>«str»</pre>'''
 
     def CharSequence descAndRefLi(SchemaNode node) '''
-        Â«listItem(node.description)»
+        Â«listItem("Description", node.description)»
         Â«listItem("Reference", node.reference)»
     '''
 
@@ -887,7 +1312,7 @@ class GeneratorImpl {
             Â«node.QName.localName»«node.addedByInfo»
         Â«ENDIF»
     '''
-    
+
     private def dispatch nodeName(ContainerSchemaNode node) '''
         Â«IF node.isAddedBy»
             Â«strong(italic(node.QName.localName))»«node.addedByInfo»
index 436ea44942c7927c703c9e5e6ba7a4fe46907c9c..c3e7d3038236aab0c224c7f3d51c6be00e6233bb 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.yangtools.yang.unified.doc.generator.maven;
 import java.io.File;
 import java.io.IOException;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
 
@@ -26,8 +25,7 @@ public class DocumentationGeneratorImpl extends GeneratorImpl implements CodeGen
     @Override
     public Collection<File> generateSources(SchemaContext arg0, File arg1, Set<Module> arg2) throws IOException {
         // TODO Auto-generated method stub
-         generate(arg0, arg1, arg2);
-         return Collections.emptySet();
+         return generate(arg0, arg1, arg2);
     }
 
     @Override
index b15193d2cec1818797aa2bc5eaee4512de7665e6..1335450395acf9c3929204d8c266dadf46821f72 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.unified.doc.generator.maven;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
 import java.io.File;
@@ -14,6 +15,7 @@ import java.io.FileNotFoundException;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 
@@ -53,7 +55,8 @@ public class DocGenTest {
         final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
         final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
         final CodeGenerator generator = new DocumentationGeneratorImpl();
-        generator.generateSources(context, GENERATOR_OUTPUT_DIR, modulesToBuild);
+        Collection<File> generatedFiles = generator.generateSources(context, GENERATOR_OUTPUT_DIR, modulesToBuild);
+        assertEquals(4, generatedFiles.size());
     }
 
     private static List<File> getSourceFiles(String path) throws Exception {
index 174baf72c08766ab89d6c09a115e075a99a05204..756ba674ac8ba9f28be2ba4000d7566f41cfe589 100644 (file)
@@ -7,7 +7,8 @@
  */
 package org.opendaylight.yangtools.yang.wadl.generator.maven;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 
 import java.io.File;
 import java.io.FileNotFoundException;
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/config.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/config.yang
new file mode 100644 (file)
index 0000000..a0a4292
--- /dev/null
@@ -0,0 +1,190 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module config {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:config";
+    prefix "config";
+
+
+    description
+         "This module contains the base YANG definitions for NS-OS
+         configuration subsystem. The system modeled revolves around two
+         major concepts: modules and services.";
+
+    revision "2013-04-05" {
+        description
+            "Reworked to give modules their own space.";
+    }
+
+    revision "2013-04-03" {
+        description
+            "Initial revision.";
+    }
+
+    extension java-class {
+        description
+            "YANG language extension carrying the fully-qualified name of
+             a Java class. Code generation tools use the provided reference
+             to tie a specific construct to its Java representation.";
+
+        argument "name";
+    }
+
+    extension required-identity {
+        description
+            "YANG language extension which indicates that a particular
+             leafref, which points to a identityref, should additionally
+             require the target node is actually set to a descendant to
+             of a particular identity.
+
+             This is a workaround to two YANG deficiencies:
+             1) not being able to leafref instances of identityref
+             2) not being able to refine an identityref
+
+             This extension takes one argument, name, which MUST be the name
+             of an identity. Furthermore, that identity MUST be based,
+             directly or indirectly, on the identity, which is referenced by
+             the leaf reference, which is annotated with this extension.";
+
+        argument "name";
+    }
+
+    extension inner-state-bean {
+        description
+            "YANG language extension which indicates that a particular
+             list located under module's state should be treated as a list
+             of child state beans instead of just an ordinary list attribute";
+    }
+
+    extension provided-service {
+        description
+            "YANG language extension which indicates that a particular
+            module provides certain service. This extension can be placed
+            on identities that are based on module-type. Zero or more services
+            can be provided.
+            This extension takes one argument - name - which MUST be the name
+            of an identity. Furthermore, this identity MUST be based on
+            service-type.";
+
+        argument "name";
+    }
+
+    extension java-name-prefix {
+        description
+            "YANG language extension carrying java simple class name prefix
+            that will be taken into account when generating java code from
+            identities that are based on module-type.";
+            argument "java-prefix";
+    }
+
+    identity module-type {
+        description
+            "Module identity base type. All module identities must be derived
+            from this type. A module type uniquely defines a single atomic
+            component, such as an application. Each such component is assumed
+            to have its unique, stable and versioned configuration structure.";
+    }
+
+    identity service-type {
+        description
+            "Service identity base type. All service identities must be
+             derived from this type. A service type uniquely defines a single
+             atomic API contract, such as a Java interface, a set of C
+             function declarations, or similar.
+
+             If the service type has a corresponding Java interface, the name
+             of that interface should be attached to the derived identity MUST
+             include a java-class keyword, whose name argument points to that
+             interface.";
+    }
+
+    typedef service-type-ref {
+        description
+            "Internal type of references to service type identity.";
+
+        type identityref {
+            base service-type;
+        }
+    }
+
+    grouping service-ref {
+        description
+            "Type of references to a particular service instance. This type
+             can be used when defining module configuration to refer to a
+             particular service instance. Containers using this grouping
+             should not define anything else. The run-time implementation
+             is expected to inject a reference to the service as the value
+             of the container.";
+
+        leaf type {
+            description
+                "Type of the service being referenced. Users of this grouping
+                 should refine this leaf with required-identity pointing to
+                 the actual service-type which is actually required.";
+
+            mandatory true;
+            type service-type-ref;
+        }
+
+        leaf name {
+            mandatory true;
+            type leafref {
+                path "/config:services/config:service[config:type=current()/../type]/config:instance/config:name";
+            }
+        }
+    }
+
+    container modules {
+        description
+            "Top level container encapsulating configuration of all modules.";
+
+        list module {
+            key "name";
+            leaf name {
+                description "Unique module instance name";
+                type string;
+                mandatory true;
+            }
+
+            leaf type {
+                type identityref {
+                    base module-type;
+                }
+                mandatory true;
+            }
+
+            choice configuration {
+                mandatory true;
+                config true;
+            }
+
+            choice state {
+                config false;
+            }
+        }
+    }
+
+
+    container services {
+        list service {
+            key "type";
+            leaf type {
+                type service-type-ref;
+            }
+            list instance {
+                key "name";
+                leaf name {
+                    type string;
+                }
+
+                leaf provider {
+                    mandatory true;
+                    type leafref {
+                        path "/modules/module/name";
+                    }
+                }
+            }
+        }
+    }
+
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/netty.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/netty.yang
new file mode 100644 (file)
index 0000000..7cac5ad
--- /dev/null
@@ -0,0 +1,52 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module netty {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:netty";
+    prefix "netty";
+
+    import config { prefix config; revision-date 2013-04-05; }
+
+    organization "Cisco Systems, Inc.";
+
+    contact "Milos Fabian <milfabia@cisco.com>";
+
+    description
+        "This module contains the base YANG definitions for
+         netty services.
+
+        Copyright (c)2013 Cisco Systems, Inc. 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";
+
+    revision "2013-11-19" {
+        description
+            "Initial revision.";
+    }
+
+    identity netty-threadgroup {
+        description
+            "Configuration wrapper around netty's threadgroup";
+
+        base "config:service-type";
+        config:java-class "io.netty.channel.EventLoopGroup";
+    }
+
+    identity netty-event-executor {
+        description
+            "Configuration wrapper around netty's event executor";
+
+        base "config:service-type";
+        config:java-class "io.netty.util.concurrent.EventExecutor";
+    }
+
+    identity netty-timer {
+        description
+            "Configuration wrapper around netty's timer";
+
+        base "config:service-type";
+        config:java-class "io.netty.util.Timer";
+    }
+}
\ No newline at end of file
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/odl-protocol-framework-cfg.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/odl-protocol-framework-cfg.yang
new file mode 100644 (file)
index 0000000..1856369
--- /dev/null
@@ -0,0 +1,151 @@
+// vi: set smarttab et sw=4 tabstop=4:
+module protocol-framework {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:protocol:framework";
+    prefix "pf";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import netty { prefix netty; revision-date 2013-11-19; }
+
+    organization "Cisco Systems, Inc.";
+
+    contact "Milos Fabian <milfabia@cisco.com>";
+
+    description
+        "This module contains the base YANG definitions for
+         protocol framework.
+
+        Copyright (c)2013 Cisco Systems, Inc. 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";
+
+    revision "2014-03-13" {
+        description
+            "Changed reconnect-strategy to reconnect-strategy-factory - represents ReconnectStrategyFactory.
+            reconnect-strategy-factory modules provides reconnect-strategy-factory service.";
+    }
+
+    revision "2013-11-09" {
+        description
+            "Initial revision";
+    }
+
+    identity reconnect-strategy-factory {
+        description
+            "Service representing a reconnect strategy factory.";
+
+        base "config:service-type";
+        config:java-class "org.opendaylight.protocol.framework.ReconnectStrategyFactory";
+    }
+
+    identity never-reconnect-strategy-factory {
+        base config:module-type;
+        config:provided-service reconnect-strategy-factory;
+        config:java-name-prefix NeverReconnectStrategyFactory;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case never-reconnect-strategy-factory {
+            when "/config:modules/config:module/config:type = 'never-reconnect-strategy-factory'";
+
+            leaf timeout {
+                mandatory true;
+                type int32;
+            }
+
+            container executor {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity netty:netty-event-executor;
+                    }
+                }
+            }
+        }
+    }
+
+    identity reconnect-immediately-strategy-factory {
+        base config:module-type;
+        config:provided-service reconnect-strategy-factory;
+        config:java-name-prefix ReconnectImmediatelyStrategyFactory;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case reconnect-immediately-strategy-factory {
+            when "/config:modules/config:module/config:type = 'reconnect-immediately-strategy-factory'";
+
+            leaf timeout {
+                mandatory true;
+                type int32;
+            }
+
+            container executor {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity netty:netty-event-executor;
+                    }
+                }
+            }
+        }
+    }
+
+    identity timed-reconnect-strategy-factory {
+        base config:module-type;
+        config:provided-service reconnect-strategy-factory;
+        config:java-name-prefix TimedReconnectStrategyFactory;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case timed-reconnect-strategy-factory {
+            when "/config:modules/config:module/config:type = 'timed-reconnect-strategy-factory'";
+
+            leaf deadline {
+                type int64;
+                units "epoch nanoseconds";
+            }
+
+            leaf max-attempts {
+                mandatory true;
+                type int64;
+            }
+
+            leaf max-sleep {
+                mandatory true;
+                type int64;
+                units "milliseconds";
+            }
+
+            leaf min-sleep {
+                mandatory true;
+                type int64;
+                units "milliseconds";
+            }
+
+            leaf sleep-factor {
+                mandatory true;
+                type decimal64 {
+                    fraction-digits 2;
+                }
+            }
+
+            leaf connect-time {
+                mandatory true;
+                type int32;
+                units "milliseconds";
+            }
+
+            container executor {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity netty:netty-event-executor;
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
similarity index 91%
rename from concepts/pom.xml
rename to common/concepts/pom.xml
index 7c9df45b4db526ac2e2bd66798febaf39e03556b..657d8a1c6f9ca35af8a910a22fe3d78b85a60118 100644 (file)
 
     <parent>
         <groupId>org.opendaylight.yangtools</groupId>
-        <artifactId>yangtools</artifactId>
+        <artifactId>common-parent</artifactId>
         <version>0.6.2-SNAPSHOT</version>
     </parent>
     <packaging>bundle</packaging>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>concepts</artifactId>
     <name>${project.artifactId}</name>
-    <description>Java binding for YANG</description>
+    <description>Common concepts</description>
 
     <build>
         <plugins>
diff --git a/common/concepts/src/main/java/org/opendaylight/yangtools/concepts/ProductAwareBuilder.java b/common/concepts/src/main/java/org/opendaylight/yangtools/concepts/ProductAwareBuilder.java
new file mode 100644 (file)
index 0000000..b2c2d04
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.concepts;
+
+/**
+ * An extension of the {@link Builder} concept which allows an implementation
+ * of this interface to be used in collections instead of the product. Given
+ * the mutable nature of Builders, this has to be done very carefully.
+ *
+ * @param <P> Product type
+ */
+public interface ProductAwareBuilder<P> extends Builder<P> {
+       /**
+        * Return the hash code of the product. This has to be equivalent
+        * of calling {@link #toInstance()}.{@link #hashCode()}.
+        *
+        * @return the hash code of the product.
+        */
+       int productHashCode();
+
+       /**
+        * Check whether an instance of the product that would be created
+        * by the builder is equal to an existing instance. This has to
+        * be equivalent of calling {@link #toInstance()}.{@link #equals(Object)}.
+        *
+        * @param product Product instance
+        * @return Return true if the product is equal to the would-be
+        *         product of the builder.
+        */
+       boolean productEquals(Object product);
+}
similarity index 83%
rename from concepts/src/main/java/org/opendaylight/yangtools/concepts/util/Immutables.java
rename to common/concepts/src/main/java/org/opendaylight/yangtools/concepts/util/Immutables.java
index 403d0341c687020a14795212189d1fe70c1e06bf..d659123f9710e81a6fbc4c6df8ef3978e283c786 100644 (file)
@@ -12,8 +12,6 @@ import java.math.BigInteger;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
 
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.concepts.Mutable;
@@ -31,10 +29,10 @@ public class Immutables {
 
     /**
      * Determines if object is known to be immutable
-     * 
+     *
      * Note: This method may return false to immutable objects which
      * immutability is not known, was defined not using concepts term.
-     * 
+     *
      * @param o
      *            Reference to check
      * @return true if object is known to be immutable false otherwise.
@@ -55,17 +53,6 @@ public class Immutables {
         return false;
     }
 
-    private static boolean isNumberImmutable(Number o) {
-        if(o instanceof AtomicInteger) {
-            return false;
-        } else if(o instanceof AtomicLong) {
-            return false;
-        } else if(o instanceof Short) {
-            return true;
-        }
-        return false;
-    }
-
     @SafeVarargs
     private static <E> Set<E> asHashSet(E... list) {
         HashSet<E> ret = new HashSet<>();
similarity index 96%
rename from mockito-configuration/pom.xml
rename to common/mockito-configuration/pom.xml
index c0d5225e9a4f283954579f70a6c3fee4f26c3f74..2e896de18b946b4ec59aa8e0540c25acabeb0966 100644 (file)
@@ -11,7 +11,7 @@
 
     <parent>
         <groupId>org.opendaylight.yangtools</groupId>
-        <artifactId>yangtools</artifactId>
+        <artifactId>common-parent</artifactId>
         <version>0.6.2-SNAPSHOT</version>
     </parent>
 
diff --git a/common/object-cache-api/pom.xml b/common/object-cache-api/pom.xml
new file mode 100644 (file)
index 0000000..8ef8a14
--- /dev/null
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>common-parent</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+    </parent>
+    <packaging>bundle</packaging>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>object-cache-api</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>concepts</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <phase>process-classes</phase>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                        <configuration>
+                            <tasks>
+                                <!-- This is necessary to remove the impl package and
+                                     make static binding work with the implementation -->
+                                <delete dir="${project.build.outputDirectory}/org/opendaylight/yangtools/objcache/impl"/>
+                            </tasks>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/ObjectCache.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/ObjectCache.java
new file mode 100644 (file)
index 0000000..9f32768
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.concepts.ProductAwareBuilder;
+
+/**
+ * A cache of objects. Caches are useful for reducing memory overhead
+ * stemming from multiple copies of identical objects -- by putting
+ * a cache in the instantiation path, one can expend some memory on
+ * indexes and spend some CPU cycles on walking the index to potentially
+ * end up with a reused object.
+ * 
+ * Note that the cached objects should really be semantically {@link Immutable}.
+ * This interface does not enforce that interface contract simply because
+ * there are third-party objects which fulfill this contract.
+ */
+public interface ObjectCache {
+       /**
+        * Get a reference for an object which is equal to specified object.
+        * The cache is free return either a cached instance, or retain the
+        * object and return it back.
+        *
+        * @param object Requested object, may be null
+        * @return Reference to an object which is equal to the one passed in.
+        *         If @object was @null, this method returns @null.
+        */
+       <T> T getReference(@Nullable T object);
+
+       /**
+        * Get a reference to an object equal to the product of a builder.
+        * The builder is expected to remain constant while this method
+        * executes. Unlike {@link #getReference(Object)}, this method has
+        * the potential of completely eliding the product instantiation.
+        * 
+        * @param builder Builder instance, may not be null
+        * @return Result of builder's toInstance() product, or an equal
+        *         object.
+        */
+       <B extends ProductAwareBuilder<P>, P> P getProduct(@Nonnull B builder);
+}
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/ObjectCacheFactory.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/ObjectCacheFactory.java
new file mode 100644 (file)
index 0000000..58ca11c
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.yangtools.objcache.impl.StaticObjectCacheBinder;
+import org.opendaylight.yangtools.objcache.spi.IObjectCacheFactory;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Point of entry for acquiring an {@link ObjectCache} instance.
+ */
+public final class ObjectCacheFactory {
+       private static IObjectCacheFactory FACTORY;
+
+       private static synchronized IObjectCacheFactory initialize() {
+               // Double-check under lock
+               if (FACTORY != null) {
+                       return FACTORY;
+               }
+
+               final IObjectCacheFactory f = StaticObjectCacheBinder.getInstance().getProductCacheFactory();
+               FACTORY = f;
+               return f;
+       }
+
+       public static synchronized void reset() {
+               FACTORY = null;
+       }
+
+       /**
+        * Get an ObjectCache for caching a particular object class. Note
+        * that it may be shared for multiple classes.
+        * 
+        * @param objClass Class of objects which are to be cached
+        * @return Object cache instance.
+        */
+       public static ObjectCache getObjectCache(@Nonnull final Class<?> objClass) {
+               IObjectCacheFactory f = FACTORY;
+               if (f == null) {
+                       f = initialize();
+               }
+
+               return f.getObjectCache(Preconditions.checkNotNull(objClass));
+       }
+}
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/impl/StaticObjectCacheBinder.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/impl/StaticObjectCacheBinder.java
new file mode 100644 (file)
index 0000000..59cd30f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.impl;
+
+import org.opendaylight.yangtools.objcache.spi.AbstractObjectCacheBinder;
+
+/*
+ * This is a dummy placeholder implementation. The API package is bound to
+ * it at compile-time, but it is not packaged and thus not present at run-time.
+ */
+public final class StaticObjectCacheBinder extends AbstractObjectCacheBinder {
+       private StaticObjectCacheBinder() {
+               super(null);
+       }
+
+       public static StaticObjectCacheBinder getInstance() {
+               throw new IllegalStateException("This class should have been replaced");
+       }
+}
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/impl/package-info.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/impl/package-info.java
new file mode 100644 (file)
index 0000000..ecfa94a
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+/**
+ * Static binding implementation package. The API package is bound at compile-time
+ * to this package. Implementations are expected to supply this package.
+ */
+package org.opendaylight.yangtools.objcache.impl;
\ No newline at end of file
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/package-info.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/package-info.java
new file mode 100644 (file)
index 0000000..a28685a
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+/**
+ *
+ */
+package org.opendaylight.yangtools.objcache;
\ No newline at end of file
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/AbstractObjectCache.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/AbstractObjectCache.java
new file mode 100644 (file)
index 0000000..963030c
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.spi;
+
+import org.opendaylight.yangtools.concepts.ProductAwareBuilder;
+import org.opendaylight.yangtools.objcache.ObjectCache;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.FinalizableReferenceQueue;
+import com.google.common.base.FinalizableSoftReference;
+import com.google.common.base.Preconditions;
+import com.google.common.cache.Cache;
+
+/**
+ * Abstract object cache implementation. This implementation takes care
+ * of interacting with the user and manages interaction with the Garbage
+ * Collector (via soft references). Subclasses are expected to provide
+ * a backing {@link Cache} instance and provide the
+ */
+public abstract class AbstractObjectCache implements ObjectCache {
+       /**
+        * Key used when looking up a ProductAwareBuilder product. We assume
+        * the builder is not being modified for the duration of the lookup,
+        * anything else is the user's fault.
+        */
+       private static final class BuilderKey {
+               private final ProductAwareBuilder<?> builder;
+
+               private BuilderKey(final ProductAwareBuilder<?> builder) {
+                       this.builder = Preconditions.checkNotNull(builder);
+               }
+
+               @Override
+               public int hashCode() {
+                       return builder.productHashCode();
+               }
+
+               @Override
+               public boolean equals(Object obj) {
+                       /*
+                        * We can tolerate null objects coming our way, but we need
+                        * to be on the lookout for WeakKeys, as we cannot pass them
+                        * directly to productEquals().
+                        */
+                       if (obj != null && obj instanceof SoftKey) {
+                               obj = ((SoftKey)obj).get();
+                       }
+
+                       return builder.productEquals(obj);
+               }
+       }
+
+       /**
+        * Key used in the underlying map. It is essentially a soft reference, with
+        * slightly special properties.
+        * 
+        * It acts as a proxy for the object it refers to and essentially delegates
+        * to it. There are three exceptions here:
+        * 
+        * 1) This key needs to have a cached hash code. The requirement is that the
+        *    key needs to be able to look itself up after the reference to the object
+        *    has been cleared (and thus we can no longer look it up from there). One
+        *    typical container where we are stored are HashMaps -- and they need it
+        *    to be constant.
+        * 2) This key does not tolerate checks to see if its equal to null. While we
+        *    could return false, we want to catch offenders who try to store nulls
+        *    in the cache.
+        * 3) This key inverts the check for equality, e.g. it calls equals() on the
+        *    object which was passed to its equals(). Instead of supplying itself,
+        *    it supplies the referent. If the soft reference is cleared, such check
+        *    will return false, which is fine as it prevents normal lookup from
+        *    seeing the cleared key. Removal is handled by the explicit identity
+        *    check.
+        */
+       private static abstract class SoftKey extends FinalizableSoftReference<Object> {
+               private final int hashCode;
+
+               public SoftKey(final Object referent, final FinalizableReferenceQueue q) {
+                       super(Preconditions.checkNotNull(referent), q);
+                       hashCode = referent.hashCode();
+               }
+
+               @Override
+               public boolean equals(final Object obj) {
+                       Preconditions.checkState(obj != null);
+
+                       // Order is important: we do not want to call equals() on ourselves!
+                       return this == obj || obj.equals(get());
+               }
+
+               @Override
+               public int hashCode() {
+                       return hashCode;
+               }
+       }
+
+       private static final Logger LOG = LoggerFactory.getLogger(AbstractObjectCache.class);
+       private final FinalizableReferenceQueue queue;
+       private final Cache<Object, Object> cache;
+
+       protected AbstractObjectCache(final Cache<Object, Object> cache, final FinalizableReferenceQueue queue) {
+               this.queue = Preconditions.checkNotNull(queue);
+               this.cache = Preconditions.checkNotNull(cache);
+       }
+
+       private <T> T put(final T object) {
+               /*
+                * This may look like a race (having a soft reference and not have
+                * it in the cache). In fact this is protected by the fact we still
+                * have a strong reference on the object in our arguments and that
+                * reference survives past method return since we return it.
+                */
+               final Object key = new SoftKey(object, queue) {
+                       @Override
+                       public void finalizeReferent() {
+                               /*
+                                * NOTE: while it may be tempting to add "object" into this
+                                *       trace message, do not ever do that: it would retain
+                                *       a strong reference, preventing collection.
+                                */
+                               LOG.trace("Invalidating key {} for object {}", this);
+                               cache.invalidate(this);
+                       }
+               };
+               cache.put(key, object);
+               LOG.debug("Cached key {} to object {}", key, object);
+               return object;
+       }
+
+       @Override
+       public final <B extends ProductAwareBuilder<P>, P> P getProduct(final B builder) {
+               LOG.debug("Looking up product for {}", builder);
+
+               @SuppressWarnings("unchecked")
+               final P ret = (P) cache.getIfPresent(new BuilderKey(builder));
+               return ret == null ? put(Preconditions.checkNotNull(builder.toInstance())) : ret;
+       }
+
+       @Override
+       public final <T> T getReference(final T object) {
+               LOG.debug("Looking up reference for {}", object);
+               if (object == null) {
+                       return null;
+               }
+
+               @SuppressWarnings("unchecked")
+               final T ret = (T) cache.getIfPresent(object);
+               return ret == null ? put(object) : ret;
+       }
+}
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/AbstractObjectCacheBinder.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/AbstractObjectCacheBinder.java
new file mode 100644 (file)
index 0000000..be860ea
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.spi;
+
+import javax.annotation.Nonnull;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractObjectCacheBinder implements ObjectCacheFactoryBinder {
+       private final IObjectCacheFactory factory;
+
+       protected AbstractObjectCacheBinder(@Nonnull final IObjectCacheFactory factory) {
+               this.factory = Preconditions.checkNotNull(factory);
+       }
+
+       @Override
+       public final IObjectCacheFactory getProductCacheFactory() {
+               return factory;
+       }
+}
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/IObjectCacheFactory.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/IObjectCacheFactory.java
new file mode 100644 (file)
index 0000000..7ee6bc4
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.spi;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.yangtools.objcache.ObjectCache;
+
+public interface IObjectCacheFactory {
+       ObjectCache getObjectCache(@Nonnull Class<?> objClass);
+}
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/NoopObjectCache.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/NoopObjectCache.java
new file mode 100644 (file)
index 0000000..1163199
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.spi;
+
+import org.opendaylight.yangtools.concepts.ProductAwareBuilder;
+import org.opendaylight.yangtools.objcache.ObjectCache;
+
+/**
+ * No-operation implementation of an Object Cache. This implementation
+ * does not do any caching, so it only returns the request object.
+ */
+public final class NoopObjectCache implements ObjectCache {
+       private static final NoopObjectCache INSTANCE = new NoopObjectCache();
+
+       private NoopObjectCache() {
+
+       }
+
+       /**
+        * Get the cache instance. Since the cache does not have any state,
+        * this method always returns a singleton instance.
+        *
+        * @return Cache instance.
+        */
+       public static NoopObjectCache getInstance() {
+               return INSTANCE;
+       }
+
+       @Override
+       public <T> T getReference(final T object) {
+               return object;
+       }
+
+       @Override
+       public <B extends ProductAwareBuilder<P>, P> P getProduct(final B builder) {
+               return builder.toInstance();
+       }
+}
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/ObjectCacheFactoryBinder.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/ObjectCacheFactoryBinder.java
new file mode 100644 (file)
index 0000000..012428c
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.spi;
+
+/**
+ * Interface binding an implementation into ObjectCacheFactory.
+ */
+public interface ObjectCacheFactoryBinder {
+       /**
+        * Get the implementation-specific cache factory.
+        * 
+        * @return Implementation-specific factory.
+        */
+       IObjectCacheFactory getProductCacheFactory();
+}
diff --git a/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/package-info.java b/common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/spi/package-info.java
new file mode 100644 (file)
index 0000000..57223b6
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+/**
+ * Service Provider Interface for Object Cache. Object cache implementations
+ * use classes contained in this package to implement their functionality.
+ */
+package org.opendaylight.yangtools.objcache.spi;
\ No newline at end of file
diff --git a/common/object-cache-guava/pom.xml b/common/object-cache-guava/pom.xml
new file mode 100644 (file)
index 0000000..ee65f85
--- /dev/null
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>common-parent</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+    </parent>
+    <packaging>bundle</packaging>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>object-cache-guava</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>object-cache-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/guava/GuavaObjectCache.java b/common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/guava/GuavaObjectCache.java
new file mode 100644 (file)
index 0000000..7d90e39
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.guava;
+
+import org.opendaylight.yangtools.objcache.spi.AbstractObjectCache;
+
+import com.google.common.base.FinalizableReferenceQueue;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheBuilderSpec;
+
+final class GuavaObjectCache extends AbstractObjectCache {
+       public GuavaObjectCache(final FinalizableReferenceQueue queue, final CacheBuilderSpec spec) {
+               super(CacheBuilder.from(spec).softValues().build(), queue);
+       }
+}
diff --git a/common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/guava/GuavaObjectCacheFactory.java b/common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/guava/GuavaObjectCacheFactory.java
new file mode 100644 (file)
index 0000000..067b626
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.guava;
+
+import org.opendaylight.yangtools.objcache.ObjectCache;
+import org.opendaylight.yangtools.objcache.spi.IObjectCacheFactory;
+
+import com.google.common.base.FinalizableReferenceQueue;
+
+public final class GuavaObjectCacheFactory implements IObjectCacheFactory {
+       private static final GuavaObjectCacheFactory INSTANCE = new GuavaObjectCacheFactory();
+       private final FinalizableReferenceQueue queue = new FinalizableReferenceQueue();
+       private final ObjectCache cache;
+
+       private GuavaObjectCacheFactory() {
+               // FIXME: make this more dynamic
+               this.cache = new GuavaObjectCache(queue, null);
+       }
+
+       @Override
+       public void finalize() throws Throwable {
+               try {
+                       queue.close();
+               } finally {
+                       super.finalize();
+               }
+       }
+
+       @Override
+       public ObjectCache getObjectCache(final Class<?> objClass) {
+               return cache;
+       }
+
+       public static GuavaObjectCacheFactory getInstance() {
+               return INSTANCE;
+       }
+}
diff --git a/common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/guava/package-info.java b/common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/guava/package-info.java
new file mode 100644 (file)
index 0000000..46b6029
--- /dev/null
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+/**
+ *
+ */
+package org.opendaylight.yangtools.objcache.guava;
\ No newline at end of file
diff --git a/common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/impl/StaticObjectCacheBinder.java b/common/object-cache-guava/src/main/java/org/opendaylight/yangtools/objcache/impl/StaticObjectCacheBinder.java
new file mode 100644 (file)
index 0000000..5867d55
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.impl;
+
+import org.opendaylight.yangtools.objcache.guava.GuavaObjectCacheFactory;
+import org.opendaylight.yangtools.objcache.spi.AbstractObjectCacheBinder;
+
+public final class StaticObjectCacheBinder extends AbstractObjectCacheBinder {
+       private static final StaticObjectCacheBinder INSTANCE = new StaticObjectCacheBinder();
+
+       private StaticObjectCacheBinder() {
+               super(GuavaObjectCacheFactory.getInstance());
+       }
+
+       public static StaticObjectCacheBinder getInstance() {
+               return INSTANCE;
+       }
+}
diff --git a/common/object-cache-noop/pom.xml b/common/object-cache-noop/pom.xml
new file mode 100644 (file)
index 0000000..e2c9bce
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>common-parent</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+    </parent>
+    <packaging>bundle</packaging>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>object-cache-noop</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>object-cache-api</artifactId>
+        </dependency>
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/common/object-cache-noop/src/main/java/org/opendaylight/yangtools/objcache/impl/StaticObjectCacheBinder.java b/common/object-cache-noop/src/main/java/org/opendaylight/yangtools/objcache/impl/StaticObjectCacheBinder.java
new file mode 100644 (file)
index 0000000..2af58bf
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.objcache.impl;
+
+import org.opendaylight.yangtools.objcache.ObjectCache;
+import org.opendaylight.yangtools.objcache.spi.AbstractObjectCacheBinder;
+import org.opendaylight.yangtools.objcache.spi.IObjectCacheFactory;
+import org.opendaylight.yangtools.objcache.spi.NoopObjectCache;
+
+public final class StaticObjectCacheBinder extends AbstractObjectCacheBinder {
+       private static final StaticObjectCacheBinder INSTANCE = new StaticObjectCacheBinder();
+
+       private StaticObjectCacheBinder() {
+               super(new IObjectCacheFactory() {
+                       @Override
+                       public ObjectCache getObjectCache(final Class<?> objClass) {
+                               return NoopObjectCache.getInstance();
+                       }
+               });
+       }
+
+       public static StaticObjectCacheBinder getInstance() {
+               return INSTANCE;
+       }
+}
diff --git a/common/pom.xml b/common/pom.xml
new file mode 100644 (file)
index 0000000..6f1d440
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+
+ This program and the accompanying materials are made available under the
+ terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ and is available at http://www.eclipse.org/legal/epl-v10.html
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yangtools</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>common-parent</artifactId>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>concepts</module>
+        <module>mockito-configuration</module>
+        <module>object-cache-api</module>
+        <module>object-cache-guava</module>
+        <module>object-cache-noop</module>
+    </modules>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>object-cache-api</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>object-cache-guava</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>object-cache-noop</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+</project>
diff --git a/integration-test/bug527-test-model/pom.xml b/integration-test/bug527-test-model/pom.xml
new file mode 100644 (file)
index 0000000..a9f516a
--- /dev/null
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- 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 -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <artifactId>model-parent</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+        <relativePath>../../model/pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.opendaylight.yangtools</groupId>
+    <artifactId>bug527-test-model</artifactId>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
+
diff --git a/integration-test/bug527-test-model/src/main/yang/bar.yang b/integration-test/bug527-test-model/src/main/yang/bar.yang
new file mode 100644 (file)
index 0000000..d40faad
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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
+ */
+module bar {
+    yang-version 1;
+    namespace "urn:yang:bar";
+    prefix "bar";
+
+    revision "2014-03-21" {
+    }
+
+    container alpha {
+        container beta {
+        }
+    }
+
+    grouping group-a {
+        container xcont {
+            choice xchoice {
+            }
+        }
+    }
+
+    grouping group-b {
+        uses group-a {
+            augment "xcont/xchoice" {
+                case xcase {
+                    leaf idx {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/integration-test/bug527-test-model/src/main/yang/foo.yang b/integration-test/bug527-test-model/src/main/yang/foo.yang
new file mode 100644 (file)
index 0000000..0db6231
--- /dev/null
@@ -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
+ */
+module foo {
+    yang-version 1;
+    namespace "urn:yang:foo";
+    prefix "foo";
+
+    import bar {
+        prefix bar;
+    }
+
+    revision "2014-03-21" {
+    }
+
+
+
+    augment "/bar:alpha/bar:beta" {
+        uses bar:group-b;
+    }
+
+}
+
index 02a92720c27f93a12aa06be1232c190382877e4a..6e71866664ad6f6acc250414b6b7f32c678370d6 100644 (file)
@@ -18,6 +18,7 @@
     <packaging>pom</packaging>
 
     <modules>
+        <module>bug527-test-model</module>
         <module>regression-test-model</module>
         <module>yang-runtime-tests</module>
     </modules>
diff --git a/pom.xml b/pom.xml
index 37399eff88b7163690ef34c9e5152d53196ad46c..e229268818624987b3e648f535a231bc302d509a 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -29,7 +29,7 @@
 
         <!-- Build Plugin Versions -->
         <maven.bundle.version>2.4.0</maven.bundle.version>
-        <maven.jar.version>2.4</maven.jar.version>
+        <maven.jar.version>2.3.2</maven.jar.version>
         <maven.javadoc.version>2.9.1</maven.javadoc.version>
         <maven.release.version>2.4.2</maven.release.version>
         <maven.source.version>2.2.1</maven.source.version>
     </scm>
 
     <modules>
-        <module>concepts</module>
-        <module>yang</module>
         <module>code-generator</module>
+        <module>common</module>
+        <module>integration-test</module>
         <module>model</module>
         <module>restconf</module>
-        <module>integration-test</module>
-        <module>mockito-configuration</module>
         <module>websocket</module>
+        <module>yang</module>
         <!-- module>third-party</module -->
     </modules>
 
                 <artifactId>commons-lang3</artifactId>
                 <version>${commons.lang.version}</version>
             </dependency>
+            <dependency>
+                <groupId>com.google.code.findbugs</groupId>
+                <artifactId>jsr305</artifactId>
+                <version>2.0.3</version>
+            </dependency>
 
             <!-- Plugin integration -->
             <dependency>
index be73c409162a326019932a10d3226d93ab439af7..18392f22f36af78acc8134a5db364e9d711008a5 100644 (file)
                 <artifactId>concepts</artifactId>
                 <version>${project.version}</version>
             </dependency>
-            <dependency>
-                <groupId>org.glassfish.jersey.ext</groupId>
-                <artifactId>jersey-proxy-client</artifactId>
-                <version>2.0</version>
-            </dependency>
-            <dependency>
-                <groupId>org.glassfish.jersey.core</groupId>
-                <artifactId>jersey-client</artifactId>
-                <version>2.0</version>
-            </dependency>
 
             <dependency>
                 <groupId>javax.ws.rs</groupId>
                 <artifactId>javax.ws.rs-api</artifactId>
-                <version>2.0-m01</version>
+                <version>2.0</version>
             </dependency>
             <dependency>
                 <groupId>javax.ws.rs</groupId>
                 <version>1.1.1</version>
             </dependency>
 
+            <dependency>
+                <groupId>org.glassfish.jersey.ext</groupId>
+                <artifactId>jersey-proxy-client</artifactId>
+                <version>2.0</version>
+            </dependency>
+            <dependency>
+                <groupId>org.glassfish.jersey.core</groupId>
+                <artifactId>jersey-client</artifactId>
+                <version>2.0</version>
+            </dependency>
+
             <dependency>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>yang-model-util</artifactId>
         </pluginManagement>
     </build>
 
-</project>
\ No newline at end of file
+</project>
index 942b83f68e70ad5d1b07e3277de633d409e9c666..91e08bd124399958b5d32c5ee2d3231dc795381d 100644 (file)
@@ -8,9 +8,9 @@
  and is available at http://www.eclipse.org/legal/epl-v10.html
 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>restconf-client-api</artifactId>
-  <packaging>bundle</packaging>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>restconf-client-api</artifactId>
+    <packaging>bundle</packaging>
 
     <parent>
         <groupId>org.opendaylight.yangtools</groupId>
         <version>0.6.2-SNAPSHOT</version>
     </parent>
     <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>concepts</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-binding</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>concepts</artifactId>
+            <artifactId>yang-common</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>restconf-jaxrs-api</artifactId>
+            <artifactId>yang-data-impl</artifactId>
         </dependency>
         <dependency>
             <groupId>org.opendaylight.yangtools</groupId>
-            <artifactId>binding-generator-impl</artifactId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
         </dependency>
     </dependencies>
     <build>
index 6e695359daf0f2e02b8d6e9e8388fd2c0e88aa88..fe4eb76695e25b08007f27215ce3cd26bc1d7e7a 100644 (file)
@@ -7,14 +7,12 @@
  */
 package org.opendaylight.yangtools.restconf.client;
 
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.sun.jersey.api.client.ClientResponse;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.ArrayList;
 import java.util.List;
+
 import org.opendaylight.yangtools.restconf.client.to.RestRpcError;
 import org.opendaylight.yangtools.restconf.client.to.RestRpcResult;
 import org.opendaylight.yangtools.restconf.common.ResourceUri;
@@ -38,6 +36,10 @@ import org.w3c.dom.Document;
 import org.w3c.dom.ls.DOMImplementationLS;
 import org.w3c.dom.ls.LSSerializer;
 
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.sun.jersey.api.client.ClientResponse;
+
 public class BindingToRestRpc implements InvocationHandler {
 
     private final RestconfClientImpl client;
@@ -46,7 +48,7 @@ public class BindingToRestRpc implements InvocationHandler {
     private final SchemaContext schcemaContext;
     private final Module module;
 
-    public BindingToRestRpc(Class proxiedInterface,BindingIndependentMappingService mappingService,RestconfClientImpl client,SchemaContext schemaContext) throws Exception {
+    public BindingToRestRpc(Class<?> proxiedInterface,BindingIndependentMappingService mappingService,RestconfClientImpl client,SchemaContext schemaContext) throws Exception {
         this.mappingService = mappingService;
         this.client  = client;
         this.schcemaContext = schemaContext;
index e08f5b65d882fb4d6b7629393ba22de64c0e2b49..796959fe627af02eb619199567f9630605a2525b 100644 (file)
@@ -7,14 +7,8 @@
  */
 package org.opendaylight.yangtools.restconf.client;
 
-import com.google.common.base.Charsets;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.sun.jersey.api.client.ClientResponse;
 import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
+
 import java.io.UnsupportedEncodingException;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -24,7 +18,9 @@ import java.util.Date;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Executors;
+
 import javax.ws.rs.core.MediaType;
+
 import org.opendaylight.yangtools.concepts.AbstractListenerRegistration;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.restconf.client.api.event.EventStreamInfo;
@@ -40,6 +36,14 @@ import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.common.util.concurrent.MoreExecutors;
+import com.sun.jersey.api.client.ClientResponse;
+
 
 
 
index a074bf12c37e0d2d68e3f1c07406e76a86f616c2..934fe1686be72a4af39ebb0108037b998a530afe 100644 (file)
         <artifactId>restconf-parent</artifactId>
         <version>0.6.2-SNAPSHOT</version>
     </parent>
+
     <artifactId>restconf-common</artifactId>
-    <packaging>jar</packaging>
+    <packaging>bundle</packaging>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
 </project>
index 14bd206e77bf28b502479cfff880abdec50d540c..f62df8a9ba2f43e71d703f29a8584d707ed15ba5 100644 (file)
@@ -9,30 +9,24 @@
 -->
 <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
-  <modelVersion>4.0.0</modelVersion>
-  <parent>
-    <groupId>org.opendaylight.yangtools</groupId>
-    <artifactId>restconf-parent</artifactId>
-    <version>0.6.2-SNAPSHOT</version>
-  </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>restconf-parent</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+    </parent>
 
-  <artifactId>restconf-jaxrs-api</artifactId>
-  <name>restconf-jaxrs-api</name>
+    <artifactId>restconf-jaxrs-api</artifactId>
+    <name>restconf-jaxrs-api</name>
 
-  <dependencies>
-    <dependency>
-      <groupId>junit</groupId>
-      <artifactId>junit</artifactId>
-      <scope>test</scope>
-    </dependency>
-      <dependency>
-          <groupId>org.glassfish.jersey.ext</groupId>
-          <artifactId>jersey-proxy-client</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>yang-data-api</artifactId>
-      </dependency>
-
-  </dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+        </dependency>
+    </dependencies>
 </project>
index 830957179d2ce67392dea9c6caba7bad9178e79d..06c4863a07e3dba0adf81e538cb5c16659031146 100644 (file)
@@ -1,14 +1,11 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
- 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
--->
+<!-- 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 -->
 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.opendaylight.yangtools</groupId>
     <artifactId>restconf-util</artifactId>
     <packaging>jar</packaging>
 
-  <dependencies>
-      <dependency>
-          <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>restconf-jaxrs-api</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>yang-data-api</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>org.slf4j</groupId>
-          <artifactId>slf4j-api</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>yang-data-api</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>yang-data-impl</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>com.sun.jersey</groupId>
-          <artifactId>jersey-client</artifactId>
-          <version>1.17</version>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.yangtools</groupId>
-          <artifactId>restconf-client-api</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>commons-io</groupId>
-          <artifactId>commons-io</artifactId>
-      </dependency>
-      <dependency>
-          <groupId>xml-apis</groupId>
-          <artifactId>xml-apis</artifactId>
-          <version>2.0.2</version>
-      </dependency>
-      <dependency>
-          <groupId>junit</groupId>
-          <artifactId>junit</artifactId>
-          <scope>test</scope>
-      </dependency>
-      <dependency>
-          <groupId>org.opendaylight.yangtools.model</groupId>
-          <artifactId>ietf-topology-isis</artifactId>
-          <version>2013.10.21.2-SNAPSHOT</version>
-          <scope>test</scope>
-      </dependency>
-  </dependencies>
+    <dependencies>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>restconf-client-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>restconf-jaxrs-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.sun.jersey</groupId>
+            <artifactId>jersey-client</artifactId>
+            <version>1.17</version>
+        </dependency>
+        <dependency>
+            <groupId>xml-apis</groupId>
+            <artifactId>xml-apis</artifactId>
+            <version>2.0.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-topology-isis</artifactId>
+            <version>2013.10.21.2-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>bug527-test-model</artifactId>
+            <version>0.6.2-SNAPSHOT</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
 </project>
index 95f167bda0e32d6257341ada7d63d540eecd9ffe..80de7af7d40b182ba2bd1548af8cd42f9517c255 100644 (file)
@@ -24,9 +24,6 @@ import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.eclipse.xtend2.lib.StringConcatenation;
-import org.eclipse.xtext.xbase.lib.Functions;
-import org.eclipse.xtext.xbase.lib.IterableExtensions;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -56,19 +53,13 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
+import com.google.common.collect.Iterables;
 
 public class RestconfUtils {
 
     private static final Logger logger = LoggerFactory.getLogger(RestconfUtils.class);
 
-    private static final BiMap<URI,String> uriToModuleName = new Functions.Function0<BiMap<URI,String>>() {
-        @Override
-        public BiMap<URI,String> apply() {
-            HashBiMap<URI,String> _create = HashBiMap.<URI, String>create();
-            return _create;
-        }
-    }.apply();
-
+    private static final BiMap<URI,String> uriToModuleName = HashBiMap.<URI, String>create();
 
     public static Entry<String,DataSchemaNode> toRestconfIdentifier(org.opendaylight.yangtools.yang.binding.InstanceIdentifier<?> bindingIdentifier, BindingIndependentMappingService mappingService, SchemaContext schemaContext) {
         InstanceIdentifier domIdentifier = mappingService.toDataDom(bindingIdentifier);
@@ -82,8 +73,7 @@ public class RestconfUtils {
 
         final List<InstanceIdentifier.PathArgument> elements = xmlInstanceIdentifier.getPath();
         final StringBuilder ret = new StringBuilder();
-        InstanceIdentifier.PathArgument _head = IterableExtensions.<InstanceIdentifier.PathArgument>head(elements);
-        final QName startQName = _head.getNodeType();
+        final QName startQName = elements.iterator().next().getNodeType();
         URI _namespace = startQName.getNamespace();
         Date _revision = startQName.getRevision();
         final Module initialModule = schemaContext.findModuleByNamespaceAndRevision(_namespace, _revision);
@@ -104,21 +94,17 @@ public class RestconfUtils {
     }
 
     private static CharSequence convertContainerToRestconfIdentifier(final InstanceIdentifier.NodeIdentifier argument, final ContainerSchemaNode node, SchemaContext schemaContext) {
-        StringConcatenation _builder = new StringConcatenation();
-        _builder.append("/");
-        QName _nodeType = argument.getNodeType();
-        CharSequence _restconfIdentifier = toRestconfIdentifier(_nodeType,schemaContext);
-        _builder.append(_restconfIdentifier, "");
-        return _builder;
+        return "/" + toRestconfIdentifier(argument.getNodeType(), schemaContext);
     }
+
     private static CharSequence convertListToRestconfIdentifier(final InstanceIdentifier.NodeIdentifierWithPredicates argument, final ListSchemaNode node,SchemaContext schemaContext) {
         QName _nodeType = argument.getNodeType();
         final CharSequence nodeIdentifier = toRestconfIdentifier(_nodeType,schemaContext);
         final Map<QName,Object> keyValues = argument.getKeyValues();
-        StringConcatenation _builder = new StringConcatenation();
-        _builder.append("/");
-        _builder.append(nodeIdentifier, "");
-        _builder.append("/");
+
+        StringBuilder sb = new StringBuilder("/");
+        sb.append(nodeIdentifier);
+        sb.append('/');
         {
             List<QName> _keyDefinition = node.getKeyDefinition();
             boolean _hasElements = false;
@@ -126,14 +112,13 @@ public class RestconfUtils {
                 if (!_hasElements) {
                     _hasElements = true;
                 } else {
-                    _builder.appendImmediate("/", "");
+                    sb.append('/');
                 }
                 Object _get = keyValues.get(key);
-                String _uriString = toUriString(_get);
-                _builder.append(_uriString, "");
+                sb.append(toUriString(_get));
             }
         }
-        return _builder;
+        return sb.toString();
     }
     private static String toUriString(final Object object) {
         boolean _tripleEquals = (object == null);
@@ -162,12 +147,8 @@ public class RestconfUtils {
             String _name_1 = moduleSchema.getName();
             module = _name_1;
         }
-        StringConcatenation _builder = new StringConcatenation();
-        _builder.append(module, "");
-        _builder.append(":");
-        String _localName = qname.getLocalName();
-        _builder.append(_localName, "");
-        return _builder;
+
+        return module + ':' + qname.getLocalName();
     }
     private static CharSequence convertToRestconfIdentifier(final InstanceIdentifier.PathArgument argument, final DataNodeContainer node, SchemaContext schemaContext) {
         if (argument instanceof InstanceIdentifier.NodeIdentifier
@@ -203,7 +184,7 @@ public class RestconfUtils {
     }
 
     private static Module filterLatestModule(final Iterable<Module> modules) {
-        Module latestModule = IterableExtensions.<Module>head(modules);
+        Module latestModule = Iterables.getFirst(modules, null);
         for (final Module module : modules) {
             Date _revision = module.getRevision();
             Date _revision_1 = latestModule.getRevision();
diff --git a/restconf/restconf-util/src/test/java/org/opendaylight/yangtools/restconf/utils/Bug527Test.java b/restconf/restconf-util/src/test/java/org/opendaylight/yangtools/restconf/utils/Bug527Test.java
new file mode 100644 (file)
index 0000000..2f60871
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.restconf.utils;
+
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.*;
+
+import java.io.InputStream;
+
+import javassist.ClassPool;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.yang.bar.rev140321.Alpha;
+import org.opendaylight.yang.gen.v1.urn.yang.bar.rev140321.alpha.Beta;
+import org.opendaylight.yang.gen.v1.urn.yang.bar.rev140321.group.a.xcont.Xchoice;
+import org.opendaylight.yang.gen.v1.urn.yang.bar.rev140321.group.b.xcont.xchoice.Xcase;
+import org.opendaylight.yang.gen.v1.urn.yang.foo.rev140321.Beta1;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+public class Bug527Test {
+
+    private RuntimeGeneratedMappingServiceImpl mappingService;
+
+    @Before
+    public void setup() {
+        this.mappingService = new RuntimeGeneratedMappingServiceImpl();
+        this.mappingService.setPool(new ClassPool());
+        this.mappingService.init();
+
+        final ModuleInfoBackedContext moduleInfo = ModuleInfoBackedContext.create();
+        moduleInfo.addModuleInfos(BindingReflections.loadModuleInfos());
+        this.mappingService.onGlobalContextUpdated(moduleInfo.tryToCreateSchemaContext().get());
+    }
+
+    @Test
+    public void testToDataObjectMappingWithNestedAugmentations() {
+        InstanceIdentifier<Alpha> alphaId = InstanceIdentifier.builder(Alpha.class).toInstance();
+        InputStream is = this.getClass().getClassLoader().getResourceAsStream("topology-bug527.xml");
+        DataSchemaNode dataSchema = RestconfUtils.toRestconfIdentifier(alphaId, mappingService,
+                mappingService.getSchemaContext()).getValue();
+        Alpha alpha = (Alpha) RestconfUtils.dataObjectFromInputStream(alphaId, is, mappingService.getSchemaContext(),
+                mappingService, dataSchema);
+        assertNotNull(alpha);
+
+        Beta beta = alpha.getBeta();
+        Beta1 beta1 = beta.getAugmentation(Beta1.class);
+
+        Xchoice xchoice = beta1.getXcont().getXchoice();
+        assertNotNull(xchoice);
+
+        Xcase acase = (Xcase) xchoice;
+        assertEquals("idx2", acase.getIdx());
+    }
+
+}
diff --git a/restconf/restconf-util/src/test/resources/topology-bug527.xml b/restconf/restconf-util/src/test/resources/topology-bug527.xml
new file mode 100644 (file)
index 0000000..938717b
--- /dev/null
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- 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 -->
+<alpha xmlns="urn:yang:bar">
+    <beta>
+        <xcont xmlns="urn:yang:foo">
+            <idx>idx2</idx>
+        </xcont>
+    </beta>
+</alpha>
index a9309503601994f67c6eb4db970dbb5f59930eda..9a1c8df5ae31ecb16f12c60fc8d21114e0ab0341 100644 (file)
     <packaging>jar</packaging>
 
     <dependencies>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.netty</groupId>
             <artifactId>netty-codec-http</artifactId>
index 9f94887f9a6e0b35740a1597155e8687404f2b4b..a5bbb87b491dc37af1bbf0dc87030281f48bcadd 100644 (file)
@@ -7,60 +7,95 @@
  */
 package org.opendaylight.yangtools.websocket;
 
-import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
 import java.net.URI;
 import java.net.URISyntaxException;
+
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.yangtools.websocket.client.WebSocketIClient;
-import org.opendaylight.yangtools.websocket.server.WebSocketServer;
+import org.junit.Assert;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.opendaylight.yangtools.websocket.client.WebSocketIClient;
+import org.opendaylight.yangtools.websocket.server.WebSocketServer;
+
+import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
+
+import com.google.common.util.concurrent.SettableFuture;
+
 public class WebSocketClientTest {
     private static final Logger logger = LoggerFactory.getLogger(WebSocketClientTest.class.toString());
     private static final String MESSAGE = "Take me to your leader!";
-    private static final int port = 8080;
     private Thread webSocketServerThread;
 
+    /**
+     * Tracks if the message from the server has been received
+     */
+    private SettableFuture<Boolean> messageReceived = SettableFuture.<Boolean>create();
+
+    /**
+     * Tracks the port on which the server is listening
+     */
+    private int port = 0;
 
     @Before
     public void startWebSocketServer(){
         try {
-            WebSocketServer webSocketServer = new WebSocketServer(port);
+            WebSocketServer webSocketServer = new WebSocketServer(0);
             webSocketServerThread = new Thread(webSocketServer);
             webSocketServerThread.setDaemon(false);
             webSocketServerThread.start();
+            port = webSocketServer.getPort().get();
         } catch (Exception e) {
             logger.trace("Error starting websocket server");
         }
     }
+
     @Test
     public void connectAndSendData(){
 
         URI uri = null;
         try {
-            uri = new URI("ws://localhost:8080/websocket");
+            uri = new URI(String.format("ws://localhost:%d/websocket", port));
+            logger.info("CLIENT: " + uri);
             ClientMessageCallback messageCallback = new ClientMessageCallback();
             WebSocketIClient wsClient = new WebSocketIClient(uri,messageCallback);
             try {
                 wsClient.connect();
                 wsClient.writeAndFlush(MESSAGE);
                 wsClient.writeAndFlush(new CloseWebSocketFrame());
+
+                /*
+                 * Wait for up to 5 seconds for the message to be received. If
+                 * after that time, the message has not been received then
+                 * consider this a failed test.
+                 */
+                messageReceived.get(5, TimeUnit.SECONDS);
+
                 webSocketServerThread.interrupt();
             } catch (InterruptedException e) {
-                logger.info("WebSocket client couldn't connect to : "+uri);
+                logger.info("WebSocket client couldn't connect to : " + uri);
+                Assert.fail("WebSocker client could not connect to : " + uri);
+            } catch (ExecutionException | TimeoutException toe) {
+                logger.info("Message not received");
+                Assert.fail(toe.toString());
             }
         } catch (URISyntaxException e) {
             logger.info("There is an error in URL sytnax {}",e);
+            Assert.fail("There is an error in URL sytnax");
         }
     }
 
     private class ClientMessageCallback implements org.opendaylight.yangtools.websocket.client.callback.ClientMessageCallback {
         @Override
         public void onMessageReceived(Object message) {
-           logger.info("received message {}",message);
-           System.out.println("received message : " + message);
+            logger.info("received message {}",message);
+            messageReceived.set(true);
         }
     }
 }
index 08d51b3f6815972620b3e37470472d2355be9f99..8fb379cb79d30182842080c88a9e9b9661d75071 100644 (file)
@@ -20,9 +20,20 @@ import io.netty.channel.Channel;
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.channel.socket.nio.NioServerSocketChannel;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.net.SocketAddress;
+import java.net.InetSocketAddress;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+import com.google.common.util.concurrent.SettableFuture;
+
 /**
  * A HTTP server which serves Web Socket requests at:
  *
@@ -44,19 +55,28 @@ import org.slf4j.LoggerFactory;
  */
 public class WebSocketServer implements Runnable {
 
-    private final int port;
+    /**
+     * Utilized to get the port on which the server listens. This is a future as
+     * the port is selected dynamically from available ports, thus until the
+     * server is started the value will not be established.
+     */
+    private final SettableFuture<Integer> port;
+
+    /**
+     * Maintains the port number with which the class was initialized.
+     */
+    private final int inPort;
     private final ServerBootstrap bootstrap = new ServerBootstrap();
     private final EventLoopGroup bossGroup = new NioEventLoopGroup();
     private final EventLoopGroup workerGroup = new NioEventLoopGroup();
     private static final Logger logger = LoggerFactory.getLogger(WebSocketServer.class.toString());
 
-    public WebSocketServer(int port) {
-        this.port = port;
+
+    public WebSocketServer(int inPort) {
+        this.inPort = inPort;
+        port = SettableFuture.<Integer>create();
     }
 
-    /**
-     * Tries to start web socket server. 
-     */
     public void run(){
         try {
             startServer();
@@ -64,27 +84,35 @@ public class WebSocketServer implements Runnable {
             logger.info("Exception occured while starting webSocket server {}",e);
         }
     }
-    
-    /**
-     * Start web socket server at {@link #port}.
-     * @throws Exception
-     */
+
+    public Future<Integer> getPort() {
+        return port;
+    }
+
     public void startServer() throws Exception {
         try {
             bootstrap.group(bossGroup, workerGroup)
              .channel(NioServerSocketChannel.class)
              .childHandler(new WebSocketServerInitializer());
 
-            Channel ch = bootstrap.bind(port).sync().channel();
-            logger.info("Web socket server started at port " + port + '.');
-            logger.info("Open your browser and navigate to http://localhost:" + port + '/');
+            Channel ch = bootstrap.bind(inPort).sync().channel();
+            SocketAddress localSocket = ch.localAddress();
+            try {
+                port.set(((InetSocketAddress) localSocket).getPort());
+            } catch (ClassCastException cce) {
+                throw new ExecutionException("Unknown socket address type", cce);
+            }
+            logger.info("Web socket server started at port " + port.get() + '.');
+            logger.info("Open your browser and navigate to http://localhost:" + port.get() + '/');
 
-            ch.closeFuture().sync();
+            try {
+                ch.closeFuture().sync();
+            } catch (InterruptedException ie) {
+                // No op, sometimes the server is shutdown hard
+            }
         } finally {
             bossGroup.shutdownGracefully();
             workerGroup.shutdownGracefully();
         }
     }
-
-
 }
index 21ded106a35ad624e84323599a58cfb43625fdb0..5cbc84271de3ccdb5dd7c02d37cfc2e6b63e0afc 100644 (file)
@@ -25,6 +25,7 @@
         <module>yang-data-api</module>
         <module>yang-data-util</module>
         <module>yang-data-impl</module>
+        <module>yang-data-operations</module>
         <module>yang-model-api</module>
         <module>yang-maven-plugin</module>
         <module>yang-maven-plugin-it</module>
@@ -32,6 +33,7 @@
         <module>yang-model-util</module>
         <module>yang-parser-api</module>
         <module>yang-parser-impl</module>
+        <module>yang-data-json</module>
     </modules>
 
     <properties>
                 <artifactId>yang-data-api</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-data-impl</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-data-json</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.yangtools</groupId>
                 <artifactId>yang-data-util</artifactId>
index aad6a72e55cb6d7a9ec42d71c3484568126c485c..ff75bd1d0ef99193dcd525aff93c22024d4d2202 100644 (file)
@@ -18,9 +18,32 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 
 /**
- * Uniquely identifies data location in the overall of data tree
- * modeled by YANG.
  *
+ * This instance identifier uniquely identifies a specific DataObject in the data tree modeled by YANG.
+ *
+ * For Example let's say you were trying to refer to a node in inventory which was modeled in YANG as follows,
+ *
+ * <pre>
+ * module opendaylight-inventory {
+ *      ....
+ *
+ *      container nodes {
+ *        list node {
+ *            key "id";
+ *            ext:context-instance "node-context";
+ *
+ *            uses node;
+ *        }
+ *    }
+ *
+ * }
+ * </pre>
+ *
+ * You could create an instance identifier as follows to get to a node with id "openflow:1"
+ *
+ * InstanceIdentifierBuilder.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:1")).build();
+ *
+ * This would be the same as using a path like so, "/nodes/node/openflow:1" to refer to the openflow:1 node
  *
  */
 public final class InstanceIdentifier<T extends DataObject> implements Path<InstanceIdentifier<? extends DataObject>>,Immutable {
@@ -28,11 +51,33 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
     private final List<PathArgument> path;
     private final Class<T> targetType;
 
+    /**
+     * Create an instance identifier for a very specific object type.
+     *
+     * For example
+     * <pre>
+     *      new InstanceIdentifier(Nodes.class)
+     * </pre>
+     * would create an InstanceIdentifier for an object of type Nodes
+     *
+     * @param type The type of the object which this instance identifier represents
+     */
     public InstanceIdentifier(Class<T> type) {
-        path = Collections.<PathArgument> singletonList(new Item<>(type));
-        this.targetType = type;
+        this(Collections.<PathArgument> singletonList(new Item<>(type)), type);
     }
 
+    /**
+     * Create an instance identifier for a very specific object type.
+     *
+     * Example
+     * <pre>
+     *  List<PathArgument> path = Arrays.asList(new Item(Nodes.class))
+     *  new InstanceIdentifier(path, Nodes.class);
+     * </pre>
+     *
+     * @param path The path to a specific node in the data tree
+     * @param type The type of the object which this instance identifier represents
+     */
     public InstanceIdentifier(List<PathArgument> path, Class<T> type) {
         this.path = ImmutableList.copyOf(path);
         this.targetType = type;
@@ -40,16 +85,25 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
 
     /**
      *
-     * @return path
+     * @return A list of the elements of the path
      */
     public List<PathArgument> getPath() {
         return getPathArguments();
     }
 
+    /**
+     *
+     * @return A list of the elements of the path
+     */
+
     public List<PathArgument> getPathArguments() {
         return this.path;
     }
 
+    /**
+     *
+     * @return The target type of this instance identifier
+     */
     public Class<T> getTargetType() {
         return this.targetType;
     }
@@ -63,6 +117,17 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
      * Return an instance identifier trimmed at the first occurrence of a
      * specific component type.
      *
+     * For example let's say an instance identifier was built like so,
+     * <pre>
+     *      identifier = InstanceIdentifierBuilder.builder(Nodes.class).child(Node.class, new NodeKey(new NodeId("openflow:1")).build();
+     * </pre>
+     *
+     * And you wanted to obtain the Instance identifier which represented Nodes you would do it like so,
+     *
+     * <pre>
+     *      identifier.firstIdentifierOf(Nodes.class)
+     * </pre>
+     *
      * @param type component type
      * @return trimmed instance identifier, or null if the component type
      *         is not present.
@@ -126,6 +191,13 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
         Class<? extends DataObject> getType();
     }
 
+
+    /**
+     * An Item represents an object that probably is only one of it's kind. For example a Nodes object is only one of
+     * a kind. In YANG terms this would probably represent a container.
+     *
+     * @param <T>
+     */
     public static final class Item<T extends DataObject> implements PathArgument {
         private final Class<T> type;
 
@@ -169,6 +241,13 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
         }
     }
 
+    /**
+     * An IdentifiableItem represents a object that is usually present in a collection and can be identified uniquely
+     * by a key. In YANG terms this would probably represent an item in a list.
+     *
+     * @param <I> An object that is identifiable by an identifier
+     * @param <T> The identifier of the object
+     */
     public static final class IdentifiableItem<I extends Identifiable<T> & DataObject, T extends Identifier<I>> implements
             PathArgument {
 
@@ -233,13 +312,57 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
         <N extends Identifiable<K> & DataObject, K extends Identifier<N>> InstanceIdentifierBuilder<N> node(
                 Class<N> listItem, K listKey);
 
+        /**
+         * Append the specified container as a child of the current InstanceIdentifier referenced by the builder.
+         *
+         * This method should be used when you want to build an instance identifier by appending top-level
+         * elements
+         *
+         * Example,
+         * <pre>
+         *     InstanceIdentifier.builder().child(Nodes.class).build();
+         *
+         * </pre>
+         *
+         * NOTE :- The above example is only for illustration purposes InstanceIdentifier.builder() has been deprecated
+         * and should not be used. Use InstanceIdentifier.builder(Nodes.class) instead
+         *
+         * @param container
+         * @param <N>
+         * @return
+         */
         <N extends ChildOf<? super T>> InstanceIdentifierBuilder<N> child(Class<N> container);
 
+        /**
+         * Append the specified listItem as a child of the current InstanceIdentifier referenced by the builder.
+         *
+         * This method should be used when you want to build an instance identifier by appending a specific list element
+         * to the identifier
+         *
+         * @param listItem
+         * @param listKey
+         * @param <N>
+         * @param <K>
+         * @return
+         */
         <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> InstanceIdentifierBuilder<N> child(
                 Class<N> listItem, K listKey);
 
+        /**
+         * Build an identifier which refers to a specific augmentation of the current InstanceIdentifier referenced by
+         * the builder
+         *
+         * @param container
+         * @param <N>
+         * @return
+         */
         <N extends DataObject & Augmentation<? super T>> InstanceIdentifierBuilder<N> augmentation(Class<N> container);
 
+        /**
+         * Build the instance identifier.
+         *
+         * @return
+         */
         InstanceIdentifier<T> build();
 
     }
@@ -253,15 +376,38 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
         return new BuilderImpl();
     }
 
+    /**
+     * Create an InstanceIdentifierBuilder for a specific type of InstanceIdentifier as specified by container
+     *
+     * @param container
+     * @param <T>
+     * @return
+     */
     public static <T extends ChildOf<? extends DataRoot>> InstanceIdentifierBuilder<T> builder(Class<T> container) {
         return new BuilderImpl<T>().addNode(container);
     }
 
+    /**
+     * Create an InstanceIdentifierBuilder for a specific type of InstanceIdentifier which represents an IdentifiableItem
+     *
+     * @param listItem
+     * @param listKey
+     * @param <N>
+     * @param <K>
+     * @return
+     */
     public static <N extends Identifiable<K> & ChildOf<? extends DataRoot>, K extends Identifier<N>> InstanceIdentifierBuilder<N> builder(
             Class<N> listItem, K listKey) {
         return new BuilderImpl<N>().addNode(listItem, listKey);
     }
 
+    /**
+     * Create a new InstanceIdentifierBuilder given a base InstanceIdentifier
+     *
+     * @param basePath
+     * @param <T>
+     * @return
+     */
     public static <T extends DataObject> InstanceIdentifierBuilder<T> builder(InstanceIdentifier<T> basePath) {
         return new BuilderImpl<T>(basePath.path,basePath.targetType);
     }
@@ -373,6 +519,24 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
         return true;
     }
 
+    /**
+     * The contains method checks if the other identifier is fully contained within the current identifier. It does this
+     * by looking at only the types of the path arguments and not by comparing the path arguments themselse.
+     * If you want to compare path arguments you must use containsWildcarded
+     *
+     * To illustrate here is an example which explains the working of this api.
+     *
+     * Let's say you have two instance identifiers as follows,
+     *
+     * this = /nodes/node/openflow:1
+     * other = /nodes/node/openflow:2
+     *
+     * then this.contains(other) will return true. To ensure that this and other are compared properly you must use
+     * containsWildcarded
+     *
+     * @param other
+     * @return
+     */
     @Override
     public boolean contains(final InstanceIdentifier<?> other) {
         if(other == null) {
@@ -391,6 +555,13 @@ public final class InstanceIdentifier<T extends DataObject> implements Path<Inst
         return true;
     }
 
+    /**
+     * The containsWildcarded method checks if the other identifier is fully contained within the current identifier.
+     * It does this by looking at both the type and identity of the path arguments.
+     *
+     * @param other
+     * @return
+     */
     public boolean containsWildcarded(final InstanceIdentifier<?> other) {
         if(other == null) {
             throw new IllegalArgumentException("other should not be null");
index 074624b1e53ea4bc9a5d6259a12fe09cb124232f..792ccd0ccf2018ede2d1dac58043a92a376a98c3 100644 (file)
@@ -7,7 +7,10 @@
  */
 package org.opendaylight.yangtools.yang.binding.test;
 
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
@@ -23,18 +26,18 @@ public class InstanceIdentifierTest {
 
     @Test
     public void constructWithPredicates() {
-        
+
         InstanceIdentifier<Nodes> nodes = InstanceIdentifier.builder(Nodes.class).toInstance();
-        
+
         assertNotNull(nodes);
         assertEquals(Nodes.class, nodes.getTargetType());
-        
-        
-        InstanceIdentifier<Node> node = InstanceIdentifier.builder(nodes).node(Node.class).toInstance();
-        
+
+
+        InstanceIdentifier<Node> node = InstanceIdentifier.builder(nodes).child(Node.class).toInstance();
+
         assertNotNull(node);
         assertEquals(Node.class, node.getTargetType());
-        
+
         assertTrue(nodes.contains(node));
     }
 
@@ -49,25 +52,25 @@ public class InstanceIdentifierTest {
 
         assertTrue(nodes.contains(node));
     }
-   
-    
+
+
     @Test
     public void negativeContains() {
         InstanceIdentifier<FooChild> fooChild = InstanceIdentifier.builder(Nodes.class).child(InstantiatedFoo.class).child(FooChild.class).build();
-        
+
         InstanceIdentifier<Node> nodeTen = InstanceIdentifier.builder(Nodes.class) //
                 .child(Node.class,new NodeKey(10)).toInstance();
         InstanceIdentifier<Node> nodeOne = InstanceIdentifier.builder(Nodes.class) //
                 .child(Node.class,new NodeKey(1)).toInstance();
         InstanceIdentifier<Nodes> nodes = InstanceIdentifier.builder(Nodes.class).toInstance();
-    
+
         assertFalse(fooChild.contains(nodeTen));
         assertFalse(nodeTen.contains(nodes));
-        
+
         assertFalse(nodeOne.contains(nodes));
         assertTrue(nodes.contains(nodeOne));
     }
-    
+
     @Test
     public void containsWildcarded() {
         InstanceIdentifier<Nodes> nodes = InstanceIdentifier.builder(Nodes.class).toInstance();
@@ -75,40 +78,40 @@ public class InstanceIdentifierTest {
         InstanceIdentifier<NodeChild> wildcardedChildren = InstanceIdentifier.builder(Nodes.class) //
                 .child(Node.class) //
                 .child(NodeChild.class).build();
-        
+
         assertTrue(wildcarded.isWildcarded());
         assertTrue(wildcardedChildren.isWildcarded());
-        
-        
+
+
         InstanceIdentifier<Node> nodeTen = InstanceIdentifier.builder(Nodes.class) //
                 .child(Node.class,new NodeKey(10)).toInstance();
         InstanceIdentifier<Node> nodeOne = InstanceIdentifier.builder(Nodes.class) //
                 .child(Node.class,new NodeKey(1)).toInstance();
-        
+
         assertFalse(nodeTen.isWildcarded());
         assertFalse(nodeOne.isWildcarded());
         assertTrue(nodes.containsWildcarded(nodeOne));
         assertTrue(wildcarded.containsWildcarded(nodeOne));
         assertTrue(wildcarded.containsWildcarded(nodeTen));
-        
-        
+
+
         InstanceIdentifier<NodeChild> nodeTenChildWildcarded = InstanceIdentifier.builder(Nodes.class) //
                 .child(Node.class,new NodeKey(10)).child(NodeChild.class).toInstance();
-        
+
         assertTrue(nodeTenChildWildcarded.isWildcarded());
-        
+
         InstanceIdentifier<NodeChild> nodeTenChild = InstanceIdentifier.builder(Nodes.class) //
                 .child(Node.class,new NodeKey(10)).child(NodeChild.class, new NodeChildKey(10)).toInstance();
         InstanceIdentifier<NodeChild> nodeOneChild = InstanceIdentifier.builder(Nodes.class) //
                 .child(Node.class,new NodeKey(1)).child(NodeChild.class, new NodeChildKey(1)).toInstance();
 
-        
+
         assertFalse(nodeTenChildWildcarded.containsWildcarded(nodeOneChild));
         assertTrue(nodeTenChildWildcarded.containsWildcarded(nodeTenChild));
-        
+
     }
-    
-    
+
+
     void childOfTest() {
         InstanceIdentifier.builder(Nodes.class).child(InstantiatedFoo.class).child(FooChild.class);
     }
index f78427840ca1bd81fd231a3d144a5703fa7c7cdc..4c915fb8474209a24a86b4538fc4ea3466a7a34e 100644 (file)
@@ -11,8 +11,8 @@ import org.opendaylight.yangtools.yang.binding.Identifier;
 
 public class NodeChildKey implements //
         Identifier<NodeChild> {
-
-    private final int id;
+       private static final long serialVersionUID = 1L;
+       private final int id;
 
     public NodeChildKey(int id) {
         super();
index 295b6e5765628047e899ae528d881ce445ab23b3..7b83790c7537fca4937673db8b958c9a7144631b 100644 (file)
@@ -11,8 +11,8 @@ import org.opendaylight.yangtools.yang.binding.Identifier;
 
 public class NodeKey implements //
         Identifier<Node> {
-
-    private final int id;
+       private static final long serialVersionUID = 1L;
+       private final int id;
 
     public NodeKey(int id) {
         super();
index 00aaccc1ff3af27ef0ea38c8e9a80ae98d5e72e1..befb17f811cd366e26eb8ab58a450cd45b91e058 100644 (file)
@@ -42,7 +42,7 @@ import static org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil.getRev
  *
  *
  */
-public final class QName implements Immutable,Serializable {
+public final class QName implements Immutable, Serializable, Comparable<QName> {
 
     private static final long serialVersionUID = 5398411242927766414L;
 
@@ -372,4 +372,46 @@ public final class QName implements Immutable,Serializable {
     public boolean isEqualWithoutRevision(QName other) {
         return localName.equals(other.getLocalName()) && Objects.equals(namespace, other.getNamespace());
     }
+
+    @Override
+    public int compareTo(QName other) {
+        // compare mandatory localName parameter
+        int result = localName.compareTo(other.localName);
+        if (result != 0) {
+            return result;
+        }
+
+        // compare nullable namespace parameter
+        if (namespace == null) {
+            if (other.namespace != null) {
+                return -1;
+            }
+        } else {
+            if (other.namespace == null) {
+                return 1;
+            }
+            result = namespace.compareTo(other.namespace);
+            if (result != 0) {
+                return result;
+            }
+        }
+
+        // compare nullable revision parameter
+        if (revision == null) {
+            if (other.revision != null) {
+                return -1;
+            }
+        } else {
+            if (other.revision == null) {
+                return 1;
+            }
+            result = revision.compareTo(other.revision);
+            if (result != 0) {
+                return result;
+            }
+        }
+
+        return result;
+    }
+
 }
index 23ca2ee2a37c7af7afb89858c20c57e06d4306ba..410bca2b82090c6b32c4ab1c37092489c345d5e5 100644 (file)
@@ -11,8 +11,7 @@ import org.junit.Test;
 
 import java.net.URI;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.fail;
+import static org.junit.Assert.*;
 
 public class QNameTest {
     private final String namespace = "urn:foo", revision = "2013-12-24", localName = "bar";
@@ -58,6 +57,57 @@ public class QNameTest {
         assertLocalNameFails("&");
     }
 
+    @Test
+    public void testCompareTo() throws Exception {
+        String A = "a";
+        String B = "b";
+
+        QName a = QName.create(A);
+        QName b = QName.create(A);
+        assertTrue(a.compareTo(b) == 0);
+        assertTrue(b.compareTo(a) == 0);
+
+        // compare with localName
+        a = QName.create(A);
+        b = QName.create(B);
+        assertTrue(a.compareTo(b) < 0);
+        assertTrue(b.compareTo(a) > 0);
+
+        // compare with namespace
+        a = QName.create(A, revision, A);
+        b = QName.create(B, revision, A);
+        assertTrue(a.compareTo(b) < 0);
+        assertTrue(b.compareTo(a) > 0);
+
+        // compare with 1 null namespace
+        a = new QName(null, QName.parseRevision(revision), A);
+        b = new QName(URI.create(A), QName.parseRevision(revision), A);
+        assertTrue(a.compareTo(b) < 0);
+        assertTrue(b.compareTo(a) > 0);
+
+        // compare with both null namespace
+        b = new QName(null, QName.parseRevision(revision), A);
+        assertTrue(a.compareTo(b) == 0);
+        assertTrue(b.compareTo(a) == 0);
+
+        // compare with revision
+        a = QName.create(A, "2013-12-24", A);
+        b = QName.create(A, "2013-12-25", A);
+        assertTrue(a.compareTo(b) < 0);
+        assertTrue(b.compareTo(a) > 0);
+
+        // compare with 1 null revision
+        a = new QName(URI.create(A), null, A);
+        b = new QName(URI.create(A), QName.parseRevision(revision), A);
+        assertTrue(a.compareTo(b) < 0);
+        assertTrue(b.compareTo(a) > 0);
+
+        // compare with both null revision
+        b = new QName(URI.create(A), null, A);
+        assertTrue(a.compareTo(b) == 0);
+        assertTrue(b.compareTo(a) == 0);
+    }
+
     private void assertLocalNameFails(String localName) {
         try {
             new QName((URI)null, localName);
index f3a6c3800fe6d5fdd2c765ca204ce73602a245ce..174ae31000d90a9be813dd204adf9166f5cc5949 100644 (file)
@@ -354,6 +354,33 @@ public class InstanceIdentifier implements Path<InstanceIdentifier>, 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 {
index 8ddcf6899668903117507322ad49871411ac7d4e..e9634e5e8553b9b156d096aec2919993bf00e0ad 100644 (file)
@@ -7,12 +7,14 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 
 import com.google.common.base.Optional;
 
 public interface ContainerNode extends //
+        AttributesContainer,
         DataContainerNode<NodeIdentifier>,
         DataContainerChild<NodeIdentifier, Iterable<DataContainerChild<? extends PathArgument, ?>>> {
 
index 9347bdc5baf684b37dd5dd2fe8c274d1b69c6e1c..f82d78f7bb63434491909be768f25141f30d7323 100644 (file)
@@ -7,9 +7,11 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 
 public interface LeafNode<T> extends //
+        AttributesContainer,
         DataContainerChild<NodeIdentifier, T> {
 
     @Override
index 3209b5eed5a3f810d9c44965448f6e007bb0e570..e8d56ae5f8da725a7d9841b0c269c174902de530 100644 (file)
@@ -7,9 +7,12 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
 
-public interface LeafSetEntryNode<T> extends NormalizedNode<NodeWithValue, T> {
+public interface LeafSetEntryNode<T> extends
+        AttributesContainer,
+        NormalizedNode<NodeWithValue, T> {
 
     @Override
     public NodeWithValue getIdentifier();
index 69e9dd9bda7667d71941dd41d809f7bfa10f9046..445f8c34fe5c2709657ac0d865cad9c036b04c09 100644 (file)
@@ -7,9 +7,12 @@
  */
 package org.opendaylight.yangtools.yang.data.api.schema;
 
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
 
-public interface MapEntryNode extends DataContainerNode<NodeIdentifierWithPredicates> {
+public interface MapEntryNode extends
+        AttributesContainer,
+        DataContainerNode<NodeIdentifierWithPredicates> {
 
     @Override
     public NodeIdentifierWithPredicates getIdentifier();
index a4e2ef8a82d9688e664e5f7b32e1772b4f721cd3..013bbcc357a2b9974c5915c0705c698172c88b9b 100644 (file)
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
-            <artifactId>yang-binding</artifactId>
+            <artifactId>yang-model-api</artifactId>
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
-            <artifactId>yang-parser-impl</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-simple</artifactId>
-                </exclusion>
-            </exclusions>
+            <artifactId>yang-model-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-binding</artifactId>
         </dependency>
         <dependency>
             <groupId>com.google.guava</groupId>
             <version>1.5</version>
             <scope>test</scope>
         </dependency>
-      <dependency>
-        <groupId>commons-lang</groupId>
-        <artifactId>commons-lang</artifactId>
-        <version>2.6</version>
-      </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.6</version>
+        </dependency>
     </dependencies>
 </project>
index a1fa857775319ca249d50484604bf22d16703b23..8cb399584d0343b27b5a745c08d9d42ead4cd35b 100644 (file)
@@ -58,23 +58,23 @@ import com.google.common.collect.ImmutableSet;
 import com.google.common.io.BaseEncoding;
 
 public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> implements DataStringCodec<J> {
-    
+
     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<T> typeDefinition;
     private final Class<J> 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<J, T extends TypeDefinition<T>> 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<J, T extends TypeDefinition<T>> i
             }
         }
     }
-    
+
     private static String normalizeHexadecimal(final String hexInt) {
         if (hexInt == null) {
             throw new IllegalArgumentException(
@@ -111,7 +111,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
         }
         return normalizedString;
     }
-    
+
     public static final BinaryCodecStringImpl BINARY_DEFAULT_CODEC = new BinaryCodecStringImpl(
             Optional.<BinaryTypeDefinition> absent());
 
index 9f034543d7c659ff7dcc8999bf0914c341c03a7f..7345d3dded5ae16c61256750213fa988ebafb76e 100644 (file)
@@ -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;
index 09823823630f7b4ca9e52b57d8c0c4886b099fca..439857807b3eef2e44d177034a9695590e50d0d5 100644 (file)
 package org.opendaylight.yangtools.yang.data.impl.schema;
 
 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.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.LeafSetEntryNode;
+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.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.*;
-import org.opendaylight.yangtools.yang.model.api.*;
-
-public class Builders {
-
-    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> leafBuilder() {
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeSchemaAwareBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeSchemaAwareBuilder;
+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;
+
+public final class Builders {
+
+    private Builders() {
+        throw new UnsupportedOperationException("Utilities class should not be instantiated");
+    }
+
+    public static <T> NormalizedNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> leafBuilder() {
         return ImmutableLeafNodeBuilder.create();
     }
 
-    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> leafBuilder(
-            LeafSchemaNode schema) {
+    public static <T> NormalizedNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> leafBuilder(
+            final LeafSchemaNode schema) {
         return ImmutableLeafNodeSchemaAwareBuilder.create(schema);
     }
 
-    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> leafSetEntryBuilder() {
+    public static <T> NormalizedNodeAttrBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> leafSetEntryBuilder() {
         return ImmutableLeafSetEntryNodeBuilder.create();
     }
 
-    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> leafSetEntryBuilder(
-            LeafListSchemaNode schema) {
+    public static <T> NormalizedNodeAttrBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> leafSetEntryBuilder(
+            final LeafListSchemaNode schema) {
         return ImmutableLeafSetEntryNodeSchemaAwareBuilder.create(schema);
     }
 
-    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> leafSetBuilder() {
+    public static <T> ListNodeBuilder<T,LeafSetEntryNode<T>> leafSetBuilder() {
         return ImmutableLeafSetNodeBuilder.create();
     }
 
-    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> leafSetBuilder(LeafListSchemaNode schema) {
-        return ImmutableLeafSetNodeSchemaAwareBuilder.create(schema);
+    public static <T> ListNodeBuilder<T,LeafSetEntryNode<T>> leafSetBuilder(final LeafSetNode<T> node) {
+        return ImmutableLeafSetNodeBuilder.create(node);
+    }
+
+    public static <T> ListNodeBuilder<T,LeafSetEntryNode<T>> leafSetBuilder(final LeafListSchemaNode schema) {
+        return ImmutableLeafSetNodeSchemaAwareBuilder.<T>create(schema);
     }
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> containerBuilder() {
+    public static <T> ListNodeBuilder<T,LeafSetEntryNode<T>> leafSetBuilder(final LeafListSchemaNode schema, final LeafSetNode<T> node) {
+        return ImmutableLeafSetNodeSchemaAwareBuilder.<T>create(schema, node);
+    }
+
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> containerBuilder() {
         return ImmutableContainerNodeBuilder.create();
     }
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> containerBuilder(
-            ContainerSchemaNode schema) {
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> containerBuilder(final ContainerNode node) {
+        return ImmutableContainerNodeBuilder.create(node);
+    }
+
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> containerBuilder(
+            final ContainerSchemaNode schema) {
         return ImmutableContainerNodeSchemaAwareBuilder.create(schema);
     }
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder() {
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> containerBuilder(
+            final ContainerSchemaNode schema, final ContainerNode node) {
+        return ImmutableContainerNodeSchemaAwareBuilder.create(schema, node);
+    }
+
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder() {
         return ImmutableMapEntryNodeBuilder.create();
     }
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder(
-            ListSchemaNode schema) {
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder(
+            final ListSchemaNode schema) {
         return ImmutableMapEntryNodeSchemaAwareBuilder.create(schema);
     }
 
@@ -67,15 +114,23 @@ public class Builders {
         return ImmutableMapNodeBuilder.create();
     }
 
-    public static CollectionNodeBuilder<MapEntryNode, MapNode> mapBuilder(ListSchemaNode schema) {
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> mapBuilder(final MapNode node) {
+        return ImmutableMapNodeBuilder.create(node);
+    }
+
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> mapBuilder(final ListSchemaNode schema) {
         return ImmutableMapNodeSchemaAwareBuilder.create(schema);
     }
 
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> mapBuilder(final ListSchemaNode schema, final MapNode node) {
+        return ImmutableMapNodeSchemaAwareBuilder.create(schema, node);
+    }
+
     public static DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> augmentationBuilder() {
         return ImmutableAugmentationNodeBuilder.create();
     }
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> augmentationBuilder(AugmentationSchema schema) {
+    public static DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> augmentationBuilder(final AugmentationSchema schema) {
         return ImmutableAugmentationNodeSchemaAwareBuilder.create(schema);
     }
 
@@ -83,7 +138,7 @@ public class Builders {
         return ImmutableChoiceNodeBuilder.create();
     }
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> choiceBuilder(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> choiceBuilder(final org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
         return ImmutableChoiceNodeSchemaAwareBuilder.create(schema);
     }
 
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/ImmutableNodes.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/ImmutableNodes.java
new file mode 100644 (file)
index 0000000..21e2792
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
+
+public final class ImmutableNodes {
+
+    private ImmutableNodes() {
+        throw new UnsupportedOperationException("Utilities class should not be instantiated");
+    }
+
+    public static final CollectionNodeBuilder<MapEntryNode, MapNode> mapNodeBuilder() {
+        return ImmutableMapNodeBuilder.create();
+    }
+
+    public static final CollectionNodeBuilder<MapEntryNode, MapNode> mapNodeBuilder(final QName name) {
+        return ImmutableMapNodeBuilder.create().withNodeIdentifier(new NodeIdentifier(name));
+    }
+
+    public static final <T> LeafNode<T> leafNode(final QName name,final T value) {
+        return ImmutableLeafNodeBuilder.<T>create()
+                .withNodeIdentifier(new NodeIdentifier(name))
+                .withValue(value)
+                .build();
+    }
+
+    public static DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder(final QName nodeName,final QName keyName,final Object keyValue) {
+        return ImmutableMapEntryNodeBuilder.create()
+                .withNodeIdentifier(new NodeIdentifierWithPredicates(nodeName, keyName,keyValue))
+                .withChild(leafNode(keyName, keyValue));
+    }
+
+    public static MapEntryNode mapEntry(final QName nodeName,final QName keyName,final Object keyValue) {
+        return mapEntryBuilder(nodeName, keyName, keyValue).build();
+    }
+
+    public static DataContainerNodeBuilder<NodeIdentifierWithPredicates, MapEntryNode> mapEntryBuilder() {
+        return ImmutableMapEntryNodeBuilder.create();
+    }
+
+    public static NormalizedNode<?, ?> containerNode(final QName name) {
+        return ImmutableContainerNodeBuilder.create().withNodeIdentifier(new NodeIdentifier(name)).build();
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedNodeUtils.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/NormalizedNodeUtils.java
new file mode 100644 (file)
index 0000000..2e9b90e
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.Iterator;
+
+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.schema.DataContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+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.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+public final class NormalizedNodeUtils {
+    private NormalizedNodeUtils() {
+        throw new UnsupportedOperationException("Utilities class should not be instantiated");
+    }
+
+    public static Optional<NormalizedNode<?, ?>> findNode(final InstanceIdentifier rootPath, final NormalizedNode<?, ?> rootNode, final InstanceIdentifier childPath) {
+        if(rootPath.contains(childPath)) {
+            int common = rootPath.getPath().size();
+            InstanceIdentifier relativePath = new InstanceIdentifier(childPath.getPath().subList(common, childPath.getPath().size()));
+            return findNode(rootNode, relativePath);
+        }
+        return Optional.absent();
+    }
+
+    public static Optional<NormalizedNode<?, ?>> findNode(final NormalizedNode<?, ?> tree, final InstanceIdentifier path) {
+        checkNotNull(tree, "Tree must not be null");
+        checkNotNull(path, "Path must not be null");
+
+        Optional<NormalizedNode<?, ?>> currentNode = Optional.<NormalizedNode<?, ?>> of(tree);
+        Iterator<PathArgument> pathIterator = path.getPath().iterator();
+        while (currentNode.isPresent() && pathIterator.hasNext()) {
+            currentNode = getDirectChild(currentNode.get(), pathIterator.next());
+        }
+        return currentNode;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    public static Optional<NormalizedNode<?, ?>> getDirectChild(final NormalizedNode<?, ?> node, final PathArgument pathArg) {
+        if (node instanceof LeafNode<?> || node instanceof LeafSetEntryNode<?>) {
+            return Optional.absent();
+        } else if (node instanceof DataContainerNode<?>) {
+            return (Optional) ((DataContainerNode<?>) node).getChild(pathArg);
+        } else if (node instanceof MapNode && pathArg instanceof NodeIdentifierWithPredicates) {
+            return (Optional) ((MapNode) node).getChild((NodeIdentifierWithPredicates) pathArg);
+        } else if (node instanceof LeafSetNode<?>) {
+            return (Optional) ((LeafSetNode<?>) node).getChild((NodeWithValue) pathArg);
+        }
+        return Optional.absent();
+    }
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/AttributesBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/AttributesBuilder.java
new file mode 100644 (file)
index 0000000..32172d2
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.builder.api;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+public interface AttributesBuilder<B> {
+    /**
+     * Attach a map of attributes. The map is expected to remain unchanged,
+     * otherwise undefined behavior may occur.
+     *
+     * @param attributes Attribute map
+     * @return Builder instance, such that fluent use is possible
+     */
+    B withAttributes(Map<QName, String> attributes);
+}
index 2dc68a9a828daafa18c473f3f6f4f749761ab044..9972d627a1be7fde08ab0cbe701587a9e144b6f5 100644 (file)
@@ -10,12 +10,13 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.api;
 import java.util.List;
 
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 
-public interface CollectionNodeBuilder<V, R extends NormalizedNode<InstanceIdentifier.NodeIdentifier, ?>>
-        extends NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, List<V>, R> {
+public interface CollectionNodeBuilder<V extends NormalizedNode<?, ?>, R extends NormalizedNode<InstanceIdentifier.NodeIdentifier, ?>>
+        extends NormalizedNodeContainerBuilder<NodeIdentifier,PathArgument, V, R> {
 
-    //TODO might be list to keep ordering and map internal
     @Override
     CollectionNodeBuilder<V, R> withValue(List<V> value);
 
@@ -23,4 +24,5 @@ public interface CollectionNodeBuilder<V, R extends NormalizedNode<InstanceIdent
     CollectionNodeBuilder<V, R> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier);
 
     CollectionNodeBuilder<V, R> withChild(V child);
+    CollectionNodeBuilder<V, R> withoutChild(InstanceIdentifier.PathArgument key);
 }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/DataContainerNodeAttrBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/DataContainerNodeAttrBuilder.java
new file mode 100644 (file)
index 0000000..6a441e2
--- /dev/null
@@ -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.builder.api;
+
+import java.util.List;
+
+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;
+
+public interface DataContainerNodeAttrBuilder<I extends InstanceIdentifier.PathArgument, R extends DataContainerNode<I>>
+        extends DataContainerNodeBuilder<I, R>,
+        AttributesBuilder<DataContainerNodeAttrBuilder<I, R>> {
+
+    @Override
+    DataContainerNodeAttrBuilder<I, R> withValue(List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value);
+
+    @Override
+    DataContainerNodeAttrBuilder<I, R> withNodeIdentifier(I nodeIdentifier);
+
+    DataContainerNodeAttrBuilder<I, R> withChild(DataContainerChild<?, ?> child);
+}
index 9c39b871d7e16a90622f5fcf80a96fcf12f8f036..136f1e40e4fa6a1f4be8174d2ff0de0dcc7872ab 100644 (file)
@@ -8,14 +8,14 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.api;
 
 import java.util.List;
-import java.util.Map;
 
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
 
 public interface DataContainerNodeBuilder<I extends InstanceIdentifier.PathArgument, R extends DataContainerNode<I>>
-        extends NormalizedNodeBuilder<I, List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>>, R> {
+        extends NormalizedNodeContainerBuilder<I, PathArgument, DataContainerChild<? extends PathArgument, ?>, R> {
 
     @Override
     DataContainerNodeBuilder<I, R> withValue(List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value);
@@ -24,4 +24,5 @@ public interface DataContainerNodeBuilder<I extends InstanceIdentifier.PathArgum
     DataContainerNodeBuilder<I, R> withNodeIdentifier(I nodeIdentifier);
 
     DataContainerNodeBuilder<I, R> withChild(DataContainerChild<?, ?> child);
-}
+    DataContainerNodeBuilder<I, R> withoutChild(PathArgument key);
+}
\ No newline at end of file
index 41aeae367a79f1242d5b2d7d543706e0b82a0d83..4fde6fa22cc8f36e9b092e60e47e4a3fd41c15e9 100644 (file)
@@ -8,21 +8,29 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.api;
 
 import java.util.List;
+import java.util.Map;
 
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 
 public interface ListNodeBuilder<T, V>
-        extends CollectionNodeBuilder<V, LeafSetNode<T>> {
+        extends CollectionNodeBuilder<LeafSetEntryNode<T>, LeafSetNode<T>> {
 
     @Override
     ListNodeBuilder<T, V> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier);
 
     @Override
-    ListNodeBuilder<T, V> withValue(List<V> value);
+    ListNodeBuilder<T, V> withValue(List<LeafSetEntryNode<T>> value);
 
     @Override
-    ListNodeBuilder<T, V> withChild(V child);
+    ListNodeBuilder<T, V> withChild(LeafSetEntryNode<T> child);
+
+    @Override
+    ListNodeBuilder<T, V> withoutChild(InstanceIdentifier.PathArgument key);
 
     ListNodeBuilder<T, V> withChildValue(T child);
+
+    ListNodeBuilder<T, LeafSetEntryNode<T>> withChildValue(T value, Map<QName, String> attributes);
 }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/NormalizedNodeAttrBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/NormalizedNodeAttrBuilder.java
new file mode 100644 (file)
index 0000000..8863e1b
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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.builder.api;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface NormalizedNodeAttrBuilder<I extends InstanceIdentifier.PathArgument, V, R extends NormalizedNode<I, ?>>
+        extends AttributesBuilder<NormalizedNodeAttrBuilder<I, V, R>>,
+        NormalizedNodeBuilder<I, V, R> {
+
+    @Override
+    NormalizedNodeAttrBuilder<I, V, R> withValue(V value);
+
+    @Override
+    NormalizedNodeAttrBuilder<I, V, R> withNodeIdentifier(I nodeIdentifier);
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/NormalizedNodeContainerBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/api/NormalizedNodeContainerBuilder.java
new file mode 100644 (file)
index 0000000..03b4995
--- /dev/null
@@ -0,0 +1,19 @@
+package org.opendaylight.yangtools.yang.data.impl.schema.builder.api;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+public interface NormalizedNodeContainerBuilder<K extends PathArgument,CK extends PathArgument,CV extends NormalizedNode<? extends CK, ?>,P extends NormalizedNode<K, ?>>
+extends NormalizedNodeBuilder<K,List<CV>,P>{
+
+    @Override
+    NormalizedNodeContainerBuilder<K,CK,CV,P> withNodeIdentifier(K nodeIdentifier);
+
+    @Override
+    NormalizedNodeContainerBuilder<K,CK,CV,P> withValue(List<CV> value);
+
+    NormalizedNodeContainerBuilder<K,CK,CV,P> addChild(CV child);
+    NormalizedNodeContainerBuilder<K,CK,CV,P> removeChild(CK key);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeAttrBuilder.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeAttrBuilder.java
new file mode 100644 (file)
index 0000000..4fef48b
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * 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.builder.impl;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+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.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerAttrNode;
+
+abstract class AbstractImmutableDataContainerNodeAttrBuilder<I extends InstanceIdentifier.PathArgument, R extends DataContainerNode<I>>
+        extends AbstractImmutableDataContainerNodeBuilder<I, R>
+        implements DataContainerNodeAttrBuilder<I, R> {
+
+    private Map<QName, String> attributes;
+
+    protected AbstractImmutableDataContainerNodeAttrBuilder() {
+        this.attributes = Collections.emptyMap();
+    }
+
+    protected AbstractImmutableDataContainerNodeAttrBuilder(final AbstractImmutableDataContainerAttrNode<I> node) {
+        super(node);
+        this.attributes = node.getAttributes();
+    }
+
+    protected final Map<QName, String> getAttributes() {
+        return attributes;
+    }
+
+    @Override
+    public DataContainerNodeAttrBuilder<I, R> withAttributes(final Map<QName, String> attributes){
+        this.attributes = attributes;
+        return this;
+    }
+
+    @Override
+    public DataContainerNodeAttrBuilder<I, R> withValue(final List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
+        return (DataContainerNodeAttrBuilder<I, R>) super.withValue(value);
+    }
+
+    @Override
+    public DataContainerNodeAttrBuilder<I, R> withChild(final DataContainerChild<?, ?> child) {
+        return (DataContainerNodeAttrBuilder<I, R>) super.withChild(child);
+    }
+
+    @Override
+    public DataContainerNodeAttrBuilder<I, R> withNodeIdentifier(final I nodeIdentifier) {
+        return (DataContainerNodeAttrBuilder<I, R>) super.withNodeIdentifier(nodeIdentifier);
+    }
+}
index 39032ad78e9408faf5b4cdd252b04d6f64d8d71a..1479c8c3aeb05d213aaf7679b80b06cce1a13ea5 100644 (file)
@@ -7,45 +7,99 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 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 com.google.common.collect.Maps;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
 
 abstract class AbstractImmutableDataContainerNodeBuilder<I extends InstanceIdentifier.PathArgument, R extends DataContainerNode<I>>
         implements DataContainerNodeBuilder<I, R> {
 
-    protected Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value;
-    protected I nodeIdentifier;
+    private Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value;
+    private I nodeIdentifier;
+
+    /*
+     * Tracks whether the builder is dirty, e.g. whether the value map has been used
+     * to construct a child. If it has, we detect this condition before any further
+     * modification and create a new value map with same contents. This way we do not
+     * force a map copy if the builder is not reused.
+     */
+    private boolean dirty;
 
     protected AbstractImmutableDataContainerNodeBuilder() {
-        this.value = Maps.newLinkedHashMap();
+        this.value = new HashMap<>();
+        this.dirty = false;
+    }
+
+    protected AbstractImmutableDataContainerNodeBuilder(final AbstractImmutableDataContainerNode<I> node) {
+        this.value = node.getChildren();
+        this.dirty = true;
+    }
+
+    protected final I getNodeIdentifier() {
+        return nodeIdentifier;
+    }
+
+    protected final DataContainerChild<? extends PathArgument, ?> getChild(final PathArgument child) {
+        return value.get(child);
+    }
+
+    protected final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> buildValue() {
+        dirty = true;
+        return value;
+    }
+
+    private void checkDirty() {
+        if (dirty) {
+            value = new HashMap<>(value);
+            dirty = false;
+        }
     }
 
     @Override
-    public DataContainerNodeBuilder<I, R> withValue(List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
+    public DataContainerNodeBuilder<I, R> withValue(final List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
         // TODO Replace or putAll ?
-        for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild : value) {
+        for (final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild : value) {
             withChild(dataContainerChild);
         }
         return this;
     }
 
     @Override
-    public DataContainerNodeBuilder<I, R> withChild(DataContainerChild<?, ?> child) {
+    public DataContainerNodeBuilder<I, R> withChild(final DataContainerChild<?, ?> child) {
+        checkDirty();
         this.value.put(child.getIdentifier(), child);
         return this;
     }
 
+    @Override
+    public DataContainerNodeBuilder<I, R> withoutChild(final PathArgument key) {
+        checkDirty();
+        this.value.remove(key);
+        return this;
+    }
 
     @Override
-    public DataContainerNodeBuilder<I, R> withNodeIdentifier(I nodeIdentifier) {
+    public DataContainerNodeBuilder<I, R> withNodeIdentifier(final I nodeIdentifier) {
         this.nodeIdentifier = nodeIdentifier;
         return this;
     }
+
+    @Override
+    public DataContainerNodeBuilder<I, R> addChild(
+            final DataContainerChild<? extends PathArgument, ?> child) {
+        return withChild(child);
+    }
+
+    @Override
+    public NormalizedNodeContainerBuilder<I, PathArgument, DataContainerChild<? extends PathArgument, ?>, R> removeChild(final PathArgument key) {
+        return withoutChild(key);
+    }
 }
index ff6a2354ade52d09642319936c2f15ab33f89520..7f476798569c0b3c3b45a827aa4eb0cac11d5fb7 100644 (file)
@@ -7,27 +7,48 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import java.util.Collections;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
 
 abstract class AbstractImmutableNormalizedNodeBuilder<I extends InstanceIdentifier.PathArgument, V, R extends NormalizedNode<I, ?>>
-        implements NormalizedNodeBuilder<I,V,R> {
+        implements NormalizedNodeAttrBuilder<I,V,R> {
+
+    private Map<QName, String> attributes = Collections.emptyMap();
+    private I nodeIdentifier;
+    private V value;
+
+    protected final I getNodeIdentifier() {
+        return nodeIdentifier;
+    }
 
-    protected V value;
-    protected I nodeIdentifier;
+    protected final V getValue() {
+        return value;
+    }
+
+    protected final Map<QName, String> getAttributes() {
+        return attributes;
+    }
 
     @Override
-    public NormalizedNodeBuilder<I,V,R> withValue(V value) {
+    public NormalizedNodeAttrBuilder<I,V,R> withValue(final V value) {
         this.value = value;
         return this;
     }
 
-
     @Override
-    public NormalizedNodeBuilder<I,V,R> withNodeIdentifier(I nodeIdentifier) {
+    public NormalizedNodeAttrBuilder<I,V,R> withNodeIdentifier(final I nodeIdentifier) {
         this.nodeIdentifier = nodeIdentifier;
         return this;
     }
 
+    @Override
+    public NormalizedNodeAttrBuilder<I,V,R> withAttributes(final Map<QName, String> attributes){
+        this.attributes = attributes;
+        return this;
+    }
 }
index 481ddb09ff181a5fec4ea2271e24d846b066b526..ae12e4b704fe7779e59aebd7f28f8cce8b610446 100644 (file)
@@ -10,6 +10,8 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 import java.util.Map;
 
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 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.builder.api.DataContainerNodeBuilder;
@@ -26,26 +28,32 @@ public class ImmutableAugmentationNodeBuilder
 
     @Override
     public DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> withChild(
-            DataContainerChild<?, ?> child) {
+            final DataContainerChild<?, ?> child) {
         // Check nested augments
         Preconditions.checkArgument(child instanceof AugmentationNode == false,
                 "Unable to add: %s, as a child for: %s, Nested augmentations are not permitted", child.getNodeType(),
-                nodeIdentifier == null ? this : nodeIdentifier);
+                getNodeIdentifier() == null ? this : getNodeIdentifier());
 
         return super.withChild(child);
     }
 
+    @Override
+    public DataContainerNodeBuilder<AugmentationIdentifier, AugmentationNode> withoutChild(final PathArgument key) {
+        return super.withoutChild(key);
+    }
+
     @Override
     public AugmentationNode build() {
-        return new ImmutableAugmentationNode(nodeIdentifier, value);
+        return new ImmutableAugmentationNode(getNodeIdentifier(), buildValue());
     }
 
-    static final class ImmutableAugmentationNode
+    private static final class ImmutableAugmentationNode
             extends AbstractImmutableDataContainerNode<InstanceIdentifier.AugmentationIdentifier>
             implements AugmentationNode {
 
-        ImmutableAugmentationNode(InstanceIdentifier.AugmentationIdentifier nodeIdentifier, Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
+        ImmutableAugmentationNode(final InstanceIdentifier.AugmentationIdentifier nodeIdentifier, final Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
             super(children, nodeIdentifier);
         }
     }
+
 }
index 1f07eb555302dc14e1d6b7803bc26e559e5df269..9a658317329421fd96fcbad9feae5672bb1b2378 100644 (file)
@@ -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 {
@@ -26,7 +25,6 @@ public class ImmutableAugmentationNodeSchemaAwareBuilder extends ImmutableAugmen
     private final DataNodeContainerValidator validator;
 
     protected ImmutableAugmentationNodeSchemaAwareBuilder(AugmentationSchema schema) {
-        super();
         this.validator = new DataNodeContainerValidator(schema);
         // TODO no QName for augmentation
         super.withNodeIdentifier(new InstanceIdentifier.AugmentationIdentifier(null, getChildQNames(schema)));
index 674ebbaddc048dca748799494db70744545f57fa..36719534d5c1f666e80c46a1b5b3e8b98973a7b6 100644 (file)
@@ -21,18 +21,18 @@ public class ImmutableChoiceNodeBuilder extends AbstractImmutableDataContainerNo
         return new ImmutableChoiceNodeBuilder();
     }
 
+    @Override
     public ChoiceNode build() {
-        return new ImmutableChoiceNode(nodeIdentifier, value);
+        return new ImmutableChoiceNode(getNodeIdentifier(), buildValue());
     }
 
-    static final class ImmutableChoiceNode
+    private static final class ImmutableChoiceNode
             extends AbstractImmutableDataContainerNode<InstanceIdentifier.NodeIdentifier>
             implements ChoiceNode {
 
-        ImmutableChoiceNode(InstanceIdentifier.NodeIdentifier nodeIdentifier,
-                            Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
+        ImmutableChoiceNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
+                            final Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
             super(children, nodeIdentifier);
         }
-
     }
 }
index ab73930b402f09104d906d21e71f2149e7101db5..5988554428c6806fbfd8e0f49fe724cc40bd0015 100644 (file)
@@ -12,10 +12,11 @@ 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;
+import com.google.common.base.Supplier;
 
 public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBuilder {
 
@@ -24,8 +25,7 @@ public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBu
     private DataNodeContainerValidator validator;
 
     protected ImmutableChoiceNodeSchemaAwareBuilder(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
-        super();
-        this.schema = schema;
+        this.schema = Preconditions.checkNotNull(schema);
         super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
     }
 
@@ -35,9 +35,15 @@ public class ImmutableChoiceNodeSchemaAwareBuilder extends ImmutableChoiceNodeBu
     }
 
     @Override
-    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> withChild(DataContainerChild<?, ?> child) {
+    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> withChild(final DataContainerChild<?, ?> child) {
         if(detectedCase == null) {
-            detectedCase = detectCase(child);
+            detectedCase = SchemaUtils.detectCase(schema, child).or(new Supplier<ChoiceCaseNode>() {
+                @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 +58,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<InstanceIdentifier.NodeIdentifier, ChoiceNode> create(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
         return new ImmutableChoiceNodeSchemaAwareBuilder(schema);
     }
index c3cbf3477973d7ed78eb3ed13956104047867a1f..0518f7cf8c681fdac5c51051ac0a45d9ed783f3f 100644 (file)
@@ -9,32 +9,48 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
 import java.util.Map;
 
+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.api.schema.DataContainerChild;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerAttrNode;
 
-public class ImmutableContainerNodeBuilder extends AbstractImmutableDataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> {
+public class ImmutableContainerNodeBuilder extends
+        AbstractImmutableDataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> {
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> create() {
+    protected ImmutableContainerNodeBuilder() {
+        super();
+    }
+
+    protected ImmutableContainerNodeBuilder(final ImmutableContainerNode node) {
+        super(node);
+    }
+
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> create() {
         return new ImmutableContainerNodeBuilder();
     }
 
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> create(final ContainerNode node) {
+        if (!(node instanceof ImmutableContainerNode)) {
+            throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
+        }
+        return new ImmutableContainerNodeBuilder((ImmutableContainerNode) node);
+    }
+
     @Override
     public ContainerNode build() {
-        return new ImmutableContainerNode(nodeIdentifier, value);
+        return new ImmutableContainerNode(getNodeIdentifier(), buildValue(), getAttributes());
     }
 
-    final class ImmutableContainerNode
-            extends AbstractImmutableDataContainerNode<InstanceIdentifier.NodeIdentifier>
-            implements ContainerNode {
+    protected static final class ImmutableContainerNode extends
+            AbstractImmutableDataContainerAttrNode<InstanceIdentifier.NodeIdentifier> implements ContainerNode {
 
         ImmutableContainerNode(
-                InstanceIdentifier.NodeIdentifier nodeIdentifier,
-                Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
-            super(children, nodeIdentifier);
+                final InstanceIdentifier.NodeIdentifier nodeIdentifier,
+                final Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children,
+                final Map<QName, String> attributes) {
+            super(children, nodeIdentifier, attributes);
         }
-
     }
 }
index 5f00539c38acc5bb8f5760e9666548a5507b99c8..ca8a6a2f61cf6931e7d956b13a5d4dfdda0a5415 100644 (file)
@@ -10,33 +10,44 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 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.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 
 public final class ImmutableContainerNodeSchemaAwareBuilder extends ImmutableContainerNodeBuilder {
 
     private final DataNodeContainerValidator validator;
+    // TODO remove schema aware builders, replace by validator called at build() ?
 
-    // TODO remove schema aware builders, replace by validator called at build()
+    private ImmutableContainerNodeSchemaAwareBuilder(final ContainerSchemaNode schema) {
+        this.validator = new DataNodeContainerValidator(schema);
+        super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
+    }
 
-    private ImmutableContainerNodeSchemaAwareBuilder(ContainerSchemaNode schema) {
-        super();
+    private ImmutableContainerNodeSchemaAwareBuilder(final ContainerSchemaNode schema, final ImmutableContainerNode node) {
+        super(node);
         this.validator = new DataNodeContainerValidator(schema);
         super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
     }
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> create(ContainerSchemaNode schema) {
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> create(final ContainerSchemaNode schema) {
         return new ImmutableContainerNodeSchemaAwareBuilder(schema);
     }
 
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> create(final ContainerSchemaNode schema, final ContainerNode node) {
+        if (!(node instanceof ImmutableContainerNode)) {
+            throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
+        }
+        return new ImmutableContainerNodeSchemaAwareBuilder(schema, (ImmutableContainerNode)node);
+    }
+
     @Override
-    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+    public DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> withNodeIdentifier(final InstanceIdentifier.NodeIdentifier nodeIdentifier) {
         throw new UnsupportedOperationException("Node identifier created from schema");
     }
 
     @Override
-    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> withChild(DataContainerChild<?, ?> child) {
+    public DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> withChild(final DataContainerChild<?, ?> child) {
         validator.validateChild(child.getIdentifier());
         return super.withChild(child);
     }
index f466ed3929edf8bfc3a5c072c69d36b9f8f8c510..fcec7afc214a5967d3c7099e76c3b7fee50cd8f3 100644 (file)
@@ -7,38 +7,29 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedAttrNode;
 
 public class ImmutableLeafNodeBuilder<T> extends AbstractImmutableNormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> {
 
-    protected ImmutableLeafNodeBuilder() {
-    }
-
-    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> create() {
+    public static <T> NormalizedNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> create() {
         return new ImmutableLeafNodeBuilder<>();
     }
 
     @Override
     public LeafNode<T> build() {
-        return new ImmutableLeafNode<>(nodeIdentifier, value);
+        return new ImmutableLeafNode<>(getNodeIdentifier(), getValue(), getAttributes());
     }
 
-    static final class ImmutableLeafNode<T> extends AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, T> implements LeafNode<T> {
-
-        ImmutableLeafNode(InstanceIdentifier.NodeIdentifier nodeIdentifier, T value) {
-            super(nodeIdentifier, value);
-        }
+    private static final class ImmutableLeafNode<T> extends AbstractImmutableNormalizedAttrNode<InstanceIdentifier.NodeIdentifier, T> implements LeafNode<T> {
 
-        @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();
+        ImmutableLeafNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier, final T value, final Map<QName, String> attributes) {
+            super(nodeIdentifier, value, attributes);
         }
     }
 }
index 097889a709fe7b0b40fe800c47c8a826a415eae9..3c508fe01c2101940f784eb9a7c4efca23e4dc2a 100644 (file)
@@ -9,31 +9,27 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 
 public final class ImmutableLeafNodeSchemaAwareBuilder<T> extends ImmutableLeafNodeBuilder<T> {
 
-    private final LeafSchemaNode schema;
-
     private ImmutableLeafNodeSchemaAwareBuilder(LeafSchemaNode schema) {
-        super();
-        this.schema = schema;
         super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
     }
 
-    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> create(LeafSchemaNode schema) {
+    public static <T> NormalizedNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> create(LeafSchemaNode schema) {
         return new ImmutableLeafNodeSchemaAwareBuilder<>(schema);
     }
 
     @Override
-    public NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> withValue(T value) {
+    public NormalizedNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> withValue(T value) {
 //        TODO check value type
         return super.withValue(value);
     }
 
     @Override
-    public NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+    public NormalizedNodeAttrBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
         throw new UnsupportedOperationException("Node identifier created from schema");
     }
 }
index 77d23d80a31b1422974102c995b11fbd9408e146..fd5cf52678ecd92f248c0d8493ca3a2579187e68 100644 (file)
@@ -7,39 +7,32 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedAttrNode;
 
 import com.google.common.base.Preconditions;
 
 public class ImmutableLeafSetEntryNodeBuilder<T> extends AbstractImmutableNormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> {
 
-    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> create() {
+    public static <T> ImmutableLeafSetEntryNodeBuilder<T> create() {
         return new ImmutableLeafSetEntryNodeBuilder<>();
     }
 
     @Override
     public LeafSetEntryNode<T> build() {
-        return new ImmutableLeafSetEntryNode<>(nodeIdentifier, value);
+        return new ImmutableLeafSetEntryNode<>(getNodeIdentifier(), getValue(), getAttributes());
     }
 
-    static final class ImmutableLeafSetEntryNode<T> extends AbstractImmutableNormalizedNode<InstanceIdentifier.NodeWithValue, T> implements LeafSetEntryNode<T> {
+    private static final class ImmutableLeafSetEntryNode<T> extends AbstractImmutableNormalizedAttrNode<InstanceIdentifier.NodeWithValue, T> implements LeafSetEntryNode<T> {
 
-        ImmutableLeafSetEntryNode(InstanceIdentifier.NodeWithValue nodeIdentifier, T value) {
-            super(nodeIdentifier, value);
+        ImmutableLeafSetEntryNode(final InstanceIdentifier.NodeWithValue nodeIdentifier, final T value, final Map<QName, String> attributes) {
+            super(nodeIdentifier, value, attributes);
             Preconditions.checkArgument(nodeIdentifier.getValue().equals(value),
                     "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();
-        }
     }
 }
index 35fe29942439907f13c9162cee85683ffb07a833..577ec37c6bbb5d89332d51157123cfba9903a61b 100644 (file)
@@ -9,31 +9,32 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 
+import com.google.common.base.Preconditions;
+
 public final class ImmutableLeafSetEntryNodeSchemaAwareBuilder<T> extends ImmutableLeafSetEntryNodeBuilder<T> {
 
     private final LeafListSchemaNode schema;
 
     private ImmutableLeafSetEntryNodeSchemaAwareBuilder(LeafListSchemaNode schema) {
-        super();
-        this.schema = schema;
+        this.schema = Preconditions.checkNotNull(schema);
     }
 
-    public static <T> NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> create(LeafListSchemaNode schema) {
+    public static <T> NormalizedNodeAttrBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> create(LeafListSchemaNode schema) {
         return new ImmutableLeafSetEntryNodeSchemaAwareBuilder<>(schema);
     }
 
     @Override
-    public NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> withValue(T value) {
+    public NormalizedNodeAttrBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> withValue(T value) {
         super.withNodeIdentifier(new InstanceIdentifier.NodeWithValue(schema.getQName(), value));
         // TODO check value type
         return super.withValue(value);
     }
 
     @Override
-    public NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> withNodeIdentifier(InstanceIdentifier.NodeWithValue nodeIdentifier) {
+    public NormalizedNodeAttrBuilder<InstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> withNodeIdentifier(InstanceIdentifier.NodeWithValue nodeIdentifier) {
         throw new UnsupportedOperationException("Node identifier created from schema");
     }
 
index f352b984c7ab348693b5e083b89ac1c712106e7e..a2d044da74cb4a83780aae814867dd2f03e4c21a 100644 (file)
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 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.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
 
 import com.google.common.base.Optional;
-import com.google.common.collect.Maps;
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import com.google.common.collect.Iterables;
 
-public class ImmutableLeafSetNodeBuilder<T>
-        implements ListNodeBuilder<T, LeafSetEntryNode<T>> {
+public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSetEntryNode<T>> {
 
-    protected Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> value;
-    protected InstanceIdentifier.NodeIdentifier nodeIdentifier;
+    private Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> value;
+    private InstanceIdentifier.NodeIdentifier nodeIdentifier;
+    private boolean dirty;
+
+    protected ImmutableLeafSetNodeBuilder() {
+        value = new LinkedHashMap<>();
+        dirty = false;
+    }
+
+    protected ImmutableLeafSetNodeBuilder(final ImmutableLeafSetNode<T> node) {
+        value = node.getChildren();
+        nodeIdentifier = node.getIdentifier();
+        dirty = true;
+    }
 
     public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create() {
         return new ImmutableLeafSetNodeBuilder<>();
     }
 
-    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChild(LeafSetEntryNode<T> child) {
-        if(this.value == null) {
-            this.value = Maps.newLinkedHashMap();
+    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create(final LeafSetNode<T> node) {
+        if (!(node instanceof ImmutableLeafSetNode<?>)) {
+            throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
         }
 
+        return new ImmutableLeafSetNodeBuilder<T>((ImmutableLeafSetNode<T>) node);
+    }
+
+    private void checkDirty() {
+        if (dirty) {
+            value = new LinkedHashMap<>(value);
+            dirty = false;
+        }
+    }
+
+    @Override
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChild(final LeafSetEntryNode<T> child) {
+        checkDirty();
         this.value.put(child.getIdentifier(), child);
         return this;
     }
 
+    @Override
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withoutChild(final PathArgument key) {
+        checkDirty();
+        this.value.remove(key);
+        return this;
+    }
+
     @Override
     public LeafSetNode<T> build() {
+        dirty = true;
         return new ImmutableLeafSetNode<>(nodeIdentifier, value);
     }
 
     @Override
-    public ListNodeBuilder<T, LeafSetEntryNode<T>> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withNodeIdentifier(
+            final InstanceIdentifier.NodeIdentifier nodeIdentifier) {
         this.nodeIdentifier = nodeIdentifier;
         return this;
     }
 
     @Override
-    public ListNodeBuilder<T, LeafSetEntryNode<T>> withValue(List<LeafSetEntryNode<T>> value) {
-        for (LeafSetEntryNode<T> leafSetEntry : value) {
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withValue(final List<LeafSetEntryNode<T>> value) {
+        checkDirty();
+        for (final LeafSetEntryNode<T> leafSetEntry : value) {
             withChild(leafSetEntry);
         }
 
         return this;
     }
 
+
     @Override
-    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChildValue(T value) {
-        return withChild(new ImmutableLeafSetEntryNodeBuilder.ImmutableLeafSetEntryNode<>(new InstanceIdentifier.NodeWithValue(nodeIdentifier.getNodeType(), value), value));
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChildValue(final T value, final Map<QName, String> attributes) {
+        final ImmutableLeafSetEntryNodeBuilder<T> b = ImmutableLeafSetEntryNodeBuilder.create();
+        b.withNodeIdentifier(new InstanceIdentifier.NodeWithValue(nodeIdentifier.getNodeType(), value));
+        b.withValue(value);
+        b.withAttributes(attributes);
+        return withChild(b.build());
     }
 
-    final class ImmutableLeafSetNode<T> extends AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<LeafSetEntryNode<T>>> implements LeafSetNode<T> {
+    @Override
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChildValue(final T value) {
+        return withChildValue(value, Collections.<QName,String>emptyMap());
+    }
 
-        private final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> mappedChildren;
+    protected final static class ImmutableLeafSetNode<T> extends
+            AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<LeafSetEntryNode<T>>> implements
+            Immutable, LeafSetNode<T> {
 
-        ImmutableLeafSetNode(InstanceIdentifier.NodeIdentifier nodeIdentifier, Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children) {
-            super(nodeIdentifier, children.values());
-            this.mappedChildren = children;
+        private final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children;
+
+        ImmutableLeafSetNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
+                final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children) {
+            super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+            this.children = children;
         }
 
         @Override
-        public Optional<LeafSetEntryNode<T>> getChild(InstanceIdentifier.NodeWithValue child) {
-            return Optional.fromNullable(mappedChildren.get(child));
+        public Optional<LeafSetEntryNode<T>> getChild(final InstanceIdentifier.NodeWithValue child) {
+            return Optional.fromNullable(children.get(child));
+        }
+
+        @Override
+        protected int valueHashCode() {
+            return children.hashCode();
+        }
+
+        private Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> getChildren() {
+            return Collections.unmodifiableMap(children);
         }
 
         @Override
-        public String toString() {
-            final StringBuffer sb = new StringBuffer("ImmutableLeafSetNode{");
-            sb.append("nodeIdentifier=").append(nodeIdentifier);
-            sb.append(", children=").append(value);
-            sb.append('}');
-            return sb.toString();
+        protected boolean valueEquals(final AbstractImmutableNormalizedNode<?, ?> other) {
+            return children.equals(((ImmutableLeafSetNode<?>) other).children);
         }
     }
 
+    @Override
+    public NormalizedNodeContainerBuilder<NodeIdentifier, PathArgument, LeafSetEntryNode<T>, LeafSetNode<T>> addChild(
+            final LeafSetEntryNode<T> child) {
+        return withChild(child);
+    }
+
+    @Override
+    public NormalizedNodeContainerBuilder<NodeIdentifier, PathArgument, LeafSetEntryNode<T>, LeafSetNode<T>> removeChild(
+            final PathArgument key) {
+        return withoutChild(key);
+    }
+
 }
index e1a4eda76ae35bfa5de46780168489357f7a0b0f..e6d61e7fc3feb30b66b82add7cdbefe84e40076d 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 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.builder.api.ListNodeBuilder;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 
@@ -18,31 +19,45 @@ public final class ImmutableLeafSetNodeSchemaAwareBuilder<T> extends ImmutableLe
 
     private final LeafListSchemaNode schema;
 
-    private ImmutableLeafSetNodeSchemaAwareBuilder(LeafListSchemaNode schema) {
-        super();
-        this.schema = schema;
+    private ImmutableLeafSetNodeSchemaAwareBuilder(final LeafListSchemaNode schema) {
+        this.schema = Preconditions.checkNotNull(schema);
         super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
     }
 
-    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create(LeafListSchemaNode schema) {
+    public ImmutableLeafSetNodeSchemaAwareBuilder(final LeafListSchemaNode schema, final ImmutableLeafSetNode<T> node) {
+        super(node);
+        this.schema = Preconditions.checkNotNull(schema);
+        // FIXME: Preconditions.checkArgument(schema.getQName().equals(node.getIdentifier()));
+        super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
+    }
+
+    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create(final LeafListSchemaNode schema) {
         return new ImmutableLeafSetNodeSchemaAwareBuilder<>(schema);
     }
 
+    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create(final LeafListSchemaNode schema, final LeafSetNode<T> node) {
+        if (!(node instanceof ImmutableLeafSetNode<?>)) {
+            throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
+        }
+
+        return new ImmutableLeafSetNodeSchemaAwareBuilder<T>(schema, (ImmutableLeafSetNode<T>) node);
+    }
+
     @Override
-    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChildValue(T value) {
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChildValue(final T value) {
         // TODO check value type
         return super.withChildValue(value);
     }
 
     @Override
-    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChild(LeafSetEntryNode<T> child) {
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withChild(final LeafSetEntryNode<T> child) {
         Preconditions.checkArgument(schema.getQName().equals(child.getNodeType()),
                 "Incompatible node type, should be: %s, is: %s", schema.getQName(), child.getNodeType());
         return super.withChild(child);
     }
 
     @Override
-    public ListNodeBuilder<T, LeafSetEntryNode<T>> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+    public ListNodeBuilder<T, LeafSetEntryNode<T>> withNodeIdentifier(final InstanceIdentifier.NodeIdentifier nodeIdentifier) {
         throw new UnsupportedOperationException("Node identifier created from schema");
     }
 }
index 90e36f736a11cb1b3c4e546b67a3aef1f4f4c522..427b939d990411df32267e338293a5841511e600 100644 (file)
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 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.builder.api.DataContainerNodeBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
-import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerAttrNode;
 
 import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
 
 public class ImmutableMapEntryNodeBuilder
-        extends AbstractImmutableDataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> {
+        extends AbstractImmutableDataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> {
 
     protected final Map<QName, InstanceIdentifier.PathArgument> childrenQNamesToPaths;
 
     protected ImmutableMapEntryNodeBuilder() {
-        this.childrenQNamesToPaths = Maps.newLinkedHashMap();
+        this.childrenQNamesToPaths = new LinkedHashMap<>();
     }
 
-    public static DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> create() {
+    protected ImmutableMapEntryNodeBuilder(final ImmutableMapEntryNode node) {
+        super(node);
+        this.childrenQNamesToPaths = new LinkedHashMap<>();
+        fillQnames(node.getValue(), childrenQNamesToPaths);
+    }
+
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> create() {
         return new ImmutableMapEntryNodeBuilder();
     }
 
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> create(final MapEntryNode node) {
+        if (!(node instanceof ImmutableMapEntryNode)) {
+            throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
+        }
+
+        return new ImmutableMapEntryNodeBuilder((ImmutableMapEntryNode)node);
+    }
+
+    private static void fillQnames(final Iterable<DataContainerChild<? extends PathArgument, ?>> iterable, final Map<QName, PathArgument> out) {
+        for (final DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childId : iterable) {
+            final InstanceIdentifier.PathArgument identifier = childId.getIdentifier();
+
+            // Augmentation nodes cannot be keys, and do not have to be present in childrenQNamesToPaths map
+            if(identifier instanceof InstanceIdentifier.AugmentationIdentifier) {
+                continue;
+            }
+
+            out.put(childId.getNodeType(), identifier);
+        }
+    }
+
     // FIXME, find better solution than 2 maps (map from QName to Child ?)
 
     @Override
-    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withValue(List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
-        for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> childId : value) {
-            this.childrenQNamesToPaths.put(childId.getNodeType(), childId.getIdentifier());
-        }
+    public DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withValue(final List<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> value) {
+        fillQnames(value, childrenQNamesToPaths);
         return super.withValue(value);
     }
 
     @Override
-    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withChild(DataContainerChild<?, ?> child) {
-        childrenQNamesToPaths.put(child.getNodeType(), child.getIdentifier());
+    public DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withChild(final DataContainerChild<?, ?> child) {
+        // Augmentation nodes cannot be keys, and do not have to be present in childrenQNamesToPaths map
+        if(child.getIdentifier() instanceof InstanceIdentifier.AugmentationIdentifier == false) {
+            childrenQNamesToPaths.put(child.getNodeType(), child.getIdentifier());
+        }
         return super.withChild(child);
     }
 
+    @Override
     public MapEntryNode build() {
         checkKeys();
-        return new ImmutableMapEntryNode(nodeIdentifier, value);
+        return new ImmutableMapEntryNode(getNodeIdentifier(), buildValue(), getAttributes());
     }
 
     private void checkKeys() {
-        for (QName keyQName : nodeIdentifier.getKeyValues().keySet()) {
+        for (final QName keyQName : getNodeIdentifier().getKeyValues().keySet()) {
 
-            InstanceIdentifier.PathArgument childNodePath = childrenQNamesToPaths.get(keyQName);
-            DataContainerChild<?, ?> childNode = value.get(childNodePath);
+            final InstanceIdentifier.PathArgument childNodePath = childrenQNamesToPaths.get(keyQName);
+            final DataContainerChild<?, ?> childNode = getChild(childNodePath);
 
             Preconditions.checkNotNull(childNode, "Key child node: %s, not present", keyQName);
 
-            Object actualValue = nodeIdentifier.getKeyValues().get(keyQName);
-            Object expectedValue = childNode.getValue();
+            final Object actualValue = getNodeIdentifier().getKeyValues().get(keyQName);
+            final Object expectedValue = childNode.getValue();
             Preconditions.checkArgument(expectedValue.equals(actualValue),
                     "Key child node with unexpected value, is: %s, should be: %s", actualValue, expectedValue);
         }
     }
 
-    static final class ImmutableMapEntryNode extends AbstractImmutableDataContainerNode<InstanceIdentifier.NodeIdentifierWithPredicates> implements MapEntryNode {
+    private static final class ImmutableMapEntryNode extends AbstractImmutableDataContainerAttrNode<InstanceIdentifier.NodeIdentifierWithPredicates> implements MapEntryNode {
 
-        ImmutableMapEntryNode(InstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifier,
-                              Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children) {
-            super(children, nodeIdentifier);
+        ImmutableMapEntryNode(final InstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifier,
+                              final Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children, final Map<QName, String> attributes) {
+            super(children, nodeIdentifier, attributes);
         }
     }
 }
index 44959104390f0eaf8eca1a921d1503439b281b60..aab21ebc3b0c04f983827de62cd47a2e2c48ce25 100644 (file)
@@ -14,7 +14,7 @@ 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.MapEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataNodeContainerValidator;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
@@ -26,18 +26,18 @@ public final class ImmutableMapEntryNodeSchemaAwareBuilder extends ImmutableMapE
     private final ListSchemaNode schema;
     private final DataNodeContainerValidator validator;
 
-    protected ImmutableMapEntryNodeSchemaAwareBuilder(ListSchemaNode schema) {
-        this.schema = schema;
+    protected ImmutableMapEntryNodeSchemaAwareBuilder(final ListSchemaNode schema) {
+        this.schema = Preconditions.checkNotNull(schema);
         this.validator = new DataNodeContainerValidator(schema);
     }
 
     @Override
-    public ImmutableMapEntryNodeBuilder withNodeIdentifier(InstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifier) {
+    public ImmutableMapEntryNodeBuilder withNodeIdentifier(final InstanceIdentifier.NodeIdentifierWithPredicates nodeIdentifier) {
         throw new UnsupportedOperationException("Node identifier created from schema");
     }
 
     @Override
-    public DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withChild(DataContainerChild<?, ?> child) {
+    public DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> withChild(final DataContainerChild<?, ?> child) {
         validator.validateChild(child.getIdentifier());
         return super.withChild(child);
     }
@@ -60,18 +60,19 @@ public final class ImmutableMapEntryNodeSchemaAwareBuilder extends ImmutableMapE
             keys = childrenQNamesToPaths.keySet();
         }
 
-        Map<QName, Object> keysToValues = Maps.newHashMap();
-        for (QName key : keys) {
+        final Map<QName, Object> keysToValues = Maps.newHashMap();
+        for (final QName key : keys) {
             // TODO two maps ? find better solution
-            DataContainerChild<?, ?> valueForKey = value.get(childrenQNamesToPaths.get(key));
+            final DataContainerChild<?, ?> valueForKey = getChild(childrenQNamesToPaths.get(key));
             Preconditions.checkState(valueForKey != null, "Key value: %s cannot be empty for: %s", key, schema.getQName());
             keysToValues.put(key, valueForKey.getValue());
         }
 
+
         return new InstanceIdentifier.NodeIdentifierWithPredicates(schema.getQName(), keysToValues);
     }
 
-    public static ImmutableMapEntryNodeSchemaAwareBuilder create(ListSchemaNode schema) {
+    public static DataContainerNodeAttrBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> create(final ListSchemaNode schema) {
         return new ImmutableMapEntryNodeSchemaAwareBuilder(schema);
     }
 
index 08380c76f0a5de0afea3d8406fd3261dd3eea441..17cdaffedaf6ffa370354a72b7d0283d361b57ec 100644 (file)
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 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.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
 
 import com.google.common.base.Optional;
-import com.google.common.collect.Maps;
+import com.google.common.collect.Iterables;
 
 public class ImmutableMapNodeBuilder
         implements CollectionNodeBuilder<MapEntryNode, MapNode> {
 
-    protected Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
-    protected InstanceIdentifier.NodeIdentifier nodeIdentifier;
+    private Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
+    private InstanceIdentifier.NodeIdentifier nodeIdentifier;
+    private boolean dirty = false;
+
+    protected ImmutableMapNodeBuilder() {
+        this.value = new LinkedHashMap<>();
+        this.dirty = false;
+    }
+
+    protected ImmutableMapNodeBuilder(final ImmutableMapNode node) {
+        this.value = node.children;
+        this.dirty = true;
+    }
 
     public static CollectionNodeBuilder<MapEntryNode, MapNode> create() {
         return new ImmutableMapNodeBuilder();
     }
 
-    public CollectionNodeBuilder<MapEntryNode, MapNode> withChild(MapEntryNode child) {
-        if(this.value == null) {
-            this.value = Maps.newLinkedHashMap();
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> create(final MapNode node) {
+        if (!(node instanceof ImmutableMapNode)) {
+            throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
         }
 
+        return new ImmutableMapNodeBuilder((ImmutableMapNode) node);
+    }
+
+    private void checkDirty() {
+        if (dirty) {
+            value = new LinkedHashMap<>(value);
+            dirty = false;
+        }
+    }
+
+    @Override
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withChild(final MapEntryNode child) {
+        checkDirty();
         this.value.put(child.getIdentifier(), child);
         return this;
     }
 
     @Override
-    public CollectionNodeBuilder<MapEntryNode, MapNode> withValue(List<MapEntryNode> value) {
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withoutChild(final InstanceIdentifier.PathArgument key) {
+        checkDirty();
+        this.value.remove(key);
+        return this;
+    }
+
+    @Override
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withValue(final List<MapEntryNode> value) {
         // TODO replace or putAll ?
-        for (MapEntryNode mapEntryNode : value) {
+        for (final MapEntryNode mapEntryNode : value) {
             withChild(mapEntryNode);
         }
 
         return this;
     }
 
-    public CollectionNodeBuilder<MapEntryNode, MapNode> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+    @Override
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withNodeIdentifier(final InstanceIdentifier.NodeIdentifier nodeIdentifier) {
         this.nodeIdentifier = nodeIdentifier;
         return this;
     }
 
     @Override
     public MapNode build() {
+        dirty = true;
         return new ImmutableMapNode(nodeIdentifier, value);
     }
 
-    static final class ImmutableMapNode extends AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<MapEntryNode>> implements MapNode {
+    @Override
+    public CollectionNodeBuilder<MapEntryNode, MapNode> addChild(
+            final MapEntryNode child) {
+        return withChild(child);
+    }
+
+
+    @Override
+    public NormalizedNodeContainerBuilder<NodeIdentifier, PathArgument, MapEntryNode, MapNode> removeChild(
+            final PathArgument key) {
+        return withoutChild(key);
+    }
+
+    protected static final class ImmutableMapNode extends AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<MapEntryNode>> implements Immutable,MapNode {
 
-        private final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mappedChildren;
+        private final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children;
 
-        ImmutableMapNode(InstanceIdentifier.NodeIdentifier nodeIdentifier,
-                         Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children) {
-            super(nodeIdentifier, children.values());
-            this.mappedChildren = children;
+        ImmutableMapNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
+                         final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children) {
+            super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+            this.children = children;
+        }
+
+        @Override
+        public Optional<MapEntryNode> getChild(final InstanceIdentifier.NodeIdentifierWithPredicates child) {
+            return Optional.fromNullable(children.get(child));
         }
 
         @Override
-        public Optional<MapEntryNode> getChild(InstanceIdentifier.NodeIdentifierWithPredicates child) {
-            return Optional.fromNullable(mappedChildren.get(child));
+        protected int valueHashCode() {
+            return children.hashCode();
         }
 
         @Override
-        public String toString() {
-            final StringBuffer sb = new StringBuffer("ImmutableMapNode{");
-            sb.append("nodeIdentifier=").append(nodeIdentifier);
-            sb.append(", children=").append(mappedChildren);
-            sb.append('}');
-            return sb.toString();
+        protected boolean valueEquals(final AbstractImmutableNormalizedNode<?, ?> other) {
+            return children.equals(((ImmutableMapNode) other).children);
         }
     }
 }
index 77a0e496d5c083870b9eddab867bdf0ead5d49d9..fc976ea432f6779196a94873079e4c242194ad30 100644 (file)
@@ -19,25 +19,38 @@ public class ImmutableMapNodeSchemaAwareBuilder extends ImmutableMapNodeBuilder
 
     private final ListSchemaNode schema;
 
-    protected ImmutableMapNodeSchemaAwareBuilder(ListSchemaNode schema) {
-        super();
-        this.schema = schema;
+    protected ImmutableMapNodeSchemaAwareBuilder(final ListSchemaNode schema) {
+        this.schema = Preconditions.checkNotNull(schema);
         super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
     }
 
-    public static CollectionNodeBuilder<MapEntryNode, MapNode> create(ListSchemaNode schema) {
+    protected ImmutableMapNodeSchemaAwareBuilder(final ListSchemaNode schema, final ImmutableMapNode node) {
+        super(node);
+        this.schema = Preconditions.checkNotNull(schema);
+        super.withNodeIdentifier(new InstanceIdentifier.NodeIdentifier(schema.getQName()));
+    }
+
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> create(final ListSchemaNode schema) {
         return new ImmutableMapNodeSchemaAwareBuilder(schema);
     }
 
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> create(final ListSchemaNode schema, final MapNode node) {
+        if (!(node instanceof ImmutableMapNode)) {
+            throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
+        }
+
+        return new ImmutableMapNodeSchemaAwareBuilder(schema, (ImmutableMapNode) node);
+    }
+
     @Override
-    public CollectionNodeBuilder<MapEntryNode, MapNode> withChild(MapEntryNode child) {
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withChild(final MapEntryNode child) {
         Preconditions.checkArgument(schema.getQName().equals(child.getNodeType()),
                 "Incompatible node type, should be: %s, is: %s", schema.getQName(), child.getNodeType());
         return super.withChild(child);
     }
 
     @Override
-    public CollectionNodeBuilder<MapEntryNode, MapNode> withNodeIdentifier(InstanceIdentifier.NodeIdentifier nodeIdentifier) {
+    public CollectionNodeBuilder<MapEntryNode, MapNode> withNodeIdentifier(final InstanceIdentifier.NodeIdentifier nodeIdentifier) {
         throw new UnsupportedOperationException("Node identifier created from schema");
     }
 }
index 8e0c1d32b05df344586819ba8a4a0e2ec110a25c..1879010d967d27a450f6f21ca8e651644ce4641f 100644 (file)
@@ -7,16 +7,19 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.Collections;
+
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeSchemaAwareBuilder;
 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.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 
-import java.util.Collection;
-import java.util.Collections;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
 /**
  * General validator for container like statements, e.g. container, list-entry, choice, augment
@@ -24,10 +27,10 @@ import java.util.Collections;
 public class DataNodeContainerValidator {
 
     private final DataNodeContainer schema;
-    private Collection<AugmentationSchema> augmentations;
+    private final Collection<AugmentationSchema> augmentations;
 
     public DataNodeContainerValidator(DataNodeContainer schema) {
-        this.schema = schema;
+        this.schema = Preconditions.checkNotNull(schema);
         augmentations = schema instanceof AugmentationTarget ? ((AugmentationTarget) schema)
                 .getAvailableAugmentations() : Collections.<AugmentationSchema> emptyList();
     }
@@ -40,9 +43,17 @@ public class DataNodeContainerValidator {
                     return true;
                 }
             }
-            // check regular child node
+            // check regular child node (also in child cases)
+        } else if(schema.getDataChildByName(child.getNodeType()) == null) {
+            for (DataSchemaNode dataSchemaNode : schema.getChildNodes()) {
+                if(dataSchemaNode instanceof ChoiceCaseNode) {
+                    if(((ChoiceCaseNode) dataSchemaNode).getDataChildByName(child.getNodeType()) != null) {
+                        return true;
+                    }
+                }
+            }
         } else {
-            return schema.getDataChildByName(child.getNodeType()) != null;
+            return true;
         }
 
         return false;
@@ -61,12 +72,12 @@ public class DataNodeContainerValidator {
     // FIXME, need to compare Set of QNames(AugmentationIdentifier) with Set of DataSchemaNodes(AugmentationSchema)
     // throw away set is created just to compare
     // Or if augmentationSchemaNode had a QName, we would just compare a QName
-    private boolean equalAugments(AugmentationSchema augmentationSchema, InstanceIdentifier.AugmentationIdentifier identifier) {
+    public static boolean equalAugments(AugmentationSchema augmentationSchema, InstanceIdentifier.AugmentationIdentifier identifier) {
         return identifier.getPossibleChildNames().equals(ImmutableAugmentationNodeSchemaAwareBuilder.getChildQNames(augmentationSchema));
     }
 
     public void validateChild(InstanceIdentifier.PathArgument child) {
-        Preconditions.checkArgument(isKnownChild(child), "Unknown child node: %s, does not belong to: %s", child.getNodeType(), schema);
+        Preconditions.checkArgument(isKnownChild(child), "Unknown child node: %s, does not belong to: %s", child, schema);
 
         // FIXME make a cache for augmentation child sets in constructor
         Optional<AugmentationSchema> augmentChild = isAugmentChild(child);
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerAttrNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerAttrNode.java
new file mode 100644 (file)
index 0000000..85d4a8e
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.nodes;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+
+import com.google.common.base.Objects.ToStringHelper;
+
+public abstract class AbstractImmutableDataContainerAttrNode<K extends InstanceIdentifier.PathArgument>
+        extends AbstractImmutableDataContainerNode<K>
+    implements AttributesContainer {
+
+    private final Map<QName, String> attributes;
+
+    public AbstractImmutableDataContainerAttrNode(
+            final Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children,
+            final K nodeIdentifier, final Map<QName, String> attributes) {
+        super(children, nodeIdentifier);
+        this.attributes = attributes;
+    }
+
+    @Override
+    public final Map<QName, String> getAttributes() {
+        return attributes;
+    }
+
+    @Override
+    public final Object getAttributeValue(final QName value) {
+        return attributes.get(value);
+    }
+
+    @Override
+    protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+        return super.addToStringAttributes(toStringHelper).add("attributes", attributes);
+    }
+
+// FIXME: are attributes part of hashCode/equals?
+//    @Override
+//    protected int valueHashCode() {
+//        int result = super.valueHashCode();
+//        for (final Entry<?, ?> a : attributes.entrySet()) {
+//            result = 31 * result + a.hashCode();
+//        }
+//        return result;
+//    }
+
+ // FIXME: are attributes part of hashCode/equals?
+//    @Override
+//    protected boolean valueEquals(final NormalizedNode<?, ?> other) {
+//        if (!super.valueEquals(other)) {
+//            return false;
+//        }
+//        final Set<Entry<QName, String>> tas = getAttributes().entrySet();
+//        final Set<Entry<QName, String>> oas = container.getAttributes().entrySet();
+//
+//        return tas.containsAll(oas) && oas.containsAll(tas);
+//        return true;
+//    }
+}
index 7954d56344bc1b729e9bad31c82b2e089c84a550..7c7d53d61ac210a77bc7a5dc7c7d3e29a5f3b334 100644 (file)
@@ -7,36 +7,50 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
 
+import java.util.Collections;
 import java.util.Map;
 
-import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
 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.Iterables;
 
-public abstract class AbstractImmutableDataContainerNode<K extends InstanceIdentifier.PathArgument>
-        extends AbstractImmutableNormalizedNode<K, Iterable<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>>>
-        implements DataContainerNode<K> {
+public abstract class AbstractImmutableDataContainerNode<K extends PathArgument> //
+        extends AbstractImmutableNormalizedNode<K, Iterable<DataContainerChild<? extends PathArgument, ?>>> //
+        implements Immutable, DataContainerNode<K> {
 
-    protected Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children;
+    protected final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children;
 
-    public AbstractImmutableDataContainerNode(Map<InstanceIdentifier.PathArgument, DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> children, K nodeIdentifier) {
-        super(nodeIdentifier, children.values());
+    public AbstractImmutableDataContainerNode(
+            final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children, final K nodeIdentifier) {
+        super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
         this.children = children;
     }
 
     @Override
-    public Optional<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>> getChild(InstanceIdentifier.PathArgument child) {
-        return Optional.<DataContainerChild<? extends InstanceIdentifier.PathArgument, ?>>fromNullable(children.get(child));
+    public final Optional<DataContainerChild<? extends PathArgument, ?>> getChild(final PathArgument child) {
+        return Optional.<DataContainerChild<? extends PathArgument, ?>> 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();
+    protected int valueHashCode() {
+        return children.hashCode();
+    }
+
+    public final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> getChildren() {
+        // Make sure we do not leak a mutable view
+        return Collections.unmodifiableMap(children);
+    }
+
+    @Override
+    protected boolean valueEquals(final AbstractImmutableNormalizedNode<?, ?> other) {
+        if (!(other instanceof AbstractImmutableDataContainerNode<?>)) {
+            return false;
+        }
+
+        return children.equals(((AbstractImmutableDataContainerNode<?>)other).children);
     }
 }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedAttrNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedAttrNode.java
new file mode 100644 (file)
index 0000000..a085069
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.nodes;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.collect.ImmutableMap;
+
+public abstract class AbstractImmutableNormalizedAttrNode<K extends InstanceIdentifier.PathArgument,V>
+        extends AbstractImmutableNormalizedNode<K, V>
+        implements AttributesContainer {
+
+    private final Map<QName, String> attributes;
+
+    protected AbstractImmutableNormalizedAttrNode(final K nodeIdentifier, final V value, final Map<QName, String> attributes) {
+        super(nodeIdentifier, value);
+        this.attributes = ImmutableMap.copyOf(attributes);
+    }
+
+    @Override
+    public final Map<QName, String> getAttributes() {
+        return attributes;
+    }
+
+    @Override
+    public final Object getAttributeValue(final QName value) {
+        return attributes.get(value);
+    }
+
+    @Override
+    protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+        return super.addToStringAttributes(toStringHelper).add("attributes", attributes);
+    }
+
+    @Override
+    protected int valueHashCode() {
+        final int result = getValue().hashCode();
+// FIXME: are attributes part of hashCode/equals?
+//        for (final Entry<?, ?> a : attributes.entrySet()) {
+//            result = 31 * result + a.hashCode();
+//        }
+        return result;
+    }
+
+    @Override
+    protected boolean valueEquals(final AbstractImmutableNormalizedNode<?, ?> other) {
+        if (!getValue().equals(other.getValue())) {
+            return false;
+        }
+
+// FIXME: are attributes part of hashCode/equals?
+//        final Set<Entry<QName, String>> tas = getAttributes().entrySet();
+//        final Set<Entry<QName, String>> oas = container.getAttributes().entrySet();
+//
+//        return tas.containsAll(oas) && oas.containsAll(tas);
+        return true;
+    }
+}
index ceb20124c81f709faf28cf6c647fac50be52e464..708f9225c2f29c640db725b4550b2d5386d2a6cf 100644 (file)
@@ -13,66 +13,87 @@ 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.Objects.ToStringHelper;
 import com.google.common.base.Preconditions;
 
 public abstract class AbstractImmutableNormalizedNode<K extends InstanceIdentifier.PathArgument,V>
         implements NormalizedNode<K, V>, Immutable {
 
-    protected final K nodeIdentifier;
-    protected V value;
+    private final K nodeIdentifier;
+    private final V value;
 
-    protected AbstractImmutableNormalizedNode(K nodeIdentifier, V value) {
+    protected AbstractImmutableNormalizedNode(final K nodeIdentifier, final V value) {
         this.nodeIdentifier = Preconditions.checkNotNull(nodeIdentifier, "nodeIdentifier");
         this.value = Preconditions.checkNotNull(value, "value");
     }
 
     @Override
-    public QName getNodeType() {
+    public final QName getNodeType() {
         return getIdentifier().getNodeType();
     }
 
     @Override
-    public K getIdentifier() {
+    public final K getIdentifier() {
         return nodeIdentifier;
     }
 
     @Override
-    public CompositeNode getParent() {
+    public final CompositeNode getParent() {
         throw new UnsupportedOperationException("Deprecated");
     }
 
     @Override
-    public QName getKey() {
+    public final QName getKey() {
         return getNodeType();
     }
 
     @Override
-    public V getValue() {
+    public final V getValue() {
         return value;
     }
 
     @Override
-    public V setValue(V value) {
+    public final V setValue(final V value) {
         throw new UnsupportedOperationException("Immutable");
     }
 
     @Override
-    public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof AbstractImmutableNormalizedNode)) return false;
+    public final String toString() {
+        return addToStringAttributes(Objects.toStringHelper(this)).toString();
+    }
 
-        AbstractImmutableNormalizedNode that = (AbstractImmutableNormalizedNode) o;
+    protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+        return toStringHelper.add("nodeIdentifier", nodeIdentifier).add("value", getValue());
+    }
 
-        if (!nodeIdentifier.equals(that.nodeIdentifier)) return false;
-        if (!value.equals(that.value)) return false;
+    protected abstract boolean valueEquals(AbstractImmutableNormalizedNode<?, ?> other);
+    protected abstract int valueHashCode();
 
-        return true;
+    @Override
+    public final boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (this.getClass() != obj.getClass()) {
+            return false;
+        }
+
+        final AbstractImmutableNormalizedNode<?, ?> other = (AbstractImmutableNormalizedNode<?, ?>)obj;
+        if (!nodeIdentifier.equals(other.nodeIdentifier)) {
+            return false;
+        }
+
+        return valueEquals(other);
     }
 
     @Override
-    public int hashCode() {
+    public final int hashCode() {
         int result = nodeIdentifier.hashCode();
-        result = 31 * result + value.hashCode();
+        result = 31 * result + valueHashCode();
         return result;
     }
 }
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 (file)
index 0000000..58d666e
--- /dev/null
@@ -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 <E>
+ *            type of resulting/serialized element from NormalizedNode
+ * @param <N>
+ *            type of NormalizedNode to be serialized
+ * @param <S>
+ *            schema belonging to the type N of NormalizedNode
+ */
+public interface FromNormalizedNodeSerializer<E, N extends NormalizedNode<?, ?>, 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<E> serialize(S schema, N node);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializerFactory.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/FromNormalizedNodeSerializerFactory.java
new file mode 100644 (file)
index 0000000..48fedda
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform;
+
+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.LeafSetEntryNode;
+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.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;
+
+/**
+ * Factory for different normalized node serializers.
+ *
+ * @param <E>
+ *            type of resulting/serialized element from NormalizedNode
+ */
+public interface FromNormalizedNodeSerializerFactory<E> {
+       FromNormalizedNodeSerializer<E, AugmentationNode, AugmentationSchema> getAugmentationNodeSerializer();
+       FromNormalizedNodeSerializer<E, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeSerializer();
+       FromNormalizedNodeSerializer<E, ContainerNode, ContainerSchemaNode> getContainerNodeSerializer();
+       FromNormalizedNodeSerializer<E, LeafNode<?>, LeafSchemaNode> getLeafNodeSerializer();
+       FromNormalizedNodeSerializer<E, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer();
+       FromNormalizedNodeSerializer<E, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeSerializer();
+       FromNormalizedNodeSerializer<E, MapEntryNode, ListSchemaNode> getMapEntryNodeSerializer();
+       FromNormalizedNodeSerializer<E, MapNode, ListSchemaNode> getMapNodeSerializer();
+}
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 (file)
index 0000000..a300cc0
--- /dev/null
@@ -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 parser for normalized nodes. NormalizedNodes can be parsed
+ * e.g. from Dom APIs.
+ *
+ * @param <E>
+ *            type of element to be parsed into NormalizedNode
+ * @param <N>
+ *            type of NormalizedNode to be the result of parsing
+ * @param <S>
+ *            schema belonging to the type N of NormalizedNode
+ */
+public interface ToNormalizedNodeParser<E, N extends NormalizedNode<?, ?>, 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<E> xmlDom, S schema);
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParserFactory.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/ToNormalizedNodeParserFactory.java
new file mode 100644 (file)
index 0000000..f99cbcf
--- /dev/null
@@ -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.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.LeafSetEntryNode;
+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.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;
+
+/**
+ * Factory for different normalized node parsers.
+ *
+ * @param <E>
+ *            type of element to be parsed into NormalizedNode
+ */
+public interface ToNormalizedNodeParserFactory<E> {
+       ToNormalizedNodeParser<E, AugmentationNode, AugmentationSchema> getAugmentationNodeParser();
+       ToNormalizedNodeParser<E, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeParser();
+       ToNormalizedNodeParser<E, ContainerNode, ContainerSchemaNode> getContainerNodeParser();
+       ToNormalizedNodeParser<E, LeafNode<?>, LeafSchemaNode> getLeafNodeParser();
+       ToNormalizedNodeParser<E, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeParser();
+       ToNormalizedNodeParser<E, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeParser();
+       ToNormalizedNodeParser<E, MapEntryNode, ListSchemaNode> getMapEntryNodeParser();
+       ToNormalizedNodeParser<E, MapNode, ListSchemaNode> getMapNodeParser();
+}
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 (file)
index 0000000..726c40c
--- /dev/null
@@ -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<DataSchemaNode> realChildSchemas;
+    private final Map<QName, DataSchemaNode> mappedChildSchemas;
+
+    public AugmentationSchemaProxy(AugmentationSchema augmentSchema, Set<DataSchemaNode> 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<UnknownSchemaNode> getUnknownSchemaNodes() {
+        return delegate.getUnknownSchemaNodes();
+    }
+
+    @Override
+    public Set<TypeDefinition<?>> getTypeDefinitions() {
+        return delegate.getTypeDefinitions();
+    }
+
+    @Override
+    public Set<DataSchemaNode> getChildNodes() {
+        return realChildSchemas;
+    }
+
+    @Override
+    public Set<GroupingDefinition> 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<UsesNode> 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 (file)
index 0000000..b4df8fe
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * 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.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.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.model.api.*;
+import java.util.*;
+
+public final class SchemaUtils {
+
+    private SchemaUtils() {
+    }
+
+    public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname) {
+        Set<DataSchemaNode> childNodes = schema.getChildNodes();
+        return findSchemaForChild(schema, qname, childNodes);
+    }
+
+    public static DataSchemaNode findSchemaForChild(DataNodeContainer schema, QName qname, Set<DataSchemaNode> childNodes) {
+        Optional<DataSchemaNode> 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<QName> qNames) {
+        Optional<AugmentationSchema> 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<QName> qNames) {
+        Optional<AugmentationSchema> 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<AugmentationSchema> findAugment(AugmentationTarget schema, Set<QName> qNames) {
+        for (AugmentationSchema augment : schema.getAvailableAugmentations()) {
+
+            HashSet<QName> qNamesFromAugment = Sets.newHashSet(Collections2.transform(augment.getChildNodes(), new Function<DataSchemaNode, QName>() {
+                @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<DataSchemaNode> 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<QName,ChoiceNode> mapChildElementsFromChoicesInAugment(AugmentationSchema schema, Set<DataSchemaNode> realChildSchemas) {
+        Map<QName, ChoiceNode> 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<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema) {
+        Set<DataSchemaNode> childNodes = schema.getChildNodes();
+
+        return mapChildElementsFromChoices(schema, childNodes);
+    }
+
+    private static Map<QName, ChoiceNode> mapChildElementsFromChoices(DataNodeContainer schema, Set<DataSchemaNode> childNodes) {
+        Map<QName, ChoiceNode> 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<QName, AugmentationSchema> augments = mapChildElementsFromAugments((AugmentationTarget) schema);
+
+            return Maps.filterKeys(mappedChoices, new Predicate<QName>() {
+                @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<QName, AugmentationSchema> mapChildElementsFromAugments(AugmentationTarget schema) {
+
+        Map<QName, AugmentationSchema> childNodesToAugmentation = Maps.newLinkedHashMap();
+
+        // Find QNames of augmented child nodes
+        Map<QName, AugmentationSchema> 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<QName> getChildNodes(DataNodeContainer nodeContainer) {
+        Set<QName> 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<DataSchemaNode> getRealSchemasForAugment(AugmentationTarget targetSchema, AugmentationSchema augmentSchema) {
+        if(targetSchema.getAvailableAugmentations().contains(augmentSchema) == false) {
+            return Collections.emptySet();
+        }
+
+        Set<DataSchemaNode> 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<DataSchemaNode> getRealSchemasForAugment(DataNodeContainer targetSchema,
+            AugmentationSchema augmentSchema) {
+        Set<DataSchemaNode> realChildNodes = Sets.newHashSet();
+        for (DataSchemaNode dataSchemaNode : augmentSchema.getChildNodes()) {
+            DataSchemaNode realChild = targetSchema.getDataChildByName(dataSchemaNode.getQName());
+            realChildNodes.add(realChild);
+        }
+        return realChildNodes;
+    }
+
+    public static Optional<ChoiceCaseNode> detectCase(ChoiceNode schema, DataContainerChild<?, ?> child) {
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            if (child instanceof AugmentationNode
+                    && belongsToCaseAugment(choiceCaseNode,
+                            (InstanceIdentifier.AugmentationIdentifier) child.getIdentifier())) {
+                return Optional.of(choiceCaseNode);
+            } else if (choiceCaseNode.getDataChildByName(child.getNodeType()) != null) {
+                return Optional.of(choiceCaseNode);
+            }
+        }
+
+        return Optional.absent();
+    }
+
+    public static boolean belongsToCaseAugment(ChoiceCaseNode caseNode, InstanceIdentifier.AugmentationIdentifier childToProcess) {
+        for (AugmentationSchema augmentationSchema : caseNode.getAvailableAugmentations()) {
+
+            Set<QName> currentAugmentChildNodes = Sets.newHashSet();
+            for (DataSchemaNode dataSchemaNode : augmentationSchema.getChildNodes()) {
+                currentAugmentChildNodes.add(dataSchemaNode.getQName());
+            }
+
+            if(childToProcess.getPossibleChildNames().equals(currentAugmentChildNodes)){
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
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 (file)
index 0000000..804f28c
--- /dev/null
@@ -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 <E> type of elements to be parsed
+ */
+public abstract class AugmentationNodeBaseParser<E> extends
+        BaseDispatcherParser<E,AugmentationNode, AugmentationSchema> {
+
+    @Override
+    protected final DataContainerNodeBuilder<InstanceIdentifier.AugmentationIdentifier, AugmentationNode> getBuilder(AugmentationSchema schema) {
+        return Builders.augmentationBuilder(schema);
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> 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<QName, ChoiceNode> mapChildElementsFromChoices(AugmentationSchema schema) {
+        return SchemaUtils.mapChildElementsFromChoices(schema);
+    }
+
+    @Override
+    protected final Map<QName, AugmentationSchema> 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 (file)
index 0000000..9101c2b
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * 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.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.AttributesBuilder;
+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<E, N extends DataContainerNode<?>, S>
+        implements ToNormalizedNodeParser<E, N, S> {
+
+    /**
+     *
+     * @param schema
+     * @return New(empty) instance of a builder to build node identified by schema.
+     */
+    protected abstract DataContainerNodeBuilder<?, N> 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<QName, E> mapChildElements(Iterable<E> 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<QName, ChoiceNode> mapChildElementsFromChoices(S schema);
+
+    /**
+     *
+     * @param schema
+     * @return map from QName to child elements that are added by augmentation
+     *         that targets current schema.
+     */
+    protected abstract Map<QName, AugmentationSchema> 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<DataSchemaNode> 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<E> getDispatcher();
+
+    @Override
+    public N parse(Iterable<E> elements, S schema) {
+
+        checkAtLeastOneNode(schema, elements);
+
+        DataContainerNodeBuilder<?, N> containerBuilder = getBuilder(schema);
+
+        // Map child nodes to QName
+        LinkedListMultimap<QName, E> mappedChildElements = mapChildElements(elements);
+
+        // Map child nodes from Augments
+        Map<QName, AugmentationSchema> mappedAugmentChildNodes = mapChildElementsFromAugments(schema);
+        LinkedListMultimap<AugmentationSchema, E> augmentsToElements = LinkedListMultimap.create();
+
+        // Map child nodes from choices
+        Map<QName, ChoiceNode> mappedChoiceChildNodes = mapChildElementsFromChoices(schema);
+        LinkedListMultimap<ChoiceNode, E> choicesToElements = LinkedListMultimap.create();
+
+        // process Child nodes
+        for (QName childPartialQName : mappedChildElements.keySet()) {
+            DataSchemaNode childSchema = getSchemaForChild(schema, childPartialQName);
+            List<E> 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<? extends InstanceIdentifier.PathArgument, ?> 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<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augmentSchema);
+            AugmentationSchemaProxy augSchemaProxy = new AugmentationSchemaProxy(augmentSchema, realChildSchemas);
+            containerBuilder.withChild(getDispatcher().dispatchChildElement(augSchemaProxy, augmentsToElements.get(augmentSchema)));
+        }
+
+        if (containerBuilder instanceof AttributesBuilder) {
+            final int size = Iterables.size(elements);
+            Preconditions.checkArgument(size == 1, "Unexpected number of elements: %s, should be 1 for: %s",
+                    size, schema);
+            ((AttributesBuilder<?>) containerBuilder).withAttributes(getAttributes(elements.iterator().next()));
+        }
+
+        return containerBuilder.build();
+    }
+
+    protected Map<QName, String> getAttributes(E e) {
+        return Collections.emptyMap();
+    }
+
+    private boolean isMarkedAs(Map<QName, ?> mappedAugmentChildNodes, QName qName) {
+        return mappedAugmentChildNodes.containsKey(qName);
+    }
+
+    protected void checkOnlyOneNode(S schema, Iterable<E> 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<E> 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 (file)
index 0000000..021efc0
--- /dev/null
@@ -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 <E> type of elements to be parsed
+ */
+public abstract class ChoiceNodeBaseParser<E> extends
+        BaseDispatcherParser<E, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> {
+
+    @Override
+    protected final DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ChoiceNode> getBuilder(
+            org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+        return Builders.choiceBuilder(schema);
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> getRealSchemasForAugment(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+            AugmentationSchema augmentSchema) {
+        Set<DataSchemaNode> 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<QName, org.opendaylight.yangtools.yang.model.api.ChoiceNode> mapChildElementsFromChoices(
+            org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+        Map<QName, org.opendaylight.yangtools.yang.model.api.ChoiceNode> mappedChoices = Maps.newLinkedHashMap();
+
+        for (ChoiceCaseNode choiceCaseNode : schema.getCases()) {
+            mappedChoices.putAll(SchemaUtils.mapChildElementsFromChoices(choiceCaseNode));
+        }
+
+        return mappedChoices;
+    }
+
+    @Override
+    protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(
+            org.opendaylight.yangtools.yang.model.api.ChoiceNode schema) {
+        Map<QName, AugmentationSchema> 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 (file)
index 0000000..6809799
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * 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 <E> type of elements to be parsed
+ */
+public abstract class ContainerNodeBaseParser<E> extends
+        BaseDispatcherParser<E, ContainerNode, ContainerSchemaNode> {
+
+    @Override
+    protected final DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> getBuilder(
+            ContainerSchemaNode schema) {
+        return Builders.containerBuilder(schema);
+    }
+
+    @Override
+    public final ContainerNode parse(Iterable<E> elements, ContainerSchemaNode schema) {
+        checkOnlyOneNode(schema, elements);
+        return super.parse(elements, schema);
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> 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<QName, ChoiceNode> mapChildElementsFromChoices(ContainerSchemaNode schema) {
+        return SchemaUtils.mapChildElementsFromChoices(schema);
+    }
+
+    @Override
+    protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(ContainerSchemaNode schema) {
+        return SchemaUtils.mapChildElementsFromAugments(schema);
+    }
+
+    @Override
+    protected abstract Map<QName, String> getAttributes(E e);
+}
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 (file)
index 0000000..a6c3091
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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 org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+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.builder.api.NormalizedNodeAttrBuilder;
+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 <E> type of elements to be parsed
+ */
+public abstract class LeafNodeBaseParser<E> implements
+        ToNormalizedNodeParser<E, LeafNode<?>, LeafSchemaNode> {
+
+    @Override
+    public final LeafNode<?> parse(Iterable<E> elements, LeafSchemaNode schema) {
+        final int size = Iterables.size(elements);
+        Preconditions.checkArgument(size == 1, "Elements mapped to leaf node illegal count: %s", size);
+
+        final E e = elements.iterator().next();
+        Object value = parseLeaf(e, schema);
+
+        NormalizedNodeAttrBuilder<InstanceIdentifier.NodeIdentifier,Object,LeafNode<Object>> leafBuilder = Builders.leafBuilder(schema);
+
+        leafBuilder.withAttributes(getAttributes(e));
+
+        return leafBuilder.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);
+
+    /**
+     *
+     * @param e
+     * @return attributes mapped to QNames
+     */
+    protected abstract Map<QName, String> getAttributes(E e);
+}
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 (file)
index 0000000..f127209
--- /dev/null
@@ -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 org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+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.builder.api.NormalizedNodeAttrBuilder;
+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 <E> type of elements to be parsed
+ */
+public abstract class LeafSetEntryNodeBaseParser<E> implements
+        ToNormalizedNodeParser<E, LeafSetEntryNode<?>, LeafListSchemaNode> {
+
+    @Override
+    public final LeafSetEntryNode<Object> parse(Iterable<E> elements, LeafListSchemaNode schema) {
+        final int size = Iterables.size(elements);
+        Preconditions.checkArgument(size == 1, "Xml elements mapped to leaf node illegal count: %s", size);
+
+        final E e = elements.iterator().next();
+        Object value = parseLeafListEntry(e,schema);
+
+        NormalizedNodeAttrBuilder<InstanceIdentifier.NodeWithValue, Object, LeafSetEntryNode<Object>> leafEntryBuilder = Builders
+                .leafSetEntryBuilder(schema);
+        leafEntryBuilder.withAttributes(getAttributes(e));
+
+        return leafEntryBuilder.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);
+
+    /**
+     *
+     * @param e
+     * @return attributes mapped to QNames
+     */
+    protected abstract Map<QName, String> getAttributes(E e);
+
+}
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 (file)
index 0000000..aaa2f21
--- /dev/null
@@ -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 <E> type of elements to be parsed
+ */
+public abstract class LeafSetNodeBaseParser<E> implements
+        ToNormalizedNodeParser<E, LeafSetNode<?>, LeafListSchemaNode> {
+
+    @Override
+    public final LeafSetNode<?> parse(Iterable<E> childNodes, LeafListSchemaNode schema) {
+
+        ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafListBuilder = Builders.leafSetBuilder(schema);
+        for (E childNode : childNodes) {
+            LeafSetEntryNode<?> builtChild = getLeafSetEntryNodeParser().parse(
+                    Collections.singletonList(childNode), schema);
+
+            // TODO: can we get rid of this cast/SuppressWarnings somehow?
+            @SuppressWarnings("unchecked")
+            final LeafSetEntryNode<Object> child = (LeafSetEntryNode<Object>) 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<E, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeParser();
+}
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 (file)
index 0000000..cf25fd8
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * 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 <E> type of elements to be parsed
+ */
+public abstract class MapEntryNodeBaseParser<E> extends BaseDispatcherParser<E, MapEntryNode, ListSchemaNode> {
+
+    @Override
+    protected final DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> getBuilder(
+            ListSchemaNode schema) {
+        return Builders.mapEntryBuilder(schema);
+    }
+
+    @Override
+    public final MapEntryNode parse(Iterable<E> elements, ListSchemaNode schema) {
+        checkOnlyOneNode(schema, elements);
+        return super.parse(elements, schema);
+    }
+
+    @Override
+    protected final Set<DataSchemaNode> 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<QName, ChoiceNode> mapChildElementsFromChoices(ListSchemaNode schema) {
+        return SchemaUtils.mapChildElementsFromChoices(schema);
+    }
+
+    @Override
+    protected final Map<QName, AugmentationSchema> mapChildElementsFromAugments(ListSchemaNode schema) {
+        return SchemaUtils.mapChildElementsFromAugments(schema);
+    }
+
+    @Override
+    protected abstract Map<QName, String> getAttributes(E e);
+}
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 (file)
index 0000000..6aeb1ed
--- /dev/null
@@ -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 <E> type of elements to be parsed
+ */
+public abstract class MapNodeBaseParser<E> implements ToNormalizedNodeParser<E, MapNode, ListSchemaNode> {
+
+    @Override
+    public final MapNode parse(Iterable<E> childNodes, ListSchemaNode schema) {
+        CollectionNodeBuilder<MapEntryNode, MapNode> listBuilder = Builders.mapBuilder(schema);
+
+        for (E childNode : childNodes) {
+            MapEntryNode listChild = getMapEntryNodeParser().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<E, MapEntryNode, ListSchemaNode> getMapEntryNodeParser();
+
+}
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 (file)
index 0000000..40722b3
--- /dev/null
@@ -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.List;
+
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParserFactory;
+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 <E> type of elements parsed
+ */
+public interface NodeParserDispatcher<E> {
+
+    DataContainerChild<?, ?> dispatchChildElement(Object schema, List<E> 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<E> implements NodeParserDispatcher<E> {
+        private final ToNormalizedNodeParserFactory<E> factory;
+
+        protected BaseNodeParserDispatcher(final ToNormalizedNodeParserFactory<E> factory) {
+            this.factory = Preconditions.checkNotNull(factory);
+        }
+
+        @Override
+        public final DataContainerChild<?, ?> dispatchChildElement(Object schema, List<E> childNodes) {
+            Preconditions.checkArgument(childNodes.isEmpty() == false);
+
+            if (schema instanceof ContainerSchemaNode) {
+                return factory.getContainerNodeParser().parse(childNodes, (ContainerSchemaNode) schema);
+            } else if (schema instanceof LeafSchemaNode) {
+                return factory.getLeafNodeParser().parse(childNodes, (LeafSchemaNode) schema);
+            } else if (schema instanceof LeafListSchemaNode) {
+                return factory.getLeafSetNodeParser().parse(childNodes, (LeafListSchemaNode) schema);
+            } else if (schema instanceof ListSchemaNode) {
+                return factory.getMapNodeParser().parse(childNodes, (ListSchemaNode) schema);
+            } else if (schema instanceof ChoiceNode) {
+                return factory.getChoiceNodeParser().parse(childNodes, (ChoiceNode) schema);
+            } else if (schema instanceof AugmentationSchema) {
+                return factory.getAugmentationNodeParser().parse(childNodes, (AugmentationSchema) schema);
+            }
+
+            throw new IllegalArgumentException("Unable to parse node, unknown schema type: " + schema.getClass());
+        }
+    }
+}
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 (file)
index 0000000..35dd342
--- /dev/null
@@ -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 <E> type of serialized elements
+ */
+public abstract class AugmentationNodeBaseSerializer<E> extends
+        BaseDispatcherSerializer<E, AugmentationNode, AugmentationSchema> {
+
+    @Override
+    protected Set<DataSchemaNode> getRealSchemasForAugment(AugmentationSchema schema, AugmentationSchema augmentationSchema) {
+        return SchemaUtils.getRealSchemasForAugment(schema, augmentationSchema);
+    }
+
+    @Override
+    protected DataSchemaNode getSchemaForChild(AugmentationSchema schema,
+                                               DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> 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 (file)
index 0000000..053520d
--- /dev/null
@@ -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<E, N extends DataContainerNode<?>, S> implements
+        FromNormalizedNodeSerializer<E, N, S> {
+
+    /**
+     *
+     * @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<DataSchemaNode> 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<? extends InstanceIdentifier.PathArgument, ?> 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<E> getNodeDispatcher();
+
+    @Override
+    public Iterable<E> serialize(S schema, N node) {
+        List<Iterable<E>> choiceChildren = Lists.newArrayList();
+
+        for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> choiceChild : node.getValue()) {
+
+            Object childSchema;
+
+            if (choiceChild instanceof AugmentationNode) {
+
+                AugmentationSchema augSchema = getAugmentedCase(schema, (AugmentationNode) choiceChild);
+                Set<DataSchemaNode> realChildSchemas = getRealSchemasForAugment(schema, augSchema);
+                childSchema = new AugmentationSchemaProxy(augSchema, realChildSchemas);
+
+            } else {
+                childSchema = getSchemaForChild(schema, choiceChild);
+            }
+
+            Iterable<E> 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 (file)
index 0000000..af779b6
--- /dev/null
@@ -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 <E> type of serialized elements
+ */
+public abstract class ChoiceNodeBaseSerializer<E>
+        extends
+        BaseDispatcherSerializer<E, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> {
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema,
+            DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> 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<DataSchemaNode> getRealSchemasForAugment(org.opendaylight.yangtools.yang.model.api.ChoiceNode schema, AugmentationSchema augmentationSchema) {
+        Set<DataSchemaNode> 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 (file)
index 0000000..6d0b9f9
--- /dev/null
@@ -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 <E> type of serialized elements
+ */
+public abstract class ContainerNodeBaseSerializer<E> extends
+        BaseDispatcherSerializer<E, ContainerNode, ContainerSchemaNode> {
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(ContainerSchemaNode schema,
+            DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> 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<DataSchemaNode> 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 (file)
index 0000000..2e13766
--- /dev/null
@@ -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 <E> type of serialized elements
+ */
+public abstract class LeafNodeBaseSerializer<E> implements
+        FromNormalizedNodeSerializer<E, LeafNode<?>, LeafSchemaNode> {
+
+    @Override
+    public final Iterable<E> 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 (file)
index 0000000..f690590
--- /dev/null
@@ -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 <E> type of serialized elements
+ */
+public abstract class LeafSetEntryNodeBaseSerializer<E> implements
+        FromNormalizedNodeSerializer<E, LeafSetEntryNode<?>, LeafListSchemaNode> {
+
+    @Override
+    public final Iterable<E> 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 (file)
index 0000000..302ffbb
--- /dev/null
@@ -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 <E> type of serialized elements
+ */
+public abstract class LeafSetNodeBaseSerializer<E> implements
+        FromNormalizedNodeSerializer<E, LeafSetNode<?>, LeafListSchemaNode> {
+
+    @Override
+    public final Iterable<E> serialize(final LeafListSchemaNode schema, final LeafSetNode<?> node) {
+        return Iterables.concat(Iterables.transform(node.getValue(), new Function<LeafSetEntryNode<?>, Iterable<E>>() {
+            @Override
+            public Iterable<E> apply(final LeafSetEntryNode<?> input) {
+                final Iterable<E> 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<E, LeafSetEntryNode<?>, 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 (file)
index 0000000..2f7822a
--- /dev/null
@@ -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 <E> type of serialized elements
+ */
+public abstract class MapEntryNodeBaseSerializer<E> extends
+        BaseDispatcherSerializer<E, MapEntryNode, ListSchemaNode> {
+
+    @Override
+    protected final DataSchemaNode getSchemaForChild(ListSchemaNode schema,
+                                               DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> 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<DataSchemaNode> 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 (file)
index 0000000..dba2c5d
--- /dev/null
@@ -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 <E> type of serialized elements
+ */
+public abstract class MapNodeBaseSerializer<E> implements FromNormalizedNodeSerializer<E, MapNode, ListSchemaNode> {
+
+    @Override
+    public final Iterable<E> serialize(final ListSchemaNode schema, final MapNode node) {
+        return Iterables.concat(Iterables.transform(node.getValue(), new Function<MapEntryNode, Iterable<E>>() {
+            @Override
+            public Iterable<E> apply(MapEntryNode input) {
+                final Iterable<E> 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<E, MapEntryNode, ListSchemaNode> 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 (file)
index 0000000..9c1adfc
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * 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.FromNormalizedNodeSerializerFactory;
+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 <E> type of serialized elements
+ */
+public interface NodeSerializerDispatcher<E> {
+
+    Iterable<E> dispatchChildElement(Object childSchema,
+            DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> 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<E> implements NodeSerializerDispatcher<E> {
+        private final FromNormalizedNodeSerializerFactory<E> factory;
+
+        protected BaseNodeSerializerDispatcher(final FromNormalizedNodeSerializerFactory<E> factory) {
+            this.factory = Preconditions.checkNotNull(factory);
+        }
+
+        @Override
+        public final Iterable<E> dispatchChildElement(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> 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<E> onAugmentationSchema(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, AugmentationSchema.class, dataContainerChild);
+            return factory.getAugmentationNodeSerializer().serialize((AugmentationSchema) childSchema,
+                    (AugmentationNode) dataContainerChild);
+        }
+
+        private Iterable<E> onChoiceNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, org.opendaylight.yangtools.yang.model.api.ChoiceNode.class,
+                    dataContainerChild);
+            return factory.getChoiceNodeSerializer()
+                    .serialize((org.opendaylight.yangtools.yang.model.api.ChoiceNode) childSchema,
+                            (ChoiceNode) dataContainerChild);
+        }
+
+        private Iterable<E> onListNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, ListSchemaNode.class, dataContainerChild);
+            return factory.getMapNodeSerializer().serialize((ListSchemaNode) childSchema, (MapNode) dataContainerChild);
+        }
+
+        private Iterable<E> onLeafListNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, LeafListSchemaNode.class, dataContainerChild);
+            return factory.getLeafSetNodeSerializer().serialize((LeafListSchemaNode) childSchema,
+                    (LeafSetNode<?>) dataContainerChild);
+        }
+
+        private Iterable<E> onLeafNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, LeafSchemaNode.class, dataContainerChild);
+            Iterable<E> elements = factory.getLeafNodeSerializer().serialize((LeafSchemaNode) childSchema,
+                    (LeafNode<?>) dataContainerChild);
+            checkOnlyOneSerializedElement(elements, dataContainerChild);
+            return elements;
+        }
+
+        private static void checkOnlyOneSerializedElement(Iterable<?> elements,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> 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<E> onContainerNode(Object childSchema,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            checkSchemaCompatibility(childSchema, ContainerSchemaNode.class, dataContainerChild);
+
+            Iterable<E> elements = factory.getContainerNodeSerializer().serialize((ContainerSchemaNode) childSchema,
+                    (ContainerNode) dataContainerChild);
+            checkOnlyOneSerializedElement(elements, dataContainerChild);
+            return elements;
+        }
+
+        private static void checkSchemaCompatibility(Object childSchema, Class<?> containerSchemaNodeClass,
+                DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> dataContainerChild) {
+            Preconditions.checkArgument(containerSchemaNodeClass.isAssignableFrom(childSchema.getClass()),
+                    "Incompatible schema: %s with node: %s, expected: %s", childSchema, dataContainerChild,
+                    containerSchemaNodeClass);
+        }
+    }
+}
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 (file)
index 0000000..afcbe35
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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.net.URI;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.XMLConstants;
+
+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.NamedNodeMap;
+import org.w3c.dom.Node;
+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<Object, ? extends TypeDefinition<?>> 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<Object, ? extends TypeDefinition<?>> 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<? extends TypeDefinition<?>> type, XmlCodecProvider codecProvider, Object value) {
+        XmlDocumentUtils.writeValueByType(itemEl, type, codecProvider, value);
+    }
+
+    public static LinkedListMultimap<QName, Element> mapChildElementsForSingletonNode(Element node) {
+        List<Element> 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<QName, Element> mapChildElements(Iterable<Element> childNodesCollection) {
+        LinkedListMultimap<QName, Element> mappedChildElements = LinkedListMultimap.create();
+
+        for (Element element : childNodesCollection) {
+            QName childQName = XmlDocumentUtils.qNameFromElement(element);
+            mappedChildElements.put(childQName, element);
+        }
+
+        return mappedChildElements;
+    }
+
+
+    public static Map<QName, String> toAttributes(NamedNodeMap xmlAttributes) {
+        Map<QName, String> attributes = new HashMap<>();
+
+        for (int i = 0; i < xmlAttributes.getLength(); i++) {
+            Node node = xmlAttributes.item(i);
+            String namespace = node.getNamespaceURI();
+            if (namespace == null) {
+                namespace = "";
+            }
+
+            // Skip namespace definitions
+            if(namespace.equals(XMLConstants.XMLNS_ATTRIBUTE_NS_URI)) {
+                continue;
+            }
+
+            QName qName = new QName(URI.create(namespace), node.getLocalName());
+            attributes.put(qName, node.getNodeValue());
+        }
+        return attributes;
+    }
+}
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 (file)
index 0000000..7a5b551
--- /dev/null
@@ -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.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+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;
+
+final class AugmentationNodeDomParser extends AugmentationNodeBaseParser<Element> {
+
+    private final NodeParserDispatcher<Element> dispatcher;
+
+    AugmentationNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
+        return DomUtils.mapChildElements(elements);
+    }
+
+    @Override
+    protected NodeParserDispatcher<Element> getDispatcher() {
+        return dispatcher;
+    }
+
+}
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 (file)
index 0000000..97e8a61
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * 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.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;
+
+final class ChoiceNodeDomParser extends ChoiceNodeBaseParser<Element> {
+
+    private final NodeParserDispatcher<Element> dispatcher;
+
+    ChoiceNodeDomParser(NodeParserDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> xml) {
+        return DomUtils.mapChildElements(xml);
+    }
+
+    @Override
+    protected NodeParserDispatcher<Element> getDispatcher() {
+        return dispatcher;
+    }
+}
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 (file)
index 0000000..c03113a
--- /dev/null
@@ -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.dom.parser;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+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;
+
+final class ContainerNodeDomParser extends ContainerNodeBaseParser<Element> {
+
+    private final NodeParserDispatcher<Element> dispatcher;
+
+    ContainerNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected Map<QName, String> getAttributes(Element element) {
+        return DomUtils.toAttributes(element.getAttributes());
+    }
+
+    @Override
+    protected NodeParserDispatcher<Element> getDispatcher() {
+        return dispatcher;
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> 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/DomToNormalizedNodeParserFactory.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/parser/DomToNormalizedNodeParserFactory.java
new file mode 100644 (file)
index 0000000..53d68f8
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser;
+
+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.LeafSetEntryNode;
+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.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+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.Element;
+
+public final class DomToNormalizedNodeParserFactory implements ToNormalizedNodeParserFactory<Element> {
+    private final AugmentationNodeDomParser augmentationNodeParser;
+    private final ChoiceNodeDomParser choiceNodeParser;
+    private final ContainerNodeDomParser containerNodeParser;
+    private final LeafNodeDomParser leafNodeParser;
+    private final LeafSetEntryNodeDomParser leafSetEntryNodeParser;
+    private final LeafSetNodeDomParser leafSetNodeParser;
+    private final MapNodeDomParser mapNodeParser;
+    private final MapEntryNodeDomParser mapEntryNodeParser;
+
+    private DomToNormalizedNodeParserFactory(final XmlCodecProvider codecProvider) {
+        leafNodeParser = new LeafNodeDomParser(codecProvider);
+        leafSetEntryNodeParser = new LeafSetEntryNodeDomParser(codecProvider);
+        leafSetNodeParser = new LeafSetNodeDomParser(leafSetEntryNodeParser);
+
+        final NodeParserDispatcher<Element> dispatcher = new NodeParserDispatcher.BaseNodeParserDispatcher<Element>(this) {
+
+        };
+
+        containerNodeParser = new ContainerNodeDomParser(dispatcher);
+        mapEntryNodeParser = new MapEntryNodeDomParser(dispatcher);
+        mapNodeParser = new MapNodeDomParser(mapEntryNodeParser);
+        choiceNodeParser = new ChoiceNodeDomParser(dispatcher);
+        augmentationNodeParser = new AugmentationNodeDomParser(dispatcher);
+    }
+
+    public static DomToNormalizedNodeParserFactory getInstance(final XmlCodecProvider codecProvider) {
+        return new DomToNormalizedNodeParserFactory(codecProvider);
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Element, AugmentationNode, AugmentationSchema> getAugmentationNodeParser() {
+        return augmentationNodeParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Element, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeParser() {
+        return choiceNodeParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Element, ContainerNode, ContainerSchemaNode> getContainerNodeParser() {
+        return containerNodeParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Element, LeafNode<?>, LeafSchemaNode> getLeafNodeParser() {
+        return leafNodeParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Element, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeParser() {
+        return leafSetEntryNodeParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Element, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeParser() {
+        return leafSetNodeParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Element, MapEntryNode, ListSchemaNode> getMapEntryNodeParser() {
+        return mapEntryNodeParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Element, MapNode, ListSchemaNode> getMapNodeParser() {
+        return mapNodeParser;
+    }
+}
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 (file)
index 0000000..6c5d064
--- /dev/null
@@ -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 java.util.Map;
+
+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.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;
+
+import com.google.common.base.Preconditions;
+
+final class LeafNodeDomParser extends LeafNodeBaseParser<Element> {
+
+    private final XmlCodecProvider codecProvider;
+
+    LeafNodeDomParser(XmlCodecProvider codecProvider) {
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected Object parseLeaf(Element xmlElement, LeafSchemaNode schema) {
+        return DomUtils.parseXmlValue(xmlElement, codecProvider, schema.getType());
+    }
+
+    @Override
+    protected Map<QName, String> getAttributes(Element element) {
+        return DomUtils.toAttributes(element.getAttributes());
+    }
+}
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 (file)
index 0000000..2b224a0
--- /dev/null
@@ -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 java.util.Map;
+
+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.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;
+
+import com.google.common.base.Preconditions;
+
+final class LeafSetEntryNodeDomParser extends LeafSetEntryNodeBaseParser<Element> {
+
+    private final XmlCodecProvider codecProvider;
+
+    LeafSetEntryNodeDomParser(XmlCodecProvider codecProvider) {
+        this.codecProvider = Preconditions.checkNotNull(codecProvider);
+    }
+
+    @Override
+    protected Object parseLeafListEntry(Element xmlElement, LeafListSchemaNode schema) {
+        return DomUtils.parseXmlValue(xmlElement, codecProvider, schema.getType());
+    }
+
+    @Override
+    protected Map<QName, String> getAttributes(Element element) {
+        return DomUtils.toAttributes(element.getAttributes());
+    }
+}
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 (file)
index 0000000..adb2978
--- /dev/null
@@ -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;
+
+final class LeafSetNodeDomParser extends LeafSetNodeBaseParser<Element> {
+
+    private final LeafSetEntryNodeDomParser leafSetEntryNodeBaseParser;
+
+    LeafSetNodeDomParser(LeafSetEntryNodeDomParser leafSetEntryNodeBaseParser) {
+        this.leafSetEntryNodeBaseParser = leafSetEntryNodeBaseParser;
+    }
+
+    @Override
+    protected ToNormalizedNodeParser<Element, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeParser() {
+        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 (file)
index 0000000..65dde5c
--- /dev/null
@@ -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.dom.parser;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+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;
+
+final class MapEntryNodeDomParser extends MapEntryNodeBaseParser<Element> {
+
+    private final NodeParserDispatcher<Element> dispatcher;
+
+    MapEntryNodeDomParser(final NodeParserDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Element> mapChildElements(Iterable<Element> elements) {
+        return DomUtils.mapChildElementsForSingletonNode(elements.iterator().next());
+    }
+
+    @Override
+    protected NodeParserDispatcher<Element> getDispatcher() {
+        return dispatcher;
+    }
+
+    @Override
+    protected Map<QName, String> getAttributes(Element element) {
+        return DomUtils.toAttributes(element.getAttributes());
+    }
+}
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 (file)
index 0000000..0dd00aa
--- /dev/null
@@ -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;
+
+final class MapNodeDomParser extends MapNodeBaseParser<Element> {
+
+    private final MapEntryNodeDomParser mapEntryParser;
+
+    MapNodeDomParser(MapEntryNodeDomParser mapEntryParser) {
+        this.mapEntryParser = mapEntryParser;
+    }
+
+    @Override
+    protected ToNormalizedNodeParser<Element, MapEntryNode, ListSchemaNode> getMapEntryNodeParser() {
+        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 (file)
index 0000000..9954740
--- /dev/null
@@ -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;
+
+final class AugmentationNodeDomSerializer extends
+        AugmentationNodeBaseSerializer<Element> {
+
+    private final NodeSerializerDispatcher<Element> dispatcher;
+
+    AugmentationNodeDomSerializer(NodeSerializerDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Element> 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 (file)
index 0000000..8579202
--- /dev/null
@@ -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;
+
+final class ChoiceNodeDomSerializer extends ChoiceNodeBaseSerializer<Element> {
+    private final NodeSerializerDispatcher<Element> dispatcher;
+
+    ChoiceNodeDomSerializer(final NodeSerializerDispatcher<Element> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Element> 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 (file)
index 0000000..3144806
--- /dev/null
@@ -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;
+
+final class ContainerNodeDomSerializer extends
+        ContainerNodeBaseSerializer<Element> {
+
+    private final NodeSerializerDispatcher<Element> dispatcher;
+    private final Document doc;
+
+    ContainerNodeDomSerializer(final Document doc, final NodeSerializerDispatcher<Element> dispatcher) {
+        this.doc = Preconditions.checkNotNull(doc);
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    public Iterable<Element> 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<Element> getNodeDispatcher() {
+        return dispatcher;
+    }
+
+}
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomFromNormalizedNodeSerializerFactory.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/transform/dom/serializer/DomFromNormalizedNodeSerializerFactory.java
new file mode 100644 (file)
index 0000000..0a5aba7
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer;
+
+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.LeafSetEntryNode;
+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.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializerFactory;
+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;
+
+public final class DomFromNormalizedNodeSerializerFactory implements FromNormalizedNodeSerializerFactory<Element> {
+    private final ContainerNodeDomSerializer containerSerializer;
+    private final ChoiceNodeDomSerializer choiceSerializer;
+    private final AugmentationNodeDomSerializer augmentSerializer;
+    private final LeafNodeDomSerializer leafNodeSerializer;
+    private final LeafSetNodeDomSerializer leafSetSerializer;
+    private final MapNodeDomSerializer mapNodeSerializer;
+    private final LeafSetEntryNodeDomSerializer leafSetEntryNodeSerializer;
+       private final MapEntryNodeDomSerializer mapEntryNodeSerializer;
+
+       private DomFromNormalizedNodeSerializerFactory(final Document doc, final XmlCodecProvider codecProvider) {
+               final NodeSerializerDispatcher.BaseNodeSerializerDispatcher<Element> dispatcher = new NodeSerializerDispatcher.BaseNodeSerializerDispatcher<Element>(this) {
+
+               };
+
+        containerSerializer = new ContainerNodeDomSerializer(doc, dispatcher);
+        choiceSerializer = new ChoiceNodeDomSerializer(dispatcher);
+        augmentSerializer = new AugmentationNodeDomSerializer(dispatcher);
+        leafNodeSerializer = new LeafNodeDomSerializer(doc, codecProvider);
+
+        leafSetEntryNodeSerializer = new LeafSetEntryNodeDomSerializer(doc, codecProvider);
+        leafSetSerializer = new LeafSetNodeDomSerializer(leafSetEntryNodeSerializer);
+
+        mapEntryNodeSerializer = new MapEntryNodeDomSerializer(doc, dispatcher);
+        mapNodeSerializer = new MapNodeDomSerializer(mapEntryNodeSerializer);
+       }
+
+       public static DomFromNormalizedNodeSerializerFactory getInstance(final Document doc, final XmlCodecProvider codecProvider) {
+               return new DomFromNormalizedNodeSerializerFactory(doc, codecProvider);
+       }
+
+       @Override
+       public FromNormalizedNodeSerializer<Element, AugmentationNode, AugmentationSchema> getAugmentationNodeSerializer() {
+               return augmentSerializer;
+       }
+
+       @Override
+       public FromNormalizedNodeSerializer<Element, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeSerializer() {
+               return choiceSerializer;
+       }
+
+       @Override
+       public FromNormalizedNodeSerializer<Element, ContainerNode, ContainerSchemaNode> getContainerNodeSerializer() {
+               return containerSerializer;
+       }
+
+       @Override
+       public FromNormalizedNodeSerializer<Element, LeafNode<?>, LeafSchemaNode> getLeafNodeSerializer() {
+               return leafNodeSerializer;
+       }
+
+       @Override
+       public FromNormalizedNodeSerializer<Element, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer() {
+               return leafSetEntryNodeSerializer;
+       }
+
+       @Override
+       public FromNormalizedNodeSerializer<Element, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeSerializer() {
+               return leafSetSerializer;
+       }
+
+       @Override
+       public FromNormalizedNodeSerializer<Element, MapEntryNode, ListSchemaNode> getMapEntryNodeSerializer() {
+               return mapEntryNodeSerializer;
+       }
+
+       @Override
+       public FromNormalizedNodeSerializer<Element, MapNode, ListSchemaNode> getMapNodeSerializer() {
+               return mapNodeSerializer;
+       }
+
+}
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 (file)
index 0000000..83fcb8d
--- /dev/null
@@ -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 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.base.serializer.LeafNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+final class LeafNodeDomSerializer extends LeafNodeBaseSerializer<Element> {
+    private final XmlCodecProvider codecProvider;
+    private final Document doc;
+
+    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 (file)
index 0000000..fcc04c2
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.codec.xml.XmlCodecProvider;
+import org.opendaylight.yangtools.yang.data.impl.codec.xml.XmlDocumentUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetEntryNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import com.google.common.base.Preconditions;
+
+final class LeafSetEntryNodeDomSerializer extends
+        LeafSetEntryNodeBaseSerializer<Element> {
+
+    private final Document doc;
+    private final XmlCodecProvider codecProvider;
+
+    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 (file)
index 0000000..63af569
--- /dev/null
@@ -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.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;
+
+final class LeafSetNodeDomSerializer extends LeafSetNodeBaseSerializer<Element> {
+    private final FromNormalizedNodeSerializer<Element, LeafSetEntryNode<?>, LeafListSchemaNode> leafSetEntryNodeSerializer;
+
+    LeafSetNodeDomSerializer(LeafSetEntryNodeDomSerializer leafSetEntryNodeSerializer) {
+        this.leafSetEntryNodeSerializer = leafSetEntryNodeSerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, LeafSetEntryNode<?>, 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 (file)
index 0000000..dbe8a90
--- /dev/null
@@ -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.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;
+
+final class MapEntryNodeDomSerializer extends MapEntryNodeBaseSerializer<Element> {
+    private final NodeSerializerDispatcher<Element> dispatcher;
+    private final Document doc;
+
+    MapEntryNodeDomSerializer(final Document doc, final NodeSerializerDispatcher<Element> dispatcher) {
+        this.doc = Preconditions.checkNotNull(doc);
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    public Iterable<Element> 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<Element> 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 (file)
index 0000000..5404f19
--- /dev/null
@@ -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;
+
+final class MapNodeDomSerializer extends MapNodeBaseSerializer<Element> {
+
+    private final FromNormalizedNodeSerializer<Element, MapEntryNode, ListSchemaNode> mapEntrySerializer;
+
+    MapNodeDomSerializer(MapEntryNodeDomSerializer mapEntrySerializer) {
+        this.mapEntrySerializer = mapEntrySerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Element, MapEntryNode, ListSchemaNode> getMapEntryNodeDomSerializer() {
+        return mapEntrySerializer;
+    }
+}
index 60b93cef801fa2333ac5d02f7ce684e1295b94fb..5cea3b84ddb26a93c274f47959853fdc4f20f9e5 100644 (file)
@@ -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<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs());
+        Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs(yangPath));
         return yangParserImpl.resolveSchemaContext(modules);
     }
 
-    List<InputStream> getTestYangs() {
+    List<InputStream> getTestYangs(String... yangPaths) {
 
-        return Lists.newArrayList(Collections2.transform(Lists.newArrayList("test.yang"),
+        return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths),
                 new Function<String, InputStream>() {
                     @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<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders.containerBuilder().withNodeIdentifier(
-                getNodeIdentifier("container"));
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders
+                .containerBuilder().withNodeIdentifier(getNodeIdentifier("container"));
 
         // leaf
-        LeafNode<String> leafChild = Builders.<String>leafBuilder()
-                .withNodeIdentifier(getNodeIdentifier("leaf")).withValue("String").build();
+        LeafNode<String> leafChild = Builders.<String> leafBuilder().withNodeIdentifier(getNodeIdentifier("leaf"))
+                .withValue("String").build();
         builder.withChild(leafChild);
 
         // leafList
-        LeafSetNode<Integer> leafList = Builders.<Integer>leafSetBuilder()
+        LeafSetNode<Integer> leafList = Builders
+                .<Integer> leafSetBuilder()
                 .withNodeIdentifier(getNodeIdentifier("leaf"))
                 .withChildValue(1)
-                .withChild(Builders.<Integer>leafSetEntryBuilder().withNodeIdentifier(getNodeWithValueIdentifier("leaf", 3)).withValue(3).build())
+                .withChild(
+                        Builders.<Integer> leafSetEntryBuilder()
+                                .withNodeIdentifier(getNodeWithValueIdentifier("leaf", 3)).withValue(3).build())
                 .build();
         builder.withChild(leafList);
 
         // list
-        MapEntryNode listChild1 = Builders.mapEntryBuilder()
-                .withChild(
-                        Builders.<Integer>leafBuilder()
-                                .withNodeIdentifier(getNodeIdentifier("uint32InList")).withValue(1).build())
+        MapEntryNode listChild1 = Builders
+                .mapEntryBuilder()
                 .withChild(
-                        Builders.containerBuilder().withNodeIdentifier(
-                                getNodeIdentifier("containerInList"))
-                                .build())
+                        Builders.<Integer> 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.<Integer>leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32")).withValue(11).build())
-                .build();
+                        Builders.<Integer> 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.<Integer>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.<Integer> leafBuilder().withNodeIdentifier(getNodeIdentifier("augmentUint32"))
+                .withValue(11).build());
     }
 
     @Test
     public void testSchemaAware() throws Exception {
-        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder =  Builders.containerBuilder(containerNode);
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> builder = Builders
+                .containerBuilder(containerNode);
 
         LeafSchemaNode schemaNode = (LeafSchemaNode) getSchemaNode(schema, "test", "uint32");
-        LeafNode<String> leafChild = Builders.<String>leafBuilder(schemaNode)
-                .withValue("String").build();
+        LeafNode<String> leafChild = Builders.<String> leafBuilder(schemaNode).withValue("String").build();
         builder.withChild(leafChild);
 
         LeafListSchemaNode leafListSchemaNode = (LeafListSchemaNode) getSchemaNode(schema, "test", "leafList");
-        LeafSetNode<Integer> leafList = Builders.<Integer>leafSetBuilder(leafListSchemaNode)
-                .withChildValue(1)
-                .withChild(Builders.<Integer>leafSetEntryBuilder(leafListSchemaNode).withValue(3).build())
-                .build();
+        LeafSetNode<Integer> leafList = Builders.<Integer> leafSetBuilder(leafListSchemaNode).withChildValue(1)
+                .withChild(Builders.<Integer> 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.<Integer>leafBuilder(uint32InListSchemaNode).withValue(1).build())
-                .withChild(
-                        Builders.containerBuilder(containerInListSchemaNode).build())
-                .build();
+                .withChild(Builders.<Integer> 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.<Integer>leafBuilder(augmentUint32SchemaNode).withValue(11).build())
-                .build();
+        AugmentationNode augmentation = Builders.augmentationBuilder(augmentationSchema)
+                .withChild(Builders.<Integer>leafBuilder(augmentUint32SchemaNode).withValue(11).build()).build();
 
         builder.withChild(augmentation);
 
         // This should fail with schema, since the leaf comes from augmentation
-//        builder.withChild(ImmutableLeafNodeSchemaAwareBuilder.<Integer>get(augmentUint32SchemaNode).withValue(11).build());
+        // builder.withChild(ImmutableLeafNodeSchemaAwareBuilder.<Integer>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.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
-                        .build())
-                        // This should fail, since child node belongs to different case
-//                .withChild(Builders.<String>leafBuilder(augumentString2SchemaNode).withValue("case2")
-//                        .build())
+        org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode choice = ImmutableChoiceNodeSchemaAwareBuilder
+                .create(choice1SchemaNode)
+                .withChild(Builders.<String> leafBuilder(augumentString1SchemaNode).withValue("case1").build())
+                // This should fail, since child node belongs to different case
+                // .withChild(Builders.<String>leafBuilder(augumentString2SchemaNode).withValue("case2")
+                // .build())
                 .build();
 
-;        builder.withChild(choice);
+        ;
+        builder.withChild(choice);
 
         // This should fail, child from case
-//        builder.withChild(Builders.<String>leafBuilder(augumentString1SchemaNode).withValue("case1")
-//                .build());
-
-        System.out.println(builder.build());
+        // builder.withChild(Builders.<String>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<DataSchemaNode> children, String name) {
+    static DataSchemaNode findChildNode(Set<DataSchemaNode> children, String name) {
         List<DataNodeContainer> 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/test/NormalizedNodeUtilsTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/test/NormalizedNodeUtilsTest.java
new file mode 100644 (file)
index 0000000..36d6067
--- /dev/null
@@ -0,0 +1,119 @@
+package org.opendaylight.yangtools.yang.data.impl.schema.test;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntry;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapEntryBuilder;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.mapNodeBuilder;
+
+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.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+
+import com.google.common.base.Optional;
+
+/**
+ *
+ * Schema structure of document is
+ *
+ * <pre>
+ * container root { 
+ *      list list-a {
+ *              key leaf-a;
+ *              leaf leaf-a;
+ *              choice choice-a {
+ *                      case one {
+ *                              leaf one;
+ *                      }
+ *                      case two-three {
+ *                              leaf two;
+ *                              leaf three;
+ *                      }
+ *              }
+ *              list list-b {
+ *                      key leaf-b;
+ *                      leaf leaf-b;
+ *              }
+ *      }
+ * }
+ * </pre>
+ *
+ */
+public class NormalizedNodeUtilsTest {
+
+    private static final QName ROOT_QNAME = QName.create("urn:opendalight:controller:sal:dom:store:test", "2014-03-13",
+            "root");
+    private static final QName LIST_A_QNAME = QName.create(ROOT_QNAME, "list-a");
+    private static final QName LIST_B_QNAME = QName.create(ROOT_QNAME, "list-b");
+    private static final QName CHOICE_A_QNAME = QName.create(ROOT_QNAME, "choice-a");
+    private static final QName LEAF_A_QNAME = QName.create(ROOT_QNAME, "leaf-a");
+    private static final QName LEAF_B_QNAME = QName.create(ROOT_QNAME, "leaf-b");
+    private static final String FOO = "foo";
+    private static final String BAR = "bar";
+    private static final String ONE = "one";
+    private static final String TWO = "two";
+
+    private static final InstanceIdentifier LIST_A_FOO_PATH = InstanceIdentifier.builder()
+                //.node(ROOT_QNAME)
+                .node(LIST_A_QNAME)
+                .nodeWithKey(LIST_A_QNAME, LEAF_A_QNAME, FOO)
+                .build();
+    private static final InstanceIdentifier LIST_B_TWO_PATH = InstanceIdentifier.builder()
+                //.node(ROOT_QNAME)
+                .node(LIST_A_QNAME)
+                .nodeWithKey(LIST_A_QNAME, LEAF_A_QNAME, BAR)
+                .node(LIST_B_QNAME)
+                .nodeWithKey(LIST_B_QNAME,LEAF_B_QNAME,TWO)
+                .build();
+
+    /**
+     * Returns a test document
+     *
+     * <pre>
+     * root
+     *     list-a
+     *          leaf-a "foo"
+     *     list-a
+     *          leaf-a "bar"
+     *          list-b
+     *                  leaf-b "one"
+     *          list-b
+     *                  leaf-b "two"
+     *
+     * </pre>
+     *
+     * @return
+     */
+    public NormalizedNode<?, ?> createDocumentOne() {
+        return ImmutableContainerNodeBuilder
+                .create()
+                .withNodeIdentifier(new NodeIdentifier(ROOT_QNAME))
+                .withChild(
+                        mapNodeBuilder(LIST_A_QNAME)
+                                .withChild(mapEntry(LIST_A_QNAME, LEAF_A_QNAME, FOO))
+                                .withChild(
+                                        mapEntryBuilder(LIST_A_QNAME, LEAF_A_QNAME, BAR).withChild(
+                                                mapNodeBuilder(LIST_B_QNAME)
+                                                        .withChild(mapEntry(LIST_B_QNAME, LEAF_B_QNAME, ONE))
+                                                        .withChild(mapEntry(LIST_B_QNAME, LEAF_B_QNAME, TWO)).build())
+                                                .build()).build()).build();
+
+    }
+
+    @Test
+    public void findNodeTest() {
+        NormalizedNode<?, ?> tree = createDocumentOne();
+        assertNotNull(tree);
+
+        Optional<NormalizedNode<?, ?>> listFooResult = NormalizedNodeUtils.findNode(tree, LIST_A_FOO_PATH);
+        assertTrue(listFooResult.isPresent());
+
+        Optional<NormalizedNode<?, ?>> listTwoResult = NormalizedNodeUtils.findNode(tree, LIST_B_TWO_PATH);
+        assertTrue(listTwoResult.isPresent());
+    }
+
+}
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 (file)
index 0000000..8bfa0ff
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * 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.Map;
+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.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLAssert;
+import org.custommonkey.xmlunit.XMLUnit;
+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.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+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.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.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+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.Maps;
+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<Object[]> 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},
+                // TODO check attributes
+                {"test.yang", "simple_xml_with_attributes.xml", withAttributes()}
+        });
+    }
+
+
+    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 withAttributes() {
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> b = Builders.containerBuilder();
+        b.withNodeIdentifier(getNodeIdentifier("container"));
+
+        CollectionNodeBuilder<MapEntryNode, MapNode> listBuilder = Builders.mapBuilder().withNodeIdentifier(
+                getNodeIdentifier("list"));
+
+        Map<QName, Object> predicates = Maps.newHashMap();
+        predicates.put(getNodeIdentifier("uint32InList").getNodeType(), 3L);
+
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> list1Builder = Builders
+                .mapEntryBuilder().withNodeIdentifier(
+                        new InstanceIdentifier.NodeIdentifierWithPredicates(getNodeIdentifier("list").getNodeType(),
+                                predicates));
+        NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier,Object,LeafNode<Object>> uint32InListBuilder
+                = Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("uint32InList"));
+
+        list1Builder.withChild(uint32InListBuilder.withValue(3L).build());
+
+        listBuilder.withChild(list1Builder.build());
+        b.withChild(listBuilder.build());
+
+        NormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, Object, LeafNode<Object>> booleanBuilder
+                = Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("boolean"));
+        booleanBuilder.withValue(false);
+        b.withChild(booleanBuilder.build());
+
+        ListNodeBuilder<Object, LeafSetEntryNode<Object>> leafListBuilder
+                = Builders.leafSetBuilder().withNodeIdentifier(getNodeIdentifier("leafList"));
+
+        NormalizedNodeBuilder<InstanceIdentifier.NodeWithValue, Object, LeafSetEntryNode<Object>> leafList1Builder
+                = Builders.leafSetEntryBuilder().withNodeIdentifier(new InstanceIdentifier.NodeWithValue(getNodeIdentifier("leafList").getNodeType(), "a"));
+
+        leafList1Builder.withValue("a");
+
+        leafListBuilder.withChild(leafList1Builder.build());
+        b.withChild(leafListBuilder.build());
+
+        return b.build();
+    }
+
+    private static ContainerNode augmentChoiceHell() {
+
+        DataContainerNodeBuilder<InstanceIdentifier.NodeIdentifier, ContainerNode> 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<QName> 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) {
+        SchemaContext 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 String xmlPath;
+
+
+    SchemaContext parseTestSchema(String... yangPath) {
+        YangParserImpl yangParserImpl = new YangParserImpl();
+        Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs(yangPath));
+        return yangParserImpl.resolveSchemaContext(modules);
+    }
+
+    List<InputStream> getTestYangs(String... yangPaths) {
+
+        return Lists.newArrayList(Collections2.transform(Lists.newArrayList(yangPaths),
+                new Function<String, InputStream>() {
+                    @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 =
+                DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider()).getContainerNodeParser().parse(
+                Collections.singletonList(doc.getDocumentElement()), containerNode);
+
+        if (expectedNode != null)
+            junit.framework.Assert.assertEquals(expectedNode, built);
+
+        logger.info("{}", built);
+
+        Iterable<Element> els = DomFromNormalizedNodeSerializerFactory.getInstance(XmlDocumentUtils.getDocument(), DomUtils.defaultValueCodecProvider())
+                .getContainerNodeSerializer().serialize(containerNode, built);
+
+        Element el = els.iterator().next();
+
+        XMLUnit.setIgnoreWhitespace(true);
+        XMLUnit.setIgnoreComments(true);
+
+        System.err.println(toString(doc.getDocumentElement()));
+        System.err.println(toString(el));
+
+        boolean diff = new Diff(XMLUnit.buildControlDocument(toString(doc.getDocumentElement())), XMLUnit.buildTestDocument(toString(el))).similar();
+    }
+
+    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 (file)
index 0000000..c2a57f6
--- /dev/null
@@ -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 (file)
index 0000000..c5a581c
--- /dev/null
@@ -0,0 +1,15 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+    <c2Leaf>2</c2Leaf>
+    <c2DeepChoiceCase1Leaf2>2</c2DeepChoiceCase1Leaf2>
+    <!--<c2DeepChoiceCase1Leaf1>2</c2DeepChoiceCase1Leaf1>-->
+
+    <c3Leaf>3</c3Leaf>
+
+    <augLeaf>augment</augLeaf>
+
+    <c1Leaf>1</c1Leaf>
+    <c1Leaf_AnotherAugment>1</c1Leaf_AnotherAugment>
+    <deepLeafc1>1</deepLeafc1>
+    <!--<deepLeafc2>1</deepLeafc2>-->
+</container>
\ 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 (file)
index 0000000..8332d21
--- /dev/null
@@ -0,0 +1,12 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+    <c22Leaf>2</c22Leaf>
+
+    <c34LeafS>3</c34LeafS>
+
+    <augLeaf>augment</augLeaf>
+
+    <c1Leaf>1</c1Leaf>
+    <c1Leaf_AnotherAugment>1</c1Leaf_AnotherAugment>
+    <deepLeafc2>1</deepLeafc2>
+</container>
\ No newline at end of file
index 014688e567ac51a4d428c41230b842d51ed9fa48..b36531b2ff9a80293d125eb394497e4bb9755af3 100644 (file)
@@ -8,10 +8,12 @@
 
     <list>
         <uint32InList>1</uint32InList>
-        <containerInList>
+        <containerInList name="inContainer">
             <uint32>32</uint32>
             <uint16>16</uint16>
         </containerInList>
+        <stringAugmentedToList>augmentInList</stringAugmentedToList>
+        <stringAugmentedToListInCase1>augmentInListCase1</stringAugmentedToListInCase1>
     </list>
     <list>
         <uint32InList>2</uint32InList>
             <uint32>32</uint32>
             <uint16>16</uint16>
         </containerInList>
+        <!--<stringAugmentedToListInCase1>augmentInListCase1</stringAugmentedToListInCase1>-->
+        <stringAugmentedToListInCase2>augmentInListCase2</stringAugmentedToListInCase2>
     </list>
     <list>
         <uint32InList>3</uint32InList>
     </list>
 
-    <augmentUint32>999</augmentUint32>
-
     <augmentString1>choice1Case1</augmentString1>
+    <!--<augmentString2>choice1Case1</augmentString2>-->
     <augmentInt1>41</augmentInt1>
+    <!--<stringInAugmentedCaseInAugmentedChoice>deep</stringInAugmentedCaseInAugmentedChoice>-->
+    <stringInAugmentedCaseInAugmentedChoiceFromAugment>deep</stringInAugmentedCaseInAugmentedChoiceFromAugment>
 
     <augmentContainer>
         <augmentStringInaugmentContainer>choice2Case1</augmentStringInaugmentContainer>
     </augmentContainer>
 
+    <augmentUint32>999</augmentUint32>
+
+
 
 </container>
\ 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 (file)
index 0000000..9bb8aff
--- /dev/null
@@ -0,0 +1,43 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <augmentString1>choice1Case1</augmentString1>
+    <!--<augmentString2>choice1Case1</augmentString2>-->
+    <augmentInt1>41</augmentInt1>
+    <!--<stringInAugmentedCaseInAugmentedChoice>deep</stringInAugmentedCaseInAugmentedChoice>-->
+    <stringInAugmentedCaseInAugmentedChoice2>deep</stringInAugmentedCaseInAugmentedChoice2>
+
+    <augmentedList>
+        <augmentStringInaugmentList>aug1</augmentStringInaugmentList>
+    </augmentedList>
+
+    <augmentedList>
+        <augmentStringInaugmentList>aug2</augmentStringInaugmentList>
+        <augmentedContainerInAugmentedListInAugmentedCase>
+            <leafInAugmentedContainerInAugmentedListInAugmentedCase>
+                66
+            </leafInAugmentedContainerInAugmentedListInAugmentedCase>
+        </augmentedContainerInAugmentedListInAugmentedCase>
+
+        <augmentedListInAugmentedListInAugmentedCase>
+            <leafInAugmentedListInAugmentedListInAugmentedCase>
+                661
+            </leafInAugmentedListInAugmentedListInAugmentedCase>
+            <leafInAugmentedListInAugmentedListInAugmentedCase>
+                662
+            </leafInAugmentedListInAugmentedListInAugmentedCase>
+        </augmentedListInAugmentedListInAugmentedCase>
+
+        <augmentedListInAugmentedListInAugmentedCase>
+            <leafInAugmentedListInAugmentedListInAugmentedCase>
+                6621
+            </leafInAugmentedListInAugmentedListInAugmentedCase>
+        </augmentedListInAugmentedListInAugmentedCase>
+    </augmentedList>
+
+    <augmentedList>
+        <augmentStringInaugmentList>aug3</augmentStringInaugmentList>
+        <augmentedContainerInAugmentedListInAugmentedCase/>
+
+        <augmentedListInAugmentedListInAugmentedCase/>
+    </augmentedList>
+
+</container>
\ 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_with_attributes.xml b/yang/yang-data-impl/src/test/resources/org/opendaylight/yangtools/yang/data/impl/schema/simple_xml_with_attributes.xml
new file mode 100644 (file)
index 0000000..740bed8
--- /dev/null
@@ -0,0 +1,11 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test" name="test" xmlns:foo="http://www.foo.com/" foo:baz="baz">
+
+    <list list="on list entry">
+        <uint32InList name="test" foo:baz="baz">3</uint32InList>
+    </list>
+
+    <boolean xmlns:leaf="test:namespace:in:leaf" leaf:a="b">false</boolean>
+
+    <leafList foo:b="b">a</leafList>
+
+</container>
\ No newline at end of file
index 4ad6e786259c47e91d38fc490ef6c767dfcf4634..5f0e5000d13dc205aaf24b3fe1267128f5c5dd2c 100644 (file)
@@ -6,7 +6,7 @@ module test {
 
     organization "Cisco Systems, Inc.";
 
-    revision "2013-2-21" {
+    revision "2014-3-13" {
         description
             "Initial revision";
     }
@@ -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;
diff --git a/yang/yang-data-json/pom.xml b/yang/yang-data-json/pom.xml
new file mode 100644 (file)
index 0000000..9327cf8
--- /dev/null
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- 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 -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+       <parent>
+               <groupId>org.opendaylight.yangtools</groupId>
+               <artifactId>yang</artifactId>
+               <version>0.6.2-SNAPSHOT</version>
+       </parent>
+
+       <modelVersion>4.0.0</modelVersion>
+       <artifactId>yang-data-json</artifactId>
+       <name>${project.artifactId}</name>
+       <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-data-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-data-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+        <dependency>
+          <groupId>junit</groupId>
+          <artifactId>junit</artifactId>
+          <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/AugmentationNodeCnSnParser.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/AugmentationNodeCnSnParser.java
new file mode 100644 (file)
index 0000000..60add98
--- /dev/null
@@ -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.json.schema.cnsn.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+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.json.schema.json.CnSnToNormalizedNodesUtils;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class AugmentationNodeCnSnParser extends AugmentationNodeBaseParser<Node<?>> {
+
+    private final NodeParserDispatcher<Node<?>> dispatcher;
+
+    public AugmentationNodeCnSnParser(final NodeParserDispatcher<Node<?>> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Node<?>> mapChildElements(Iterable<Node<?>> elements) {
+        return CnSnToNormalizedNodesUtils.mapChildElements(elements);
+    }
+
+    @Override
+    protected NodeParserDispatcher<Node<?>> getDispatcher() {
+        return dispatcher;
+    }
+
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/ChoiceNodeCnSnParser.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/ChoiceNodeCnSnParser.java
new file mode 100644 (file)
index 0000000..6ab6559
--- /dev/null
@@ -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.json.schema.cnsn.parser;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+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.json.schema.json.CnSnToNormalizedNodesUtils;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class ChoiceNodeCnSnParser extends ChoiceNodeBaseParser<Node<?>> {
+
+    private final NodeParserDispatcher<Node<?>> dispatcher;
+
+    public ChoiceNodeCnSnParser(final NodeParserDispatcher<Node<?>> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Node<?>> mapChildElements(Iterable<Node<?>> elements) {
+        return CnSnToNormalizedNodesUtils.mapChildElements(elements);
+    }
+
+    @Override
+    protected NodeParserDispatcher<Node<?>> getDispatcher() {
+        return dispatcher;
+    }
+
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/CnSnToNormalizedNodeParserFactory.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/CnSnToNormalizedNodeParserFactory.java
new file mode 100644 (file)
index 0000000..2cddf7d
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.json.schema.cnsn.parser;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+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.LeafSetEntryNode;
+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.transform.ToNormalizedNodeParser;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.ToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.NodeParserDispatcher;
+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;
+
+public class CnSnToNormalizedNodeParserFactory implements ToNormalizedNodeParserFactory<Node<?>> {
+
+    private final ContainerNodeCnSnParser containerNodeCnSnParser;
+    private final LeafNodeCnSnParser leafNodeCnSnParser;
+    private final LeafSetEntryNodeCnSnParser leafSetEntryNodeCnSnParser;
+    private final LeafSetNodeCnSnParser leafSetNodeCnSnParser;
+    private final MapNodeCnSnParser mapNodeCnSnParser;
+    private final MapEntryNodeCnSnParser mapEntryNodeCnSnParser;
+    private final ChoiceNodeCnSnParser choiceNodeCnSnParser;
+    private final AugmentationNodeCnSnParser augmentationNodeCnSnParser;
+
+    private CnSnToNormalizedNodeParserFactory() {
+        leafNodeCnSnParser = new LeafNodeCnSnParser();
+        leafSetEntryNodeCnSnParser = new LeafSetEntryNodeCnSnParser();
+        leafSetNodeCnSnParser = new LeafSetNodeCnSnParser(leafSetEntryNodeCnSnParser);
+
+        final NodeParserDispatcher<Node<?>> dispatcher = new NodeParserDispatcher.BaseNodeParserDispatcher<Node<?>>(
+                this) {
+
+        };
+
+        containerNodeCnSnParser = new ContainerNodeCnSnParser(dispatcher);
+        mapEntryNodeCnSnParser = new MapEntryNodeCnSnParser(dispatcher);
+        mapNodeCnSnParser = new MapNodeCnSnParser(mapEntryNodeCnSnParser);
+        choiceNodeCnSnParser = new ChoiceNodeCnSnParser(dispatcher);
+        augmentationNodeCnSnParser = new AugmentationNodeCnSnParser(dispatcher);
+    }
+
+    public static CnSnToNormalizedNodeParserFactory getInstance() {
+        return new CnSnToNormalizedNodeParserFactory();
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Node<?>, ContainerNode, ContainerSchemaNode> getContainerNodeParser() {
+        return containerNodeCnSnParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Node<?>, LeafNode<?>, LeafSchemaNode> getLeafNodeParser() {
+        return leafNodeCnSnParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Node<?>, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeParser() {
+        return leafSetNodeCnSnParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Node<?>, MapNode, ListSchemaNode> getMapNodeParser() {
+        return mapNodeCnSnParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Node<?>, org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode, ChoiceNode> getChoiceNodeParser() {
+        return choiceNodeCnSnParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Node<?>, AugmentationNode, AugmentationSchema> getAugmentationNodeParser() {
+        return augmentationNodeCnSnParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Node<?>, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeParser() {
+        return leafSetEntryNodeCnSnParser;
+    }
+
+    @Override
+    public ToNormalizedNodeParser<Node<?>, MapEntryNode, ListSchemaNode> getMapEntryNodeParser() {
+        return mapEntryNodeCnSnParser;
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/ContainerNodeCnSnParser.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/ContainerNodeCnSnParser.java
new file mode 100644 (file)
index 0000000..afd3a13
--- /dev/null
@@ -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.json.schema.cnsn.parser;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+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.json.schema.json.CnSnToNormalizedNodesUtils;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class ContainerNodeCnSnParser extends ContainerNodeBaseParser<Node<?>> {
+
+    private final NodeParserDispatcher<Node<?>> dispatcher;
+
+    public ContainerNodeCnSnParser(final NodeParserDispatcher<Node<?>> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected NodeParserDispatcher<Node<?>> getDispatcher() {
+        return dispatcher;
+    }
+
+    @Override
+    protected LinkedListMultimap<QName, Node<?>> mapChildElements(Iterable<Node<?>> elements) {
+        return CnSnToNormalizedNodesUtils.mapChildElementsForSingletonNode(elements.iterator().next());
+    }
+
+    @Override
+    protected Map<QName, String> getAttributes(Node<?> e) {
+        return Collections.emptyMap();
+    }
+
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/LeafNodeCnSnParser.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/LeafNodeCnSnParser.java
new file mode 100644 (file)
index 0000000..7a601ee
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.json.schema.cnsn.parser;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafNodeBaseParser;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+public class LeafNodeCnSnParser extends LeafNodeBaseParser<Node<?>> {
+
+    public LeafNodeCnSnParser() {
+        super();
+    }
+
+    @Override
+    protected Object parseLeaf(Node<?> elements, LeafSchemaNode schema) {
+        return elements.getValue();
+    }
+
+    @Override
+    protected Map<QName, String> getAttributes(Node<?> e) {
+        return Collections.emptyMap();
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/LeafSetEntryNodeCnSnParser.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/LeafSetEntryNodeCnSnParser.java
new file mode 100644 (file)
index 0000000..bd3a3df
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.json.schema.cnsn.parser;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.parser.LeafSetEntryNodeBaseParser;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+public class LeafSetEntryNodeCnSnParser extends LeafSetEntryNodeBaseParser<Node<?>> {
+
+    public LeafSetEntryNodeCnSnParser() {
+        super();
+    }
+
+    @Override
+    protected Object parseLeafListEntry(Node<?> elements, LeafListSchemaNode schema) {
+        return elements.getValue();
+    }
+
+    @Override
+    protected Map<QName, String> getAttributes(Node<?> e) {
+        return Collections.emptyMap();
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/LeafSetNodeCnSnParser.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/LeafSetNodeCnSnParser.java
new file mode 100644 (file)
index 0000000..1b8f96c
--- /dev/null
@@ -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.json.schema.cnsn.parser;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+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;
+
+public class LeafSetNodeCnSnParser extends LeafSetNodeBaseParser<Node<?>> {
+
+    private final LeafSetEntryNodeCnSnParser leafSetEntryNodeCnSnParser;
+
+    public LeafSetNodeCnSnParser(LeafSetEntryNodeCnSnParser leafSetEntryNodeCnSnParser) {
+        this.leafSetEntryNodeCnSnParser = leafSetEntryNodeCnSnParser;
+    }
+
+    @Override
+    protected ToNormalizedNodeParser<Node<?>, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeParser() {
+        return leafSetEntryNodeCnSnParser;
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/MapEntryNodeCnSnParser.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/MapEntryNodeCnSnParser.java
new file mode 100644 (file)
index 0000000..ec3736f
--- /dev/null
@@ -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.json.schema.cnsn.parser;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+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.json.schema.json.CnSnToNormalizedNodesUtils;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.LinkedListMultimap;
+
+public final class MapEntryNodeCnSnParser extends MapEntryNodeBaseParser<Node<?>> {
+
+    private final NodeParserDispatcher<Node<?>> dispatcher;
+
+    public MapEntryNodeCnSnParser(final NodeParserDispatcher<Node<?>> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+
+    @Override
+    protected LinkedListMultimap<QName, Node<?>> mapChildElements(Iterable<Node<?>> elements) {
+        return CnSnToNormalizedNodesUtils.mapChildElementsForSingletonNode(elements.iterator().next());
+    }
+
+    @Override
+    protected NodeParserDispatcher<Node<?>> getDispatcher() {
+        return dispatcher;
+    }
+
+    @Override
+    protected Map<QName, String> getAttributes(Node<?> e) {
+        return Collections.emptyMap();
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/MapNodeCnSnParser.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/MapNodeCnSnParser.java
new file mode 100644 (file)
index 0000000..92fb1f3
--- /dev/null
@@ -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.json.schema.cnsn.parser;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+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;
+
+public final class MapNodeCnSnParser extends MapNodeBaseParser<Node<?>> {
+
+    private final MapEntryNodeCnSnParser mapEntryNodeCnSnParser;
+
+    public MapNodeCnSnParser(MapEntryNodeCnSnParser mapEntryNodeCnSnParser) {
+        this.mapEntryNodeCnSnParser = mapEntryNodeCnSnParser;
+    }
+
+    @Override
+    protected ToNormalizedNodeParser<Node<?>, MapEntryNode, ListSchemaNode> getMapEntryNodeParser() {
+        return mapEntryNodeCnSnParser;
+    }
+
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/AugmentationNodeCnSnSerializer.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/AugmentationNodeCnSnSerializer.java
new file mode 100644 (file)
index 0000000..c71672b
--- /dev/null
@@ -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.json.schema.cnsn.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+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 com.google.common.base.Preconditions;
+
+public class AugmentationNodeCnSnSerializer extends AugmentationNodeBaseSerializer<Node<?>> {
+
+    private NodeSerializerDispatcher<Node<?>> dispatcher;
+
+    AugmentationNodeCnSnSerializer(final NodeSerializerDispatcher<Node<?>> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Node<?>> getNodeDispatcher() {
+        return dispatcher;
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/ChoiceNodeCnSnSerializer.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/ChoiceNodeCnSnSerializer.java
new file mode 100644 (file)
index 0000000..1542da7
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.json.schema.cnsn.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+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 com.google.common.base.Preconditions;
+
+public class ChoiceNodeCnSnSerializer
+        extends
+        ChoiceNodeBaseSerializer<Node<?>> {
+
+    private final NodeSerializerDispatcher<Node<?>> dispatcher;
+
+    ChoiceNodeCnSnSerializer(final NodeSerializerDispatcher<Node<?>> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Node<?>> getNodeDispatcher() {
+        return dispatcher;
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/CnSnFromNormalizedNodeSerializerFactory.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/CnSnFromNormalizedNodeSerializerFactory.java
new file mode 100644 (file)
index 0000000..2f771e6
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * 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.json.schema.cnsn.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+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.LeafSetEntryNode;
+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.transform.FromNormalizedNodeSerializer;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.FromNormalizedNodeSerializerFactory;
+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;
+
+public final class CnSnFromNormalizedNodeSerializerFactory implements FromNormalizedNodeSerializerFactory<Node<?>> {
+    private final ContainerNodeCnSnSerializer containerSerializer;
+    private final ChoiceNodeCnSnSerializer choiceSerializer;
+    private final AugmentationNodeCnSnSerializer augmentSerializer;
+    private final LeafNodeCnSnSerializer leafNodeSerializer;
+    private final LeafSetNodeCnSnSerializer leafSetSerializer;
+    private final MapNodeCnSnSerializer mapNodeSerializer;
+    private final LeafSetEntryNodeCnSnSerializer leafSetEntryNodeSerializer;
+    private final MapEntryNodeCnSnSerializer mapEntryNodeSerializer;
+
+    private CnSnFromNormalizedNodeSerializerFactory() {
+        final NodeSerializerDispatcher.BaseNodeSerializerDispatcher<Node<?>> dispatcher = new NodeSerializerDispatcher.BaseNodeSerializerDispatcher<Node<?>>(
+                this) {
+
+        };
+
+        containerSerializer = new ContainerNodeCnSnSerializer(dispatcher);
+        choiceSerializer = new ChoiceNodeCnSnSerializer(dispatcher);
+        augmentSerializer = new AugmentationNodeCnSnSerializer(dispatcher);
+        leafNodeSerializer = new LeafNodeCnSnSerializer();
+
+        leafSetEntryNodeSerializer = new LeafSetEntryNodeCnSnSerializer();
+        leafSetSerializer = new LeafSetNodeCnSnSerializer(leafSetEntryNodeSerializer);
+
+        mapEntryNodeSerializer = new MapEntryNodeCnSnSerializer(dispatcher);
+        mapNodeSerializer = new MapNodeCnSnSerializer(mapEntryNodeSerializer);
+    }
+
+
+    public static CnSnFromNormalizedNodeSerializerFactory getInstance() {
+        return new CnSnFromNormalizedNodeSerializerFactory();
+}
+
+    @Override
+    public FromNormalizedNodeSerializer<Node<?>, ContainerNode, ContainerSchemaNode> getContainerNodeSerializer() {
+        return containerSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<Node<?>, LeafNode<?>, LeafSchemaNode> getLeafNodeSerializer() {
+        return leafNodeSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<Node<?>, LeafSetNode<?>, LeafListSchemaNode> getLeafSetNodeSerializer() {
+        return leafSetSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<Node<?>, MapNode, ListSchemaNode> getMapNodeSerializer() {
+        return mapNodeSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<Node<?>, ChoiceNode, org.opendaylight.yangtools.yang.model.api.ChoiceNode> getChoiceNodeSerializer() {
+        return choiceSerializer;
+    }
+
+    @Override
+    public FromNormalizedNodeSerializer<Node<?>, AugmentationNode, AugmentationSchema> getAugmentationNodeSerializer() {
+        return augmentSerializer;
+    }
+
+
+    @Override
+    public FromNormalizedNodeSerializer<Node<?>, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer() {
+        return leafSetEntryNodeSerializer;
+    }
+
+
+    @Override
+    public FromNormalizedNodeSerializer<Node<?>, MapEntryNode, ListSchemaNode> getMapEntryNodeSerializer() {
+        return mapEntryNodeSerializer;
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/ContainerNodeCnSnSerializer.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/ContainerNodeCnSnSerializer.java
new file mode 100644 (file)
index 0000000..03dde16
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.json.schema.cnsn.serializer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.MutableNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+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 com.google.common.base.Preconditions;
+
+public class ContainerNodeCnSnSerializer extends ContainerNodeBaseSerializer<Node<?>> {
+
+    private NodeSerializerDispatcher<Node<?>> dispatcher;
+
+    ContainerNodeCnSnSerializer(final NodeSerializerDispatcher<Node<?>> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);;
+    }
+
+    @Override
+    public List<Node<?>> serialize(ContainerSchemaNode schema, ContainerNode containerNode) {
+
+        MutableCompositeNode mutCompNode = NodeFactory.createMutableCompositeNode(containerNode.getNodeType(), null,
+                null, null, null);
+
+        for (Node<?> element : super.serialize(schema, containerNode)) {
+            if (element instanceof MutableNode<?>) {
+                ((MutableNode<?>) element).setParent(mutCompNode);
+            }
+            mutCompNode.getValue().add(element);
+        }
+
+        List<Node<?>> lst = new ArrayList<>();
+        lst.add(mutCompNode);
+        return lst;
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Node<?>> getNodeDispatcher() {
+        return dispatcher;
+    }
+
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/LeafNodeCnSnSerializer.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/LeafNodeCnSnSerializer.java
new file mode 100644 (file)
index 0000000..d17ac2e
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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.json.schema.cnsn.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+public class LeafNodeCnSnSerializer extends LeafNodeBaseSerializer<Node<?>> {
+
+    @Override
+    protected Node<?> serializeLeaf(LeafSchemaNode schema, LeafNode<?> node) {
+        return NodeFactory.createMutableSimpleNode(node.getNodeType(), null, node.getValue(), null, null);
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/LeafSetEntryNodeCnSnSerializer.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/LeafSetEntryNodeCnSnSerializer.java
new file mode 100644 (file)
index 0000000..9f628e5
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.json.schema.cnsn.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.base.serializer.LeafSetEntryNodeBaseSerializer;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+
+public class LeafSetEntryNodeCnSnSerializer extends
+        LeafSetEntryNodeBaseSerializer<Node<?>> {
+
+    @Override
+    protected Node<?> serializeLeaf(LeafListSchemaNode schema, LeafSetEntryNode<?> node) {
+        return NodeFactory.createMutableSimpleNode(
+                               node.getNodeType(), null, node.getValue(), null, null);
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/LeafSetNodeCnSnSerializer.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/LeafSetNodeCnSnSerializer.java
new file mode 100644 (file)
index 0000000..f784a53
--- /dev/null
@@ -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.json.schema.cnsn.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+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;
+
+public class LeafSetNodeCnSnSerializer extends
+        LeafSetNodeBaseSerializer<Node<?>> {
+
+    private FromNormalizedNodeSerializer<Node<?>, LeafSetEntryNode<?>, LeafListSchemaNode> leafSetEntryNodeSerializer;
+
+    public LeafSetNodeCnSnSerializer(final LeafSetEntryNodeCnSnSerializer leafSetEntryNodeSerializer) {
+        this.leafSetEntryNodeSerializer = leafSetEntryNodeSerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Node<?>, LeafSetEntryNode<?>, LeafListSchemaNode> getLeafSetEntryNodeSerializer() {
+        return leafSetEntryNodeSerializer;
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/MapEntryNodeCnSnSerializer.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/MapEntryNodeCnSnSerializer.java
new file mode 100644 (file)
index 0000000..daa5691
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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.json.schema.cnsn.serializer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.MutableNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
+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 com.google.common.base.Preconditions;
+
+public class MapEntryNodeCnSnSerializer extends MapEntryNodeBaseSerializer<Node<?>> {
+
+    private NodeSerializerDispatcher<Node<?>> dispatcher;
+
+    MapEntryNodeCnSnSerializer(final NodeSerializerDispatcher<Node<?>> dispatcher) {
+        this.dispatcher = Preconditions.checkNotNull(dispatcher);
+    }
+
+    public List<Node<?>> serialize(ListSchemaNode schema, MapEntryNode node) {
+
+        MutableCompositeNode mutCompNode = NodeFactory.createMutableCompositeNode(node.getNodeType(), null, null, null,
+                null);
+
+        for (Node<?> element : super.serialize(schema, node)) {
+            if (element instanceof MutableNode<?>) {
+                ((MutableNode<?>) element).setParent(mutCompNode);
+            }
+            mutCompNode.getValue().add(element);
+        }
+
+        List<Node<?>> lst = new ArrayList<>();
+        lst.add(mutCompNode);
+        return lst;
+    }
+
+    @Override
+    protected NodeSerializerDispatcher<Node<?>> getNodeDispatcher() {
+        return dispatcher;
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/MapNodeCnSnSerializer.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/MapNodeCnSnSerializer.java
new file mode 100644 (file)
index 0000000..ea4ed18
--- /dev/null
@@ -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.json.schema.cnsn.serializer;
+
+import org.opendaylight.yangtools.yang.data.api.Node;
+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;
+
+public class MapNodeCnSnSerializer extends MapNodeBaseSerializer<Node<?>> {
+
+    private final FromNormalizedNodeSerializer<Node<?>, MapEntryNode, ListSchemaNode> mapEntrySerializer;
+
+    public MapNodeCnSnSerializer(final MapEntryNodeCnSnSerializer mapEntrySerializer) {
+        this.mapEntrySerializer = mapEntrySerializer;
+    }
+
+    @Override
+    protected FromNormalizedNodeSerializer<Node<?>, MapEntryNode, ListSchemaNode> getMapEntryNodeDomSerializer() {
+        return mapEntrySerializer;
+    }
+}
diff --git a/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/json/CnSnToNormalizedNodesUtils.java b/yang/yang-data-json/src/main/java/org/opendaylight/yangtools/yang/data/json/schema/json/CnSnToNormalizedNodesUtils.java
new file mode 100644 (file)
index 0000000..7478aa5
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.json.schema.json;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+
+import com.google.common.collect.LinkedListMultimap;
+
+public class CnSnToNormalizedNodesUtils {
+
+    public static LinkedListMultimap<QName, Node<?>> mapChildElementsForSingletonNode(Node<?> node) {
+        return mapChildElements( ((CompositeNode)node).getValue());
+    }
+
+    public static LinkedListMultimap<QName, Node<?>> mapChildElements(Iterable<Node<?>> childNodesCollection) {
+        LinkedListMultimap<QName, Node<?>> mappedChildElements = LinkedListMultimap.create();
+
+        for (Node<?> node : childNodesCollection) {
+            mappedChildElements.put(node.getNodeType(), node);
+        }
+
+        return mappedChildElements;
+    }
+}
diff --git a/yang/yang-data-json/src/test/java/org/opendaylight/yangtools/yang/data/json/schema/TestUtils.java b/yang/yang-data-json/src/test/java/org/opendaylight/yangtools/yang/data/json/schema/TestUtils.java
new file mode 100644 (file)
index 0000000..a27a465
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.json.schema;
+
+import static org.junit.Assert.assertNotNull;
+import static org.opendaylight.yangtools.yang.data.impl.NodeFactory.createMutableCompositeNode;
+import static org.opendaylight.yangtools.yang.data.impl.NodeFactory.createMutableSimpleNode;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+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.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.MutableCompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+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.LeafSetEntryNode;
+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.builder.api.DataContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestUtils {
+
+    private static final Logger LOG = LoggerFactory.getLogger(TestUtils.class);
+
+    private static final String NAMESPACE_BASE = "simple:container:yang";
+    private static final String NAMESPACE_AUGMENT = "augment:container:yang";
+    private static Date revision_base;
+    private static Date revision_augment;
+
+    static {
+        try {
+            revision_base = new SimpleDateFormat("yyyy-MM-dd").parse("2013-11-12");
+            revision_augment = new SimpleDateFormat("yyyy-MM-dd").parse("2014-03-19");
+        } catch (ParseException e) {
+            e.printStackTrace();
+        }
+    }
+
+    public static Set<Module> loadModules(URI resourceURI) throws FileNotFoundException {
+        final YangModelParser parser = new YangParserImpl();
+        final File testDir = new File(resourceURI);
+        final String[] fileList = testDir.list();
+        final List<File> testFiles = new ArrayList<>();
+        if (fileList == null) {
+            throw new FileNotFoundException(resourceURI.toString());
+        }
+        for (String fileName : fileList) {
+            testFiles.add(new File(testDir, fileName));
+        }
+        return parser.parseYangModels(testFiles);
+    }
+
+    public static Set<Module> loadModulesFrom(String yangPath) throws URISyntaxException {
+        try {
+            return loadModules(TestUtils.class.getResource(yangPath).toURI());
+        } catch (FileNotFoundException e) {
+            LOG.error("Yang files at path: " + yangPath + " weren't loaded.");
+        }
+
+        return null;
+    }
+
+    public static DataSchemaNode resolveDataSchemaNode(String searchedDataSchemaName, Module module) {
+        assertNotNull("Module can't be null", module);
+
+        if (searchedDataSchemaName != null) {
+            for (DataSchemaNode dsn : module.getChildNodes()) {
+                if (dsn.getQName().getLocalName().equals(searchedDataSchemaName)) {
+                    return dsn;
+                }
+            }
+        } else if (module.getChildNodes().size() == 1) {
+            return module.getChildNodes().iterator().next();
+        }
+        return null;
+    }
+
+    public static Module resolveModule(String searchedModuleName, Set<Module> modules) {
+        assertNotNull("Modules can't be null.", modules);
+        if (searchedModuleName != null) {
+            for (Module m : modules) {
+                if (m.getName().equals(searchedModuleName)) {
+                    return m;
+                }
+            }
+        } else if (modules.size() == 1) {
+            return modules.iterator().next();
+        }
+        return null;
+    }
+
+    /**
+     * Prepare composite node structure according to
+     * /cnsn-to-normalized-node/simple-conainer.json
+     */
+    public static CompositeNode prepareCompositeNodeStruct() {
+        MutableCompositeNode cont = createMutableCompositeNode(new QName(URI.create(NAMESPACE_BASE), revision_base,
+                "cont"), null, null, null, null);
+
+        // cont1
+        List<Node<?>> contChilds = new ArrayList<>();
+        contChilds.add(createMutableCompositeNode(new QName(URI.create(NAMESPACE_BASE), revision_base, "cont1"), cont,
+                Collections.<Node<?>> emptyList(), null, null));
+
+        // cont2
+        MutableCompositeNode cont2 = createMutableCompositeNode(new QName(URI.create(NAMESPACE_BASE), revision_base,
+                "cont2"), cont, null, null, null);
+        List<Node<?>> cont2Childs = new ArrayList<>();
+        cont2Childs.add(createMutableSimpleNode(new QName(URI.create(NAMESPACE_BASE), revision_base, "lf21"), cont2,
+                "value in cont2/lf21", null, null));
+        cont2.setValue(cont2Childs);
+        contChilds.add(cont2);
+
+        // lst1
+        contChilds.add(createMutableCompositeNode(new QName(URI.create(NAMESPACE_BASE), revision_base, "lst1"), cont,
+                Collections.<Node<?>> emptyList(), null, null));
+
+        // lst2
+        MutableCompositeNode lst2_1 = createMutableCompositeNode(new QName(URI.create(NAMESPACE_BASE), revision_base,
+                "lst2"), cont, null, null, null);
+        List<Node<?>> lst2_1Childs = new ArrayList<>();
+        lst2_1Childs.add(createMutableSimpleNode(new QName(URI.create(NAMESPACE_BASE), revision_base, "lf21"), lst2_1,
+                "some value21", null, null));
+        lst2_1.setValue(lst2_1Childs);
+        contChilds.add(lst2_1);
+
+        MutableCompositeNode lst2_2 = createMutableCompositeNode(new QName(URI.create(NAMESPACE_BASE), revision_base,
+                "lst2"), cont, null, null, null);
+        List<Node<?>> lst2_2Childs = new ArrayList<>();
+        lst2_2Childs.add(createMutableSimpleNode(new QName(URI.create(NAMESPACE_BASE), revision_base, "lf22"), lst2_2,
+                "some value22", null, null));
+        lst2_2.setValue(lst2_2Childs);
+        contChilds.add(lst2_2);
+
+        // lflst1
+        contChilds.add(createMutableSimpleNode(new QName(URI.create(NAMESPACE_BASE), revision_base, "lflst1"), cont,
+                "lflst1_1", null, null));
+        contChilds.add(createMutableSimpleNode(new QName(URI.create(NAMESPACE_BASE), revision_base, "lflst1"), cont,
+                "lflst1_2", null, null));
+
+        // lf1
+        contChilds.add(createMutableSimpleNode(new QName(URI.create(NAMESPACE_BASE), revision_base, "lf1"), cont,
+                "lf1", null, null));
+
+        // lf11
+        contChilds.add(createMutableSimpleNode(new QName(URI.create(NAMESPACE_BASE), revision_base, "lf11"), cont,
+                "value from case (cs1)", null, null));
+
+        // cont3
+        MutableCompositeNode cont3 = createMutableCompositeNode(new QName(URI.create(NAMESPACE_AUGMENT),
+                revision_augment, "cont3"), cont, null, null, null);
+        List<Node<?>> cont3Childs = new ArrayList<>();
+        cont3Childs.add(createMutableSimpleNode(new QName(URI.create(NAMESPACE_AUGMENT), revision_augment, "lf31"),
+                cont3, "value in leaf in augment", null, null));
+        cont3.setValue(cont3Childs);
+        contChilds.add(cont3);
+
+        cont.setValue(contChilds);
+        return cont;
+    }
+
+    /**
+     * Prepare composite node structure according to
+     * /cnsn-to-normalized-node/simple-conainer.json
+     */
+    public static ContainerNode prepareNormalizedNodeStruct() throws URISyntaxException {
+        DataContainerNodeBuilder<NodeIdentifier, ContainerNode> containerBuilder = Builders.containerBuilder();
+        containerBuilder.withNodeIdentifier(getNodeIdentifier("cont"));
+        containerBuilder.withChild(Builders.containerBuilder().withNodeIdentifier(getNodeIdentifier("cont1")).build());
+        containerBuilder.withChild(Builders
+                .containerBuilder()
+                .withNodeIdentifier(getNodeIdentifier("cont2"))
+                .withChild(
+                        Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("lf21"))
+                                .withValue("value in cont2/lf21").build()).build());
+
+        CollectionNodeBuilder<MapEntryNode, MapNode> lst1 = Builders.mapBuilder().withNodeIdentifier(
+                getNodeIdentifier("lst1"));
+        lst1.withChild(Builders.mapEntryBuilder()
+                .withNodeIdentifier(getNodeIdentifierPredicate("lst1", new HashMap<String, Object>()))
+                .withValue(Collections.<DataContainerChild<? extends PathArgument, ?>> emptyList()).build());
+        containerBuilder.withChild(lst1.build());
+
+        CollectionNodeBuilder<MapEntryNode, MapNode> lst2 = Builders.mapBuilder().withNodeIdentifier(
+                getNodeIdentifier("lst2"));
+
+        Map<String, Object> lst2_1 = new HashMap<>();
+        lst2_1.put("lf21", "some value21");
+
+        List<DataContainerChild<? extends PathArgument, ?>> lst2_1_values = new ArrayList<>();
+        lst2_1_values.add(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("lf21"))
+                .withValue("some value21").build());
+        lst2.withChild(Builders.mapEntryBuilder().withNodeIdentifier(getNodeIdentifierPredicate("lst2", lst2_1))
+                .withValue(lst2_1_values).build());
+
+        Map<String, Object> lst2_2 = new HashMap<>();
+        lst2_2.put("lf22", "some value22");
+        List<DataContainerChild<? extends PathArgument, ?>> lst2_2_values = new ArrayList<>();
+        lst2_2_values.add(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("lf22"))
+                .withValue("some value22").build());
+        lst2.withChild(Builders.mapEntryBuilder().withNodeIdentifier(getNodeIdentifierPredicate("lst2", lst2_2))
+                .withValue(lst2_2_values).build());
+        containerBuilder.withChild(lst2.build());
+
+        ListNodeBuilder<Object, LeafSetEntryNode<Object>> lflst1 = Builders.leafSetBuilder().withNodeIdentifier(
+                getNodeIdentifier("lflst1"));
+        lflst1.withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(getNodeIdentifier("lflst1", "lflst1_1"))
+                .withValue("lflst1_1").build());
+        lflst1.withChild(Builders.leafSetEntryBuilder().withNodeIdentifier(getNodeIdentifier("lflst1", "lflst1_2"))
+                .withValue("lflst1_2").build());
+        containerBuilder.withChild(lflst1.build());
+
+        containerBuilder.withChild(Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("lf1")).withValue("lf1")
+                .build());
+
+        containerBuilder.withChild(Builders
+                .choiceBuilder()
+                .withNodeIdentifier(getNodeIdentifier("chc"))
+                .withChild(
+                        Builders.leafBuilder().withNodeIdentifier(getNodeIdentifier("lf11"))
+                                .withValue("value from case (cs1)").build()).build());
+
+        Set<QName> children = new HashSet<>();
+        children.add(new QName(new URI(NAMESPACE_AUGMENT), revision_augment, "cont3"));
+
+        containerBuilder.withChild(Builders
+                .augmentationBuilder()
+                .withNodeIdentifier(getAugmentationIdentifier(null, null, null, children))
+                .withChild(
+                        Builders.containerBuilder()
+                                .withNodeIdentifier(getNodeIdentifier("cont3", NAMESPACE_AUGMENT, revision_augment))
+                                .withChild(
+                                        Builders.leafBuilder()
+                                                .withNodeIdentifier(
+                                                        getNodeIdentifier("lf31", NAMESPACE_AUGMENT, revision_augment))
+                                                .withValue("value in leaf in augment").build()).build()).build());
+
+        ContainerNode build = containerBuilder.build();
+        return build;
+    }
+
+    private static InstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName) {
+        return new InstanceIdentifier.NodeIdentifier(new QName(URI.create(NAMESPACE_BASE), revision_base, localName));
+    }
+
+    private static InstanceIdentifier.NodeIdentifier getNodeIdentifier(String localName, String namespace, Date revision) {
+        return new InstanceIdentifier.NodeIdentifier(new QName(URI.create(namespace), revision, localName));
+    }
+
+    private static InstanceIdentifier.NodeWithValue getNodeIdentifier(String localName, Object value) {
+        return new InstanceIdentifier.NodeWithValue(new QName(URI.create(NAMESPACE_BASE), revision_base, localName),
+                value);
+    }
+
+    private static InstanceIdentifier.NodeIdentifierWithPredicates getNodeIdentifierPredicate(String localName,
+            Map<String, Object> keys) {
+        Map<QName, Object> predicate = new HashMap<>();
+        for (String key : keys.keySet()) {
+            predicate.put(new QName(URI.create(NAMESPACE_BASE), revision_base, key), keys.get(key));
+        }
+
+        return new InstanceIdentifier.NodeIdentifierWithPredicates(
+
+        new QName(URI.create(NAMESPACE_BASE), revision_base, localName), predicate);
+    }
+
+    private static InstanceIdentifier.AugmentationIdentifier getAugmentationIdentifier(String localName,
+            String namespace, Date revision, Set<QName> children) {
+        return new InstanceIdentifier.AugmentationIdentifier(null, children);
+    }
+
+}
diff --git a/yang/yang-data-json/src/test/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/ParseCnSnStructToNormalizedStructTest.java b/yang/yang-data-json/src/test/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/parser/ParseCnSnStructToNormalizedStructTest.java
new file mode 100644 (file)
index 0000000..223278c
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.json.schema.cnsn.parser;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.json.schema.TestUtils;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+public class ParseCnSnStructToNormalizedStructTest {
+
+    private static DataSchemaNode resolvedDataSchemaNode;
+
+    @BeforeClass
+    public static void loadData() throws URISyntaxException {
+        Set<Module> modules = TestUtils.loadModulesFrom("/cnsn-to-normalized-node/yang");
+        Module resolvedModule = TestUtils.resolveModule("simple-container-yang", modules);
+        resolvedDataSchemaNode = TestUtils.resolveDataSchemaNode("cont", resolvedModule);
+    }
+
+    @Test
+    public void testCnSnToNormalizedNode() throws URISyntaxException {
+
+        CompositeNode compNode = TestUtils.prepareCompositeNodeStruct();
+
+        List<Node<?>> lst = new ArrayList<Node<?>>();
+        lst.add(compNode);
+        ContainerNode parsed = CnSnToNormalizedNodeParserFactory.getInstance().getContainerNodeParser()
+                .parse(lst, (ContainerSchemaNode) resolvedDataSchemaNode);
+
+        ContainerNode prepareExpectedStruct = TestUtils.prepareNormalizedNodeStruct();
+        assertEquals(prepareExpectedStruct, parsed);
+    }
+
+}
diff --git a/yang/yang-data-json/src/test/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/SerializeNormalizedStructToCnSnStructTest.java b/yang/yang-data-json/src/test/java/org/opendaylight/yangtools/yang/data/json/schema/cnsn/serializer/SerializeNormalizedStructToCnSnStructTest.java
new file mode 100644 (file)
index 0000000..5e1283f
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.json.schema.cnsn.serializer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URISyntaxException;
+import java.util.Set;
+
+import com.google.common.collect.Sets;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.json.schema.TestUtils;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+public class SerializeNormalizedStructToCnSnStructTest {
+
+    private static DataSchemaNode resolvedDataSchemaNode;
+
+    @BeforeClass
+    public static void loadData() throws URISyntaxException {
+        Set<Module> modules = TestUtils.loadModulesFrom("/cnsn-to-normalized-node/yang");
+        Module resolvedModule = TestUtils.resolveModule("simple-container-yang", modules);
+        resolvedDataSchemaNode = TestUtils.resolveDataSchemaNode("cont", resolvedModule);
+    }
+
+    @Test
+    public void testCnSnToNormalizedNode() throws URISyntaxException {
+        ContainerNode containerNode = TestUtils.prepareNormalizedNodeStruct();
+
+        Iterable<Node<?>> serialized = CnSnFromNormalizedNodeSerializerFactory.getInstance()
+                .getContainerNodeSerializer().serialize((ContainerSchemaNode) resolvedDataSchemaNode, containerNode);
+
+        assertNotNull(serialized);
+        assertNotNull(serialized.iterator());
+        assertNotNull(serialized.iterator().hasNext());
+
+        CompositeNode compNode = TestUtils.prepareCompositeNodeStruct();
+
+        assertEquals(serialized.iterator().next().getNodeType(), compNode.getNodeType());
+
+        Set<Node<?>> value = Sets.newHashSet(((CompositeNode)serialized.iterator().next()).getValue());
+        assertEquals(value, Sets.newHashSet(compNode.getValue()));
+    }
+}
diff --git a/yang/yang-data-json/src/test/resources/cnsn-to-normalized-node/json/simple-container.json b/yang/yang-data-json/src/test/resources/cnsn-to-normalized-node/json/simple-container.json
new file mode 100644 (file)
index 0000000..b840efb
--- /dev/null
@@ -0,0 +1,31 @@
+{
+    "simple-container-yang:cont":{
+        "cont1":{
+        },
+        "cont2":{
+            "lf21":"value in cont2/lf21"
+        },
+        "augment-container-yang:cont3":{
+            "lf31":"value in leaf in augment"
+        },
+        "lst1": [
+            {
+            }
+        ],
+        "lst2": [
+          {
+              "lf21":"some value21"
+          },
+          {
+              "lf22":"some value22"
+          }
+        ],      
+        "lflst1":[
+            "lflst1_1",
+            "lflst1_2"
+        ],
+        "lf1":"lf1",
+        
+        "lf11":"value from case (cs1)"
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-data-json/src/test/resources/cnsn-to-normalized-node/yang/augment-simple-container.yang b/yang/yang-data-json/src/test/resources/cnsn-to-normalized-node/yang/augment-simple-container.yang
new file mode 100644 (file)
index 0000000..9f24f13
--- /dev/null
@@ -0,0 +1,18 @@
+module augment-container-yang {
+  namespace "augment:container:yang";  
+
+  prefix "auconyang";
+  import simple-container-yang { prefix "simple"; revision-date 2013-11-12; }
+  
+  revision 2014-03-19 {    
+  }
+
+  augment "/simple:cont" {
+    container cont3 {
+        leaf lf31 {
+            type string;
+        }
+    }
+  }
+   
+}
diff --git a/yang/yang-data-json/src/test/resources/cnsn-to-normalized-node/yang/simple-container.yang b/yang/yang-data-json/src/test/resources/cnsn-to-normalized-node/yang/simple-container.yang
new file mode 100644 (file)
index 0000000..127ba8f
--- /dev/null
@@ -0,0 +1,47 @@
+module simple-container-yang {
+  namespace "simple:container:yang";  
+
+  prefix "smpdtp";
+  revision 2013-11-12 {    
+  }
+  
+  container cont {
+       container cont1 {
+       }
+       container cont2 {
+            leaf lf21 {
+                type string;
+            } 
+       }
+       list lst1 {
+       }
+       list lst2 {
+            leaf lf21 {
+                type string;
+            }
+            leaf lf22 {
+                type string;
+            }
+       }
+       leaf-list lflst1 {
+               type string;
+       }
+       leaf lf1 {
+               type string;
+       }
+       
+    choice chc {
+      case cs1 {
+          leaf lf11 {
+              type string;
+          }
+      }
+      case cs2 {
+          leaf lf21 {
+              type string;
+          }
+      }
+    }
+    
+  }
+}
diff --git a/yang/yang-data-operations/pom.xml b/yang/yang-data-operations/pom.xml
new file mode 100644 (file)
index 0000000..dee77da
--- /dev/null
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yang</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>yang-data-operations</artifactId>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.opendaylight.yangtools.yang.data.operations
+                        </Export-Package>
+                        <Import-Package>
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-data-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-data-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+</project>
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/AbstractContainerNodeModification.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/AbstractContainerNodeModification.java
new file mode 100644 (file)
index 0000000..1f3a7d3
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * 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.operations;
+
+import java.util.List;
+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.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.DataContainerNode;
+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.builder.api.DataContainerNodeBuilder;
+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.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+abstract class AbstractContainerNodeModification<S, N extends DataContainerNode<?>> implements Modification<S, N> {
+
+    @Override
+    public final Optional<N> modify(S schema, Optional<N> actual, Optional<N> modification,
+            OperationStack operationStack) throws DataModificationException {
+
+        operationStack.enteringNode(modification);
+
+        Optional<N> result;
+        QName nodeQName = getQName(schema);
+
+        switch (operationStack.getCurrentOperation()) {
+        case DELETE: {
+            DataModificationException.DataMissingException.check(nodeQName, actual);
+        }
+        case REMOVE: {
+            result = Optional.absent();
+            break;
+        }
+        case CREATE: {
+            DataModificationException.DataExistsException.check(nodeQName, actual, null);
+        }
+        case REPLACE: {
+            result = modification;
+            break;
+        }
+        case NONE: {
+            DataModificationException.DataMissingException.check(nodeQName, actual);
+        }
+        case MERGE: {
+            // Recursively modify all child nodes
+            result = modifyContainer(schema, actual, modification, operationStack);
+            break;
+        }
+        default:
+            throw new UnsupportedOperationException(String.format("Unable to perform operation: %s on: %s, unknown",
+                    operationStack.getCurrentOperation(), schema));
+        }
+
+        operationStack.exitingNode(modification);
+        return result;
+    }
+
+    protected abstract QName getQName(S schema);
+
+    private Optional<N> modifyContainer(S schema, Optional<N> actual, Optional<N> modification,
+            OperationStack operationStack) throws DataModificationException {
+
+        if (actual.isPresent() == false) {
+            return modification;
+        }
+
+        if (modification.isPresent() == false) {
+            return actual;
+        }
+
+        Set<InstanceIdentifier.PathArgument> toProcess = getChildrenToProcess(schema, actual, modification);
+
+        List<? extends DataContainerChild<?, ?>> merged = modifyContainerChildNodes(schema, operationStack,
+                actual.get(), modification.get(), toProcess);
+        return build(schema, merged);
+    }
+
+    private List<? extends DataContainerChild<?, ?>> modifyContainerChildNodes(S schema, OperationStack operationStack,
+            N actual, N modification, Set<InstanceIdentifier.PathArgument> toProcess) throws DataModificationException {
+        List<DataContainerChild<?, ?>> result = Lists.newArrayList();
+
+        for (InstanceIdentifier.PathArgument childToProcessId : toProcess) {
+            Object schemaOfChildToProcess = findSchema(schema, childToProcessId);
+
+            Optional<? extends DataContainerChild<?, ?>> modifiedValues = modifyContainerNode(operationStack, actual,
+                    modification, childToProcessId, schemaOfChildToProcess);
+
+            if (modifiedValues.isPresent()) {
+                result.add(modifiedValues.get());
+            }
+        }
+
+        return result;
+    }
+
+    private Optional<? extends DataContainerChild<?, ?>> modifyContainerNode(OperationStack operationStack, N actual,
+            N modification, InstanceIdentifier.PathArgument childToProcess, Object schemaChild)
+            throws DataModificationException {
+
+        Optional<DataContainerChild<?, ?>> storedChildren = actual.getChild(childToProcess);
+        Optional<DataContainerChild<?, ?>> modifiedChildren = modification.getChild(childToProcess);
+
+        return NodeDispatcher.dispatchChildModification(schemaChild, storedChildren, modifiedChildren, operationStack);
+    }
+
+    private Object findSchema(S schema, InstanceIdentifier.PathArgument childToProcessId) {
+        if (childToProcessId instanceof InstanceIdentifier.AugmentationIdentifier) {
+            return findSchemaForAugment(schema, (InstanceIdentifier.AugmentationIdentifier) childToProcessId);
+        } else {
+            return findSchemaForChild(schema, childToProcessId.getNodeType());
+        }
+    }
+
+    protected abstract Object findSchemaForChild(S schema, QName nodeType);
+
+    protected abstract Object findSchemaForAugment(S schema, InstanceIdentifier.AugmentationIdentifier childToProcessId);
+
+    private Optional<N> build(S schema, List<? extends DataContainerChild<?, ?>> result) {
+        DataContainerNodeBuilder<?, N> b = getBuilder(schema);
+
+        // TODO skip empty container nodes ? e.g. if container looses all its child nodes
+//        if(result.isEmpty()) {
+//            return Optional.absent();
+//        }
+
+        for (DataContainerChild<?, ?> dataContainerChild : result) {
+            b.withChild(dataContainerChild);
+        }
+        return Optional.of(b.build());
+    }
+
+    protected abstract DataContainerNodeBuilder<?, N> getBuilder(S schema);
+
+    protected Set<InstanceIdentifier.PathArgument> getChildrenToProcess(S schema, Optional<N> actual,
+            Optional<N> modification) throws DataModificationException {
+        Set<InstanceIdentifier.PathArgument> qNames = Sets.newLinkedHashSet();
+
+        qNames.addAll(getChildQNames(actual));
+        qNames.addAll(getChildQNames(modification));
+        return qNames;
+    }
+
+    private Set<? extends InstanceIdentifier.PathArgument> getChildQNames(Optional<N> actual) {
+        Set<InstanceIdentifier.PathArgument> qNames = Sets.newLinkedHashSet();
+
+        for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> child : actual.get().getValue()) {
+            qNames.add(child.getIdentifier());
+        }
+
+        return qNames;
+    }
+
+    private static final class NodeDispatcher {
+
+        private static final LeafNodeModification LEAF_NODE_MODIFICATION = new LeafNodeModification();
+        private static final LeafSetNodeModification LEAF_SET_NODE_MODIFICATION = new LeafSetNodeModification();
+        private static final AugmentationNodeModification AUGMENTATION_NODE_MODIFICATION = new AugmentationNodeModification();
+        private static final MapNodeModification MAP_NODE_MODIFICATION = new MapNodeModification();
+        private static final ContainerNodeModification CONTAINER_NODE_MODIFICATION = new ContainerNodeModification();
+        private static final ChoiceNodeModification CHOICE_NODE_MODIFICATION = new ChoiceNodeModification();
+
+        static Optional<? extends DataContainerChild<?, ?>> dispatchChildModification(Object schemaChild,
+                Optional<DataContainerChild<?, ?>> actual, Optional<DataContainerChild<?, ?>> modification,
+                OperationStack operations) throws DataModificationException {
+
+            if (schemaChild instanceof LeafSchemaNode) {
+                return onLeafNode((LeafSchemaNode) schemaChild, actual, modification, operations);
+            } else if (schemaChild instanceof ContainerSchemaNode) {
+                return onContainerNode((ContainerSchemaNode) schemaChild, actual, modification, operations);
+            } else if (schemaChild instanceof LeafListSchemaNode) {
+                return onLeafSetNode((LeafListSchemaNode) schemaChild, actual, modification, operations);
+            } else if (schemaChild instanceof AugmentationSchema) {
+                return onAugmentationNode((AugmentationSchema) schemaChild, actual, modification, operations);
+            } else if (schemaChild instanceof ListSchemaNode) {
+                return onMapNode((ListSchemaNode) schemaChild, actual, modification, operations);
+            } else if (schemaChild instanceof org.opendaylight.yangtools.yang.model.api.ChoiceNode) {
+                return onChoiceNode((org.opendaylight.yangtools.yang.model.api.ChoiceNode) schemaChild, actual,
+                        modification, operations);
+            }
+
+            throw new IllegalArgumentException("Unknown schema node type " + schemaChild);
+        }
+
+        private static Optional<? extends DataContainerChild<?, ?>> onChoiceNode(
+                org.opendaylight.yangtools.yang.model.api.ChoiceNode schemaChild,
+                Optional<? extends DataContainerChild<?, ?>> actual,
+                Optional<? extends DataContainerChild<?, ?>> modification, OperationStack operations)
+                throws DataModificationException {
+            checkType(actual, ChoiceNode.class);
+            checkType(modification, ChoiceNode.class);
+            return CHOICE_NODE_MODIFICATION.modify(schemaChild, (Optional<ChoiceNode>) actual,
+                    (Optional<ChoiceNode>) modification, operations);
+        }
+
+        private static Optional<? extends DataContainerChild<?, ?>> onMapNode(ListSchemaNode schemaChild,
+                Optional<? extends DataContainerChild<?, ?>> actual,
+                Optional<? extends DataContainerChild<?, ?>> modification, OperationStack operations)
+                throws DataModificationException {
+            checkType(actual, MapNode.class);
+            checkType(modification, MapNode.class);
+            return MAP_NODE_MODIFICATION.modify(schemaChild, (Optional<MapNode>) actual,
+                    (Optional<MapNode>) modification, operations);
+        }
+
+        private static Optional<? extends DataContainerChild<?, ?>> onAugmentationNode(AugmentationSchema schemaChild,
+                Optional<? extends DataContainerChild<?, ?>> actual,
+                Optional<? extends DataContainerChild<?, ?>> modification, OperationStack operations)
+                throws DataModificationException {
+            checkType(actual, AugmentationNode.class);
+            checkType(modification, AugmentationNode.class);
+            return AUGMENTATION_NODE_MODIFICATION.modify(schemaChild, (Optional<AugmentationNode>) actual,
+                    (Optional<AugmentationNode>) modification, operations);
+        }
+
+        private static Optional<? extends DataContainerChild<?, ?>> onLeafSetNode(LeafListSchemaNode schemaChild,
+                Optional<? extends DataContainerChild<?, ?>> actual,
+                Optional<? extends DataContainerChild<?, ?>> modification, OperationStack operations)
+                throws DataModificationException {
+            checkType(actual, LeafSetNode.class);
+            checkType(modification, LeafSetNode.class);
+            return LEAF_SET_NODE_MODIFICATION.modify(schemaChild, (Optional<LeafSetNode<?>>) actual,
+                    (Optional<LeafSetNode<?>>) modification, operations);
+        }
+
+        private static Optional<? extends DataContainerChild<?, ?>> onContainerNode(ContainerSchemaNode schemaChild,
+                Optional<? extends DataContainerChild<?, ?>> actual,
+                Optional<? extends DataContainerChild<?, ?>> modification, OperationStack operations)
+                throws DataModificationException {
+            checkType(actual, ContainerNode.class);
+            checkType(modification, ContainerNode.class);
+            return CONTAINER_NODE_MODIFICATION.modify(schemaChild, (Optional<ContainerNode>) actual,
+                    (Optional<ContainerNode>) modification, operations);
+        }
+
+        private static Optional<? extends DataContainerChild<?, ?>> onLeafNode(LeafSchemaNode schemaChild,
+                Optional<? extends DataContainerChild<?, ?>> actual,
+                Optional<? extends DataContainerChild<?, ?>> modification, OperationStack operations)
+                throws DataModificationException {
+            checkType(actual, LeafNode.class);
+            checkType(modification, LeafNode.class);
+            return LEAF_NODE_MODIFICATION.modify(schemaChild, (Optional<LeafNode<?>>) actual,
+                    (Optional<LeafNode<?>>) modification, operations);
+        }
+
+        private static void checkType(Optional<? extends DataContainerChild<?, ?>> actual, Class<?> leafNodeClass) {
+            if (actual.isPresent()) {
+                Preconditions.checkArgument(leafNodeClass.isAssignableFrom(actual.get().getClass()),
+                        "Unexpected node type, should be: %s, but was: %s, for: %s", leafNodeClass, actual.getClass(),
+                        actual);
+            }
+        }
+    }
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/AugmentationNodeModification.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/AugmentationNodeModification.java
new file mode 100644 (file)
index 0000000..2411d8f
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * 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.operations;
+
+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;
+
+final class AugmentationNodeModification extends AbstractContainerNodeModification<AugmentationSchema, AugmentationNode> {
+
+    @Override
+    protected QName getQName(AugmentationSchema schema) {
+        // FIXME null qname for AUGMENT
+        return null;
+    }
+
+    @Override
+    protected Object findSchemaForChild(AugmentationSchema schema, QName nodeType) {
+        return SchemaUtils.findSchemaForChild(schema, nodeType);
+    }
+
+    @Override
+    protected Object findSchemaForAugment(AugmentationSchema schema, InstanceIdentifier.AugmentationIdentifier childToProcessId) {
+        throw new UnsupportedOperationException("Augmentation cannot be augmented directly, " + schema);
+    }
+
+    @Override
+    protected DataContainerNodeBuilder<?, AugmentationNode> getBuilder(AugmentationSchema schema) {
+        return Builders.augmentationBuilder(schema);
+    }
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/ChoiceNodeModification.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/ChoiceNodeModification.java
new file mode 100644 (file)
index 0000000..534c6a6
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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.operations;
+
+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.api.schema.DataContainerChild;
+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.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Sets;
+
+final class ChoiceNodeModification extends
+        AbstractContainerNodeModification<ChoiceNode, org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode> {
+
+    @Override
+    protected QName getQName(ChoiceNode schema) {
+        return schema.getQName();
+    }
+
+    @Override
+    protected Object findSchemaForChild(ChoiceNode schema, QName nodeType) {
+        return SchemaUtils.findSchemaForChild(schema, nodeType);
+    }
+
+    @Override
+    protected Set<InstanceIdentifier.PathArgument> getChildrenToProcess(ChoiceNode schema,
+            Optional<org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode> actual,
+            Optional<org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode> modification)
+            throws DataModificationException {
+        Set<InstanceIdentifier.PathArgument> childrenToProcess = super.getChildrenToProcess(schema, actual,
+                modification);
+
+        if (modification.isPresent() == false) {
+            return childrenToProcess;
+        }
+
+        // Detect case node from modification
+        ChoiceCaseNode detectedCase = null;
+        for (DataContainerChild<? extends InstanceIdentifier.PathArgument, ?> child : modification.get().getValue()) {
+            Optional<ChoiceCaseNode> detectedCaseForChild = SchemaUtils.detectCase(schema, child);
+
+            if(detectedCaseForChild.isPresent() == false) {
+                DataModificationException.IllegalChoiceValuesException.throwUnknownChild(schema.getQName(),
+                        child.getNodeType());
+            }
+
+            if (detectedCase != null && detectedCase.equals(detectedCaseForChild.get()) == false) {
+                DataModificationException.IllegalChoiceValuesException.throwMultipleCasesReferenced(schema.getQName(),
+                        modification.get(), detectedCase.getQName(), detectedCaseForChild.get().getQName());
+            }
+            detectedCase = detectedCaseForChild.get();
+        }
+
+        if (detectedCase == null)
+            return childrenToProcess;
+
+        // Filter out child nodes that do not belong to detected case =
+        // Nodes from other cases present in actual
+        Set<InstanceIdentifier.PathArgument> childrenToProcessFiltered = Sets.newLinkedHashSet();
+        for (InstanceIdentifier.PathArgument childToProcess : childrenToProcess) {
+            // child from other cases, skip
+            if (childToProcess instanceof AugmentationNode
+                    && SchemaUtils.belongsToCaseAugment(detectedCase,
+                            (InstanceIdentifier.AugmentationIdentifier) childToProcess) == false) {
+                continue;
+            } else if (belongsToCase(detectedCase, childToProcess) == false) {
+                continue;
+            }
+
+            childrenToProcessFiltered.add(childToProcess);
+        }
+
+        return childrenToProcessFiltered;
+    }
+
+    private boolean belongsToCase(ChoiceCaseNode detectedCase, InstanceIdentifier.PathArgument childToProcess) {
+        return detectedCase.getDataChildByName(childToProcess.getNodeType()) != null;
+    }
+
+    @Override
+    protected Object findSchemaForAugment(ChoiceNode schema, InstanceIdentifier.AugmentationIdentifier childToProcessId) {
+        return SchemaUtils.findSchemaForAugment(schema, childToProcessId.getPossibleChildNames());
+    }
+
+    @Override
+    protected DataContainerNodeBuilder<?, org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode> getBuilder(
+            ChoiceNode schema) {
+        return Builders.choiceBuilder(schema);
+    }
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/ContainerNodeModification.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/ContainerNodeModification.java
new file mode 100644 (file)
index 0000000..3fffa2f
--- /dev/null
@@ -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.operations;
+
+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.ContainerSchemaNode;
+
+final class ContainerNodeModification extends AbstractContainerNodeModification<ContainerSchemaNode, ContainerNode> {
+
+    // FIXME normalized nodes as a result from merge contain attributes e.g. operation="merge" from modification
+
+    @Override
+    protected QName getQName(ContainerSchemaNode schema) {
+        return schema.getQName();
+    }
+
+    @Override
+    protected Object findSchemaForChild(ContainerSchemaNode schema, QName nodeType) {
+        return SchemaUtils.findSchemaForChild(schema, nodeType);
+    }
+
+    @Override
+    protected Object findSchemaForAugment(ContainerSchemaNode schema,
+            InstanceIdentifier.AugmentationIdentifier childToProcessId) {
+        return SchemaUtils.findSchemaForAugment(schema, childToProcessId.getPossibleChildNames());
+    }
+
+    @Override
+    protected DataContainerNodeBuilder<?, ContainerNode> getBuilder(ContainerSchemaNode schema) {
+        return Builders.containerBuilder(schema);
+    }
+
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/DataModificationException.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/DataModificationException.java
new file mode 100644 (file)
index 0000000..cc66535
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * 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.operations;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.Node;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+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.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+public class DataModificationException extends Exception {
+    // TODO replace QName as identifier for node with schema or NodeIdentifier,
+    // Augmentation does not have a QName
+
+    private static final long serialVersionUID = 1L;
+    private final QName node;
+
+    public DataModificationException(String message, QName node) {
+        super(message);
+        this.node = node;
+    }
+
+    public QName getNodeQName() {
+        return node;
+    }
+
+    public static final class DataMissingException extends DataModificationException {
+        private static final long serialVersionUID = 1L;
+
+        public DataMissingException(QName nodeType) {
+            super(String.format("Data missing for node: %s", nodeType), nodeType);
+        }
+
+        public DataMissingException(QName nodeType, Node<?> modificationNode) {
+            super(String.format("Data missing for node: %s, %s", nodeType, modificationNode), nodeType);
+        }
+
+        static void check(QName nodeQName, Optional<? extends NormalizedNode<?, ?>> actualNode) throws DataMissingException {
+            if (actualNode.isPresent() == false) {
+                throw new DataMissingException(nodeQName);
+            }
+        }
+
+        static void check(QName nodeQName, Optional<LeafSetNode<?>> actualNodes, LeafSetEntryNode<?> modificationNode)
+                throws DataMissingException {
+            if (actualNodes.isPresent()==false || actualNodes.get().getChild(modificationNode.getIdentifier()).isPresent() == false) {
+                throw new DataMissingException(nodeQName, modificationNode);
+            }
+        }
+
+        static void check(QName nodeQName, Optional<MapNode> actualNodes, MapEntryNode modificationNode)
+                throws DataModificationException {
+            if (actualNodes.isPresent()==false || actualNodes.get().getChild(modificationNode.getIdentifier()).isPresent() == false) {
+                throw new DataMissingException(nodeQName, modificationNode);
+            }
+        }
+    }
+
+    public static final class DataExistsException extends DataModificationException {
+        private static final long serialVersionUID = 1L;
+
+        public DataExistsException(QName nodeType, NormalizedNode<?, ?> actualNode, NormalizedNode<?, ?> modificationNode) {
+            super(String
+                    .format("Data already exists for node: %s, current value: %s. modification value: %s", nodeType, actualNode, modificationNode),
+                    nodeType);
+        }
+
+        static void check(QName nodeQName, Optional<? extends NormalizedNode<?, ?>> actualNode, NormalizedNode<?, ?> modificationNode) throws DataExistsException {
+            if (actualNode.isPresent()) {
+                throw new DataExistsException(nodeQName, actualNode.get(), modificationNode);
+            }
+        }
+
+        static void check(QName nodeQName, Optional<LeafSetNode<?>> actualNodes, LeafSetEntryNode<?> modificationNode)
+                throws DataExistsException {
+            if (actualNodes.isPresent() && actualNodes.get().getChild(modificationNode.getIdentifier()).isPresent()) {
+                throw new DataExistsException(nodeQName, actualNodes.get(), modificationNode);
+            }
+        }
+
+        public static void check(QName qName, Optional<MapNode> actualNodes, MapEntryNode listModification)
+                throws DataModificationException {
+            if (actualNodes.isPresent() && actualNodes.get().getChild(listModification.getIdentifier()).isPresent()) {
+                throw new DataExistsException(qName, actualNodes.get(), listModification);
+            }
+        }
+    }
+
+    public static final class IllegalChoiceValuesException extends DataModificationException {
+        private static final long serialVersionUID = 1L;
+
+        public IllegalChoiceValuesException(String message, QName node) {
+            super(message, node);
+        }
+
+        public static void throwMultipleCasesReferenced(QName choiceQName, ChoiceNode modification,
+                QName case1QName, QName case2QName) throws IllegalChoiceValuesException {
+            throw new IllegalChoiceValuesException(String.format(
+                    "Child nodes from multiple cases present in modification: %s, choice: %s, case1: %s, case2: %s",
+                    modification, choiceQName, case1QName, case2QName), choiceQName);
+        }
+
+        public static void throwUnknownChild(QName choiceQName, QName nodeQName) throws IllegalChoiceValuesException {
+            throw new IllegalChoiceValuesException(String.format(
+                    "Unknown child node detected, choice: %s, child node: %s",
+                    choiceQName, nodeQName), choiceQName);
+        }
+    }
+
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/DataOperations.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/DataOperations.java
new file mode 100644 (file)
index 0000000..401b387
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.operations;
+
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+import com.google.common.base.Optional;
+
+/**
+ * Edit config operations utilities.
+ */
+public final class DataOperations {
+
+    private DataOperations() {}
+
+    public static Optional<ContainerNode> modify(ContainerSchemaNode schema, ContainerNode stored,
+            ContainerNode modified) throws DataModificationException {
+        return modify(schema, stored, modified, ModifyAction.MERGE);
+    }
+
+    public static Optional<MapNode> modify(ListSchemaNode schema, MapNode stored, MapNode modified)
+            throws DataModificationException {
+        return modify(schema, stored, modified, ModifyAction.MERGE);
+    }
+
+    public static Optional<ContainerNode> modify(ContainerSchemaNode schema, ContainerNode stored,
+            ContainerNode modified, ModifyAction defaultOperation) throws DataModificationException {
+
+        OperationStack operations = new OperationStack(defaultOperation);
+
+        return new ContainerNodeModification().modify(schema, Optional.fromNullable(stored),
+                Optional.fromNullable(modified), operations);
+    }
+
+    public static Optional<MapNode> modify(ListSchemaNode schema, MapNode stored, MapNode modified,
+            ModifyAction defaultOperation) throws DataModificationException {
+
+        OperationStack operations = new OperationStack(defaultOperation);
+
+        return new MapNodeModification().modify(schema, Optional.fromNullable(stored), Optional.fromNullable(modified),
+                operations);
+    }
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/LeafNodeModification.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/LeafNodeModification.java
new file mode 100644 (file)
index 0000000..39990a5
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.operations;
+
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+
+import com.google.common.base.Optional;
+
+final class LeafNodeModification implements Modification<LeafSchemaNode, LeafNode<?>> {
+
+    @Override
+    public Optional<LeafNode<?>> modify(LeafSchemaNode schema, Optional<LeafNode<?>> actualNode,
+                                    Optional<LeafNode<?>> modificationNode, OperationStack operationStack) throws DataModificationException {
+
+        operationStack.enteringNode(modificationNode);
+
+        Optional<LeafNode<?>> result;
+
+        // Returns either actual node, modification node or empty in case of removal
+        switch (operationStack.getCurrentOperation()) {
+            case MERGE: {
+                result = modificationNode.isPresent() ? modificationNode : actualNode;
+                break;
+            }
+            case CREATE: {
+                DataModificationException.DataExistsException.check(schema.getQName(), actualNode, null);
+            }
+            case REPLACE: {
+                result = modificationNode;
+                break;
+            }
+            case DELETE: {
+                DataModificationException.DataMissingException.check(schema.getQName(), actualNode);
+            }
+            case REMOVE: {
+                result = Optional.absent();
+                break;
+            }
+            case NONE: {
+                result = actualNode;
+                break;
+            }
+            default:
+                throw new UnsupportedOperationException(String.format("Unable to perform operation: %s on: %s, unknown", operationStack.getCurrentOperation(), schema));
+
+        }
+
+        operationStack.exitingNode(modificationNode);
+
+        return result;
+    }
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/LeafSetNodeModification.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/LeafSetNodeModification.java
new file mode 100644 (file)
index 0000000..de5a5b0
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * 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.operations;
+
+import java.util.List;
+
+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.model.api.LeafListSchemaNode;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+
+final class LeafSetNodeModification implements Modification<LeafListSchemaNode, LeafSetNode<?>> {
+
+    @Override
+    public Optional<LeafSetNode<?>> modify(LeafListSchemaNode schema, Optional<LeafSetNode<?>> actual,
+            Optional<LeafSetNode<?>> modification, OperationStack operationStack) throws DataModificationException {
+
+        List<LeafSetEntryNode<?>> resultNodes = Lists.newArrayList();
+        if(actual.isPresent()) {
+            Iterables.addAll(resultNodes, actual.get().getValue());
+        }
+
+        // TODO implement ordering for modification nodes
+
+        for (LeafSetEntryNode<?> leafListModification : modification.get().getValue()) {
+            operationStack.enteringNode(leafListModification);
+
+            switch (operationStack.getCurrentOperation()) {
+                case MERGE:
+                case CREATE: {
+                    DataModificationException.DataExistsException.check(schema.getQName(), actual, leafListModification);
+                }
+                case REPLACE: {
+                    if (contains(actual, leafListModification) == false) {
+                        resultNodes.add(leafListModification);
+                    }
+                    break;
+                }
+                case DELETE: {
+                    DataModificationException.DataMissingException.check(schema.getQName(), actual, leafListModification);
+                }
+                case REMOVE: {
+                    if (resultNodes.contains(leafListModification)) {
+                        resultNodes.remove(leafListModification);
+                    }
+                    break;
+                }
+                case NONE: {
+                    break;
+                }
+                default:
+                    throw new UnsupportedOperationException(String.format("Unable to perform operation: %s on: %s, unknown", operationStack.getCurrentOperation(), schema));
+            }
+
+            operationStack.exitingNode(leafListModification);
+        }
+        return build(schema, resultNodes);
+    }
+
+    private Optional<LeafSetNode<?>> build(LeafListSchemaNode schemaNode, List<LeafSetEntryNode<?>> resultNodes) {
+        if(resultNodes.isEmpty())
+            return Optional.absent();
+
+        ListNodeBuilder<Object, LeafSetEntryNode<Object>> b = Builders.leafSetBuilder(schemaNode);
+        for (LeafSetEntryNode<?> resultNode : resultNodes) {
+            // FIXME: can we do something about this SuppressWarnings?
+            @SuppressWarnings("unchecked")
+            final LeafSetEntryNode<Object> child = (LeafSetEntryNode<Object>) resultNode;
+            b.withChild(child);
+        }
+
+        return Optional.<LeafSetNode<?>>of(b.build());
+    }
+
+    private static boolean contains(Optional<LeafSetNode<?>> actual, LeafSetEntryNode<?> leafListModification) {
+        boolean contains = actual.isPresent();
+        contains &= actual.get().getChild(leafListModification.getIdentifier()).isPresent();
+
+        return contains;
+    }
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/MapEntryNodeModification.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/MapEntryNodeModification.java
new file mode 100644 (file)
index 0000000..64b5399
--- /dev/null
@@ -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.operations;
+
+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.ListSchemaNode;
+
+final class MapEntryNodeModification extends AbstractContainerNodeModification<ListSchemaNode, MapEntryNode> {
+
+    @Override
+    protected QName getQName(ListSchemaNode schema) {
+        return schema.getQName();
+    }
+
+    @Override
+    protected Object findSchemaForChild(ListSchemaNode schema, QName nodeType) {
+        return SchemaUtils.findSchemaForChild(schema, nodeType);
+    }
+
+    @Override
+    protected Object findSchemaForAugment(ListSchemaNode schema, InstanceIdentifier.AugmentationIdentifier childToProcessId) {
+        return SchemaUtils.findSchemaForAugment(schema, childToProcessId.getPossibleChildNames());
+    }
+
+    @Override
+    protected DataContainerNodeBuilder<?, MapEntryNode> getBuilder(ListSchemaNode schema) {
+        return Builders.mapEntryBuilder(schema);
+    }
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/MapNodeModification.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/MapNodeModification.java
new file mode 100644 (file)
index 0000000..9bb5e88
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+* 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.operations;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+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.model.api.ListSchemaNode;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.Maps;
+
+public class MapNodeModification implements Modification<ListSchemaNode, MapNode> {
+
+    public static final MapEntryNodeModification MAP_ENTRY_NODE_MODIFICATION = new MapEntryNodeModification();
+
+    @Override
+    public Optional<MapNode> modify(ListSchemaNode schema, Optional<MapNode> actual,
+                                    Optional<MapNode> modification, OperationStack operationStack) throws DataModificationException {
+
+        // Merge or None operation on parent, leaving actual if modification not present
+        if (modification.isPresent() == false)
+            return actual;
+
+        Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> resultNodes = Maps.newLinkedHashMap();
+        if(actual.isPresent())
+            resultNodes.putAll(mapEntries(actual.get()));
+
+        // TODO implement ordering for modification nodes
+
+        for (MapEntryNode mapEntryModification : modification.get().getValue()) {
+
+            operationStack.enteringNode(mapEntryModification);
+
+            InstanceIdentifier.NodeIdentifierWithPredicates entryKey = mapEntryModification.getIdentifier();
+
+            switch (operationStack.getCurrentOperation()) {
+            case NONE:
+                DataModificationException.DataMissingException.check(schema.getQName(), actual, mapEntryModification);
+            case MERGE: {
+                MapEntryNode mergedListNode;
+                if (resultNodes.containsKey(entryKey)) {
+                    MapEntryNode actualEntry = resultNodes.get(entryKey);
+                    mergedListNode = MAP_ENTRY_NODE_MODIFICATION.modify(schema, Optional.of(actualEntry), Optional.of(mapEntryModification), operationStack).get();
+                } else {
+                    mergedListNode = mapEntryModification;
+                }
+
+                resultNodes.put(mergedListNode.getIdentifier(), mergedListNode);
+                break;
+            }
+            case CREATE: {
+                DataModificationException.DataExistsException.check(schema.getQName(), actual, mapEntryModification);
+            }
+            case REPLACE: {
+                resultNodes.put(entryKey, mapEntryModification);
+                break;
+            }
+            case DELETE: {
+                DataModificationException.DataMissingException.check(schema.getQName(), actual, mapEntryModification);
+            }
+            case REMOVE: {
+                if (resultNodes.containsKey(entryKey)) {
+                    resultNodes.remove(entryKey);
+                }
+                break;
+            }
+            default:
+                throw new UnsupportedOperationException(String.format("Unable to perform operation: %s on: %s, unknown", operationStack.getCurrentOperation(), schema));
+            }
+
+            operationStack.exitingNode(mapEntryModification);
+        }
+        return build(schema, resultNodes);
+    }
+
+    private Optional<MapNode> build(ListSchemaNode schema, Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> resultNodes) {
+        if(resultNodes.isEmpty())
+            return Optional.absent();
+
+        CollectionNodeBuilder<MapEntryNode, MapNode> b = Builders.mapBuilder(schema);
+
+        for (MapEntryNode child : resultNodes.values()) {
+            b.withChild(child);
+        }
+
+        return Optional.of(b.build());
+    }
+
+    private Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapEntries(MapNode mapNode) {
+        Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> mapped = Maps.newLinkedHashMap();
+
+        for (MapEntryNode mapEntryNode : mapNode.getValue()) {
+            mapped.put(mapEntryNode.getIdentifier(), mapEntryNode);
+        }
+
+        return mapped;
+    }
+
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/Modification.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/Modification.java
new file mode 100644 (file)
index 0000000..67ce361
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.operations;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import com.google.common.base.Optional;
+
+/**
+ * Strategy interface for data modification.
+ *
+ * @param <S> SchemaNode type
+ * @param <N> LeafNode type
+ *
+ */
+interface Modification<S, N extends NormalizedNode<?, ?>> {
+
+    Optional<N> modify(S schemaNode, Optional<N> actual, Optional<N> modification, OperationStack operations) throws DataModificationException;
+}
diff --git a/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/OperationStack.java b/yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/OperationStack.java
new file mode 100644 (file)
index 0000000..c4f890d
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * 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.operations;
+
+import java.net.URI;
+import java.util.Deque;
+import java.util.LinkedList;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
+import org.opendaylight.yangtools.yang.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * Tracks netconf operations on nested nodes.
+ */
+final class OperationStack {
+
+    private static final Logger logger = LoggerFactory.getLogger(OperationStack.class);
+    private static final QName OPERATION_NAME = new QName(URI.create("urn:ietf:params:xml:ns:netconf:base:1.0"), "operation");
+
+    private final Deque<ModifyAction> operations = new LinkedList<>();
+
+    public OperationStack(ModifyAction operation) {
+        operations.add(operation);
+    }
+
+    public void enteringNode(Optional<? extends NormalizedNode<?, ?>> modificationNode) {
+        if (modificationNode.isPresent() == false) {
+            return;
+        }
+
+        NormalizedNode<?, ?> modification = modificationNode.get();
+
+        enteringNode(modification);
+    }
+
+    public void enteringNode(NormalizedNode<?, ?> modificationNode) {
+        ModifyAction operation = getOperation(modificationNode);
+        if (operation == null) {
+            return;
+        }
+
+        addOperation(operation);
+    }
+
+    private ModifyAction getOperation(NormalizedNode<?, ?> modificationNode) {
+        if (modificationNode instanceof AttributesContainer == false)
+            return null;
+
+        String operationString = ((AttributesContainer) modificationNode).getAttributes().get(OPERATION_NAME);
+
+        return operationString == null ? null : ModifyAction.fromXmlValue(operationString);
+    }
+
+    private void addOperation(ModifyAction operation) {
+        // Add check for permitted operation
+        operations.add(operation);
+        logger.trace("Operation added {}, {}", operation, this);
+    }
+
+    public ModifyAction getCurrentOperation() {
+        return operations.getLast();
+    }
+
+    public void exitingNode(Optional<? extends NormalizedNode<?, ?>> modificationNode) {
+        if (modificationNode.isPresent() == false) {
+            return;
+        }
+
+        NormalizedNode<?, ?> modification = modificationNode.get();
+
+        exitingNode(modification);
+    }
+
+    public void exitingNode(NormalizedNode<?, ?> modification) {
+        ModifyAction operation = getOperation(modification);
+        if (operation == null) {
+            return;
+        }
+
+        Preconditions.checkState(operations.size() > 1);
+        Preconditions.checkState(operations.peekLast().equals(operation), "Operations mismatch %s, %s",
+                operations.peekLast(), operation);
+
+        ModifyAction removed = operations.removeLast();
+        logger.trace("Operation removed {}, {}", removed, this);
+    }
+
+    @Override
+       public String toString() {
+        return operations.toString();
+    }
+
+}
diff --git a/yang/yang-data-operations/src/test/java/org/opendaylight/yangtools/yang/data/operations/YangDataOperationsNegativeTest.java b/yang/yang-data-operations/src/test/java/org/opendaylight/yangtools/yang/data/operations/YangDataOperationsNegativeTest.java
new file mode 100644 (file)
index 0000000..7cfdce8
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.operations;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+@RunWith(Parameterized.class)
+public class YangDataOperationsNegativeTest extends YangDataOperationsTest{
+
+    private static final String XML_NEG_FOLDER_NAME = "/xmls-negative";
+    private final Class<? extends DataModificationException> expected;
+
+    @Parameterized.Parameters()
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {
+
+                // Container
+                { "/containerTest_noneContainerActualMissing", DataModificationException.DataMissingException.class },
+                { "/containerTest_createContainerActualPresent", DataModificationException.DataExistsException.class },
+                { "/containerTest_deleteContainerActualMissing", DataModificationException.DataMissingException.class },
+                // List
+                { "/listTest_createListActualPresent", DataModificationException.DataExistsException.class },
+                { "/listTest_deleteListActualMissing", DataModificationException.DataMissingException.class },
+                { "/listTest_noneListActualMissing", DataModificationException.DataMissingException.class },
+                // Leaf
+                { "/leafTest_createLeafActualPresent", DataModificationException.DataExistsException.class },
+                { "/leafTest_deleteLeafActualMissing", DataModificationException.DataMissingException.class },
+                // Leaf list
+                { "/leafListTest_createLeafActualPresent", DataModificationException.DataExistsException.class },
+                { "/leafListTest_deleteLeafActualMissing", DataModificationException.DataMissingException.class },
+        });
+    }
+
+    public YangDataOperationsNegativeTest(String testDir, Class<? extends DataModificationException> e) throws Exception {
+        super(testDir);
+        this.expected = e;
+    }
+
+    @Override
+    protected String getXmlFolderName() {
+        return XML_NEG_FOLDER_NAME;
+    }
+
+    @Test
+    public void testModification() throws Exception {
+        try {
+            DataOperations.modify(containerNode,
+                    currentConfig.orNull(), modification.orNull(), modifyAction);
+            fail("Negative test for " + testDirName + " should have failed");
+        } catch (Exception e) {
+            assertEquals(e.getClass(), expected);
+        }
+    }
+}
diff --git a/yang/yang-data-operations/src/test/java/org/opendaylight/yangtools/yang/data/operations/YangDataOperationsTest.java b/yang/yang-data-operations/src/test/java/org/opendaylight/yangtools/yang/data/operations/YangDataOperationsTest.java
new file mode 100644 (file)
index 0000000..5b56f0c
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.operations;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringWriter;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import javax.activation.UnsupportedDataTypeException;
+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.data.api.ModifyAction;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.DomUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.parser.DomToNormalizedNodeParserFactory;
+import org.opendaylight.yangtools.yang.data.impl.schema.transform.dom.serializer.DomFromNormalizedNodeSerializerFactory;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+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 com.google.common.base.Charsets;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.google.common.io.Files;
+
+@RunWith(Parameterized.class)
+public class YangDataOperationsTest {
+
+    public static final String CURRENT_XML_NAME = "/current.xml";
+    public static final String MODIFICATION_XML_NAME = "/merge.xml";
+    private static final String XML_FOLDER_NAME = "/xmls";
+    public static final String RESULT_XML_NAME = "/result.xml";
+    private static final Object OPERATION_XML_NAME = "/defaultOperation.txt";
+
+    protected final ContainerSchemaNode containerNode;
+    protected final String testDirName;
+    protected final Optional<ContainerNode> currentConfig;
+    protected final Optional<ContainerNode> modification;
+    protected final ModifyAction modifyAction;
+
+    @Parameterized.Parameters()
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {
+            // Container
+            { "/containerTest_createContainer" },
+            { "/containerTest_deleteContainer" },
+            { "/containerTest_innerContainerContainer" },
+            { "/containerTest_innerLeavesBaseOperationsContainer" },
+            { "/containerTest_noneContainer" },
+            { "/containerTest_removeContainer"},
+            { "/containerTest_replaceContainer"},
+            { "/containerTest_choiceActualModificationSameCase"},
+            { "/containerTest_choiceActualModificationDifferentCases"},
+            { "/containerTest_choiceActualOneCaseModificationOtherCase"},
+//            LeafList
+            { "/leafListTest" },
+            // List
+            { "/listTest" },
+            // Additional
+            {"/none_NoChange"},
+            {"/listTest_alterInnerValue"}
+        });
+    }
+
+    public YangDataOperationsTest(String testDir) throws Exception {
+        SchemaContext schema = parseTestSchema();
+        containerNode = (ContainerSchemaNode) getSchemaNode(schema, "test", "container");
+        this.testDirName = testDir;
+
+        currentConfig = loadXmlToCompositeNode(getXmlFolderName() + testDirName + CURRENT_XML_NAME);
+        modification = loadXmlToCompositeNode(getXmlFolderName() + testDirName + MODIFICATION_XML_NAME);
+        Preconditions.checkState(modification.isPresent(), "Modification xml has to be present under "
+                + getXmlFolderName() + testDirName + MODIFICATION_XML_NAME);
+
+        modifyAction = loadModifyAction(getXmlFolderName() + testDirName + OPERATION_XML_NAME);
+    }
+
+    protected String getXmlFolderName() {
+        return XML_FOLDER_NAME;
+    }
+
+    // TODO unite testing resources e.g. schemas with yang-data-impl
+    // TODO create extract common testing infrastructure from this and yang-data-impl e.g. xml dom handling
+
+    @Test
+    public void testModification() throws Exception {
+
+        Optional<ContainerNode> result = DataOperations.modify(containerNode,
+                currentConfig.orNull(), modification.orNull(), modifyAction);
+
+        String expectedResultXmlPath = getXmlFolderName() + testDirName + RESULT_XML_NAME;
+        Optional<ContainerNode> expectedResult = loadXmlToCompositeNode(expectedResultXmlPath);
+
+        if (result.isPresent()) {
+            verifyModificationResult(result, expectedResult);
+        } else {
+            junit.framework.Assert.assertNull("Result of modification is empty node, result xml should not be present "
+                    + expectedResultXmlPath, getClass().getResourceAsStream(expectedResultXmlPath));
+        }
+
+    }
+
+    private ModifyAction loadModifyAction(String path) throws Exception {
+        URL resource = getClass().getResource(path);
+        if (resource == null) {
+            return ModifyAction.MERGE;
+        }
+
+        return ModifyAction.fromXmlValue(Files.toString(new File(resource.toURI()), Charsets.UTF_8).trim());
+    }
+
+    private void verifyModificationResult(Optional<ContainerNode> result, Optional<ContainerNode> expectedResult)
+            throws UnsupportedDataTypeException {
+        Assert.assertEquals(
+                String.format(
+                        "Test result %n %s %n Expected %n %s %n",
+                        toString(toDom(result.get())),
+                        toString(toDom(expectedResult.get()))), expectedResult.get(), result.get());
+    }
+
+    private Element toDom(ContainerNode container) {
+        Iterable<Element> a =
+                DomFromNormalizedNodeSerializerFactory.getInstance(newDocument(), DomUtils.defaultValueCodecProvider())
+                .getContainerNodeSerializer().serialize(containerNode, container);
+        return a.iterator().next();
+    }
+
+    private Document newDocument() {
+        try {
+            return BUILDERFACTORY.newDocumentBuilder().newDocument();
+        } catch (ParserConfigurationException e) {
+            throw new RuntimeException("Failed to parse XML document", e);
+        }
+    }
+
+    private Optional<ContainerNode> loadXmlToCompositeNode(String xmlPath) throws IOException, SAXException {
+        InputStream resourceAsStream = getClass().getResourceAsStream(xmlPath);
+        if (resourceAsStream == null) {
+            return Optional.absent();
+        }
+
+        Document currentConfigElement = readXmlToDocument(resourceAsStream);
+        Preconditions.checkNotNull(currentConfigElement);
+
+        return Optional.of(DomToNormalizedNodeParserFactory.getInstance(DomUtils.defaultValueCodecProvider()).getContainerNodeParser().parse(
+                Collections.singletonList(currentConfigElement.getDocumentElement()), containerNode));
+    }
+
+    SchemaContext parseTestSchema() {
+        YangParserImpl yangParserImpl = new YangParserImpl();
+        Set<Module> modules = yangParserImpl.parseYangModelsFromStreams(getTestYangs());
+        return yangParserImpl.resolveSchemaContext(modules);
+    }
+
+    List<InputStream> getTestYangs() {
+
+        return Lists.newArrayList(Collections2.transform(Lists.newArrayList("/schemas/test.yang"),
+                new Function<String, InputStream>() {
+                    @Override
+                    public InputStream apply(String input) {
+                        InputStream resourceAsStream = getClass().getResourceAsStream(input);
+                        Preconditions.checkNotNull(resourceAsStream, "File %s was null", resourceAsStream);
+                        return resourceAsStream;
+                    }
+                }));
+    }
+
+    DataSchemaNode getSchemaNode(SchemaContext context, String moduleName, String childNodeName) {
+        for (Module module : context.getModules()) {
+            if (module.getName().equals(moduleName)) {
+                for (DataSchemaNode dataSchemaNode : module.getChildNodes()) {
+                    if (dataSchemaNode.getQName().getLocalName().equals(childNodeName))
+                        return dataSchemaNode;
+                }
+            }
+        }
+
+        throw new IllegalStateException("Unable to find child node " + childNodeName);
+    }
+
+    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-operations/src/test/resources/schemas/test.yang b/yang/yang-data-operations/src/test/resources/schemas/test.yang
new file mode 100644 (file)
index 0000000..96d2ef6
--- /dev/null
@@ -0,0 +1,152 @@
+// 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 "2013-2-21" {
+        description
+            "Initial revision";
+    }
+
+    grouping listGroup {
+        list list {
+            key "uint32";
+
+            leaf uint32 {
+                type uint32;
+            }
+
+               container containerInList{
+                   leaf uint32 {
+                    type uint32;
+                }
+                leaf uint16 {
+                    type uint16;
+                }
+            }
+        }
+     }
+
+     grouping innerContainerGrouping {
+        container innerContainer {
+            leaf uint16 {
+                type uint16;
+            }
+
+            container innerInnerContainer {
+
+                leaf uint16 {
+                    type uint16;
+                }
+
+                leaf uint32 {
+                    type uint32;
+                }
+            }
+        }
+     }
+
+    container container {
+        leaf uint32 {
+            type uint32;
+        }
+
+        leaf decimal64 {
+            type decimal64 {
+                fraction-digits 2;
+            }
+        }
+
+        leaf boolean {
+            type boolean;
+        }
+
+        leaf binary {
+            type binary;
+        }
+
+        leaf string {
+            type string;
+        }
+
+        uses listGroup;
+        uses innerContainerGrouping;
+
+        choice choice{}
+        choice choice2{}
+
+        leaf-list leafList {
+            type string;
+        }
+
+        leaf identityRef {
+            type identityref {
+                base test-identity;
+            }
+        }
+
+        /* TODO test modification with empty type
+        leaf empty {
+             type empty;
+         }
+         */
+    }
+
+    augment "/container/" {
+        leaf augumentUint32 {
+            type uint32;
+        }
+    }
+
+    augment "/container/choice/" {
+        case test-identity-augument {
+            when "/container/identityRef = 'test-identity'";
+            leaf augumentString1 {
+                type string;
+            }
+
+            leaf augumentInt1 {
+                type uint32;
+            }
+        }
+        case test-identity-augument2 {
+            when "/container/identityRef = 'test-identity2'";
+            leaf augumentString2 {
+                type string;
+            }
+
+            leaf augumentInt2 {
+                type uint32;
+            }
+        }
+    }
+
+    augment "/container/choice2/" {
+        case test-identity-augument {
+            when "/container/identityRef = 'test-identity'";
+            container augumentContainer {
+                leaf augumentStringInAugumentContainer {
+                    type string;
+                }
+            }
+        }
+        case test-identity-augument2 {
+            when "/container/identityRef = 'test-identity2'";
+            list augumentedList {
+                leaf augumentStringInAugumentList {
+                    type string;
+                }
+            }
+        }
+    }
+
+
+    identity test-identity {}
+    identity test-identity2 {
+        base test-identity;
+    }
+
+}
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_choiceModificationMultipleCasesReferenced/current.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_choiceModificationMultipleCasesReferenced/current.xml
new file mode 100644 (file)
index 0000000..83bf5ac
--- /dev/null
@@ -0,0 +1,2 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_choiceModificationMultipleCasesReferenced/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_choiceModificationMultipleCasesReferenced/merge.xml
new file mode 100644 (file)
index 0000000..10580b2
--- /dev/null
@@ -0,0 +1,11 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <identityRef>test-identity2</identityRef>
+
+    <augumentedList>
+        <augumentStringInAugumentList>str1</augumentStringInAugumentList>
+    </augumentedList>
+
+    <augumentContainer>
+    </augumentContainer>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_createContainerActualPresent/current.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_createContainerActualPresent/current.xml
new file mode 100644 (file)
index 0000000..d55c195
--- /dev/null
@@ -0,0 +1,3 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_createContainerActualPresent/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_createContainerActualPresent/merge.xml
new file mode 100644 (file)
index 0000000..79e1306
--- /dev/null
@@ -0,0 +1,4 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+           nc:operation="create">
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_deleteContainerActualMissing/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_deleteContainerActualMissing/merge.xml
new file mode 100644 (file)
index 0000000..41c6caa
--- /dev/null
@@ -0,0 +1,4 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+           nc:operation="delete">
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_noneContainerActualMissing/defaultOperation.txt b/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_noneContainerActualMissing/defaultOperation.txt
new file mode 100644 (file)
index 0000000..c86c3f3
--- /dev/null
@@ -0,0 +1 @@
+none
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_noneContainerActualMissing/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/containerTest_noneContainerActualMissing/merge.xml
new file mode 100644 (file)
index 0000000..2915070
--- /dev/null
@@ -0,0 +1,7 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <!--container is not present and default value is NONE-->
+    <uint32 nc:operation="replace">88</uint32>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_createLeafActualPresent/current.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_createLeafActualPresent/current.xml
new file mode 100644 (file)
index 0000000..860fdb4
--- /dev/null
@@ -0,0 +1,3 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <leafList>currentLeafList1</leafList>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_createLeafActualPresent/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_createLeafActualPresent/merge.xml
new file mode 100644 (file)
index 0000000..c5440f0
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+           nc:operation="merge">
+    <leafList nc:operation="create">currentLeafList1</leafList>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_deleteLeafActualMissing/current.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_deleteLeafActualMissing/current.xml
new file mode 100644 (file)
index 0000000..83bf5ac
--- /dev/null
@@ -0,0 +1,2 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_deleteLeafActualMissing/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/leafListTest_deleteLeafActualMissing/merge.xml
new file mode 100644 (file)
index 0000000..ae24aca
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+           nc:operation="merge">
+    <leafList nc:operation="delete">currentLeafList1</leafList>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_createLeafActualPresent/current.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_createLeafActualPresent/current.xml
new file mode 100644 (file)
index 0000000..f78d3ff
--- /dev/null
@@ -0,0 +1,3 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <uint32>44</uint32>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_createLeafActualPresent/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_createLeafActualPresent/merge.xml
new file mode 100644 (file)
index 0000000..1f0dacf
--- /dev/null
@@ -0,0 +1,7 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+           nc:operation="merge">
+
+    <uint32 nc:operation="create">88</uint32>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_deleteLeafActualMissing/current.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_deleteLeafActualMissing/current.xml
new file mode 100644 (file)
index 0000000..83bf5ac
--- /dev/null
@@ -0,0 +1,2 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_deleteLeafActualMissing/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/leafTest_deleteLeafActualMissing/merge.xml
new file mode 100644 (file)
index 0000000..f78f610
--- /dev/null
@@ -0,0 +1,7 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+           nc:operation="merge">
+
+    <uint32 nc:operation="delete">88</uint32>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_createListActualPresent/current.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_createListActualPresent/current.xml
new file mode 100644 (file)
index 0000000..012271a
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <list>
+        <uint32>1</uint32>
+    </list>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_createListActualPresent/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_createListActualPresent/merge.xml
new file mode 100644 (file)
index 0000000..99f9d2e
--- /dev/null
@@ -0,0 +1,8 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <list nc:operation="create">
+        <uint32>1</uint32>
+    </list>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_deleteListActualMissing/current.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_deleteListActualMissing/current.xml
new file mode 100644 (file)
index 0000000..012271a
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <list>
+        <uint32>1</uint32>
+    </list>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_deleteListActualMissing/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_deleteListActualMissing/merge.xml
new file mode 100644 (file)
index 0000000..8b72242
--- /dev/null
@@ -0,0 +1,8 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <list nc:operation="delete">
+        <uint32>2</uint32>
+    </list>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_noneListActualMissing/current.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_noneListActualMissing/current.xml
new file mode 100644 (file)
index 0000000..012271a
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <list>
+        <uint32>1</uint32>
+    </list>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_noneListActualMissing/defaultOperation.txt b/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_noneListActualMissing/defaultOperation.txt
new file mode 100644 (file)
index 0000000..c86c3f3
--- /dev/null
@@ -0,0 +1 @@
+none
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_noneListActualMissing/merge.xml b/yang/yang-data-operations/src/test/resources/xmls-negative/listTest_noneListActualMissing/merge.xml
new file mode 100644 (file)
index 0000000..dc90cc2
--- /dev/null
@@ -0,0 +1,11 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <list>
+        <uint32>2</uint32>
+        <containerInList nc:operation="create">
+            <uint32>88</uint32>
+        </containerInList>
+    </list>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationDifferentCases/current.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationDifferentCases/current.xml
new file mode 100644 (file)
index 0000000..c5c0159
--- /dev/null
@@ -0,0 +1,4 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <identityRef>test-identity2</identityRef>
+    <augumentString2>augumentString2</augumentString2>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationDifferentCases/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationDifferentCases/merge.xml
new file mode 100644 (file)
index 0000000..6b3a009
--- /dev/null
@@ -0,0 +1,10 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <augumentedList nc:operation="create">
+        <augumentStringInAugumentList>str1</augumentStringInAugumentList>
+    </augumentedList>
+
+    <augumentedList nc:operation="replace">
+        <augumentStringInAugumentList>str2</augumentStringInAugumentList>
+    </augumentedList>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationDifferentCases/result.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationDifferentCases/result.xml
new file mode 100644 (file)
index 0000000..fcacf89
--- /dev/null
@@ -0,0 +1,14 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <identityRef>test-identity2</identityRef>
+
+    <augumentedList>
+        <augumentStringInAugumentList>str1</augumentStringInAugumentList>
+    </augumentedList>
+
+    <augumentedList>
+        <augumentStringInAugumentList>str2</augumentStringInAugumentList>
+    </augumentedList>
+
+    <augumentString2>augumentString2</augumentString2>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationSameCase/current.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationSameCase/current.xml
new file mode 100644 (file)
index 0000000..b9d3c36
--- /dev/null
@@ -0,0 +1,9 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <identityRef>test-identity</identityRef>
+    <augumentString1>augumentString1</augumentString1>
+    <augumentContainer>
+        <augumentStringInAugumentContainer>
+            case1
+        </augumentStringInAugumentContainer>
+    </augumentContainer>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationSameCase/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationSameCase/merge.xml
new file mode 100644 (file)
index 0000000..afc17f8
--- /dev/null
@@ -0,0 +1,9 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <augumentString1>augumentString1</augumentString1>
+
+    <augumentContainer>
+        <augumentStringInAugumentContainer nc:operation="delete">
+        </augumentStringInAugumentContainer>
+    </augumentContainer>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationSameCase/result.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualModificationSameCase/result.xml
new file mode 100644 (file)
index 0000000..3019b6e
--- /dev/null
@@ -0,0 +1,9 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <identityRef>test-identity</identityRef>
+
+    <augumentString1>augumentString1</augumentString1>
+
+    <augumentContainer>
+    </augumentContainer>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualOneCaseModificationOtherCase/current.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualOneCaseModificationOtherCase/current.xml
new file mode 100644 (file)
index 0000000..fd57674
--- /dev/null
@@ -0,0 +1,8 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <identityRef>test-identity</identityRef>
+    <augumentContainer>
+        <augumentStringInAugumentContainer>
+            case1
+        </augumentStringInAugumentContainer>
+    </augumentContainer>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualOneCaseModificationOtherCase/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualOneCaseModificationOtherCase/merge.xml
new file mode 100644 (file)
index 0000000..0e68281
--- /dev/null
@@ -0,0 +1,7 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <identityRef>test-identity2</identityRef>
+    <augumentedList nc:operation="create">
+        <augumentStringInAugumentList>str1</augumentStringInAugumentList>
+    </augumentedList>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualOneCaseModificationOtherCase/result.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_choiceActualOneCaseModificationOtherCase/result.xml
new file mode 100644 (file)
index 0000000..47eae32
--- /dev/null
@@ -0,0 +1,6 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <identityRef>test-identity2</identityRef>
+    <augumentedList>
+        <augumentStringInAugumentList>str1</augumentStringInAugumentList>
+    </augumentedList>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_createContainer/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_createContainer/merge.xml
new file mode 100644 (file)
index 0000000..79aad42
--- /dev/null
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+           nc:operation="create">
+
+    <!--Inner operations under create are ignored-->
+    <uint32 nc:operation="replace">88</uint32>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_createContainer/result.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_createContainer/result.xml
new file mode 100644 (file)
index 0000000..7e29bf0
--- /dev/null
@@ -0,0 +1,3 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <uint32>88</uint32>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_deleteContainer/current.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_deleteContainer/current.xml
new file mode 100644 (file)
index 0000000..36530ed
--- /dev/null
@@ -0,0 +1,3 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <uint32>1</uint32>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_deleteContainer/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_deleteContainer/merge.xml
new file mode 100644 (file)
index 0000000..9c38da8
--- /dev/null
@@ -0,0 +1,3 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete">
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerContainerContainer/current.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerContainerContainer/current.xml
new file mode 100644 (file)
index 0000000..b0959d1
--- /dev/null
@@ -0,0 +1,9 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <innerContainer>
+           <uint16>11</uint16>
+        <innerInnerContainer>
+               <uint32>11</uint32>
+               <uint16>11</uint16>
+        </innerInnerContainer>
+    </innerContainer>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerContainerContainer/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerContainerContainer/merge.xml
new file mode 100644 (file)
index 0000000..0a29154
--- /dev/null
@@ -0,0 +1,12 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <innerContainer nc:operation="merge">
+         <!--TODO integer element has to contain value in order to be parsed even if its being removed-->
+        <uint16 nc:operation="remove">-1</uint16>
+        <innerInnerContainer nc:operation="replace">
+            <uint16>22</uint16>
+        </innerInnerContainer>
+    </innerContainer>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerContainerContainer/result.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerContainerContainer/result.xml
new file mode 100644 (file)
index 0000000..247caf7
--- /dev/null
@@ -0,0 +1,7 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <innerContainer>
+        <innerInnerContainer>
+            <uint16>22</uint16>
+        </innerInnerContainer>
+    </innerContainer>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerLeavesBaseOperationsContainer/current.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerLeavesBaseOperationsContainer/current.xml
new file mode 100644 (file)
index 0000000..97cd725
--- /dev/null
@@ -0,0 +1,10 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <uint32>1</uint32>
+    <augumentUint32>1</augumentUint32>
+    <string>currentString</string>
+    <decimal64>45.1</decimal64>
+    <binary>abcd</binary>
+
+    <identityRef>test-identity</identityRef>
+    <augumentString1>augumentString1</augumentString1>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerLeavesBaseOperationsContainer/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerLeavesBaseOperationsContainer/merge.xml
new file mode 100644 (file)
index 0000000..943836a
--- /dev/null
@@ -0,0 +1,13 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+    <uint32 nc:operation="replace">88</uint32>
+    <augumentUint32>88</augumentUint32>
+    <decimal64 nc:operation="merge">88.1</decimal64>
+    <string nc:operation="delete"></string>
+    <binary nc:operation="remove"></binary>
+    <boolean nc:operation="create">false</boolean>
+
+    <identityRef>test-identity2</identityRef>
+    <augumentString2 nc:operation="create">augumentString2</augumentString2>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerLeavesBaseOperationsContainer/result.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_innerLeavesBaseOperationsContainer/result.xml
new file mode 100644 (file)
index 0000000..618d721
--- /dev/null
@@ -0,0 +1,8 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <uint32>88</uint32>
+    <augumentUint32>88</augumentUint32>
+    <decimal64>88.1</decimal64>
+    <identityRef>test-identity2</identityRef>
+    <boolean>false</boolean>
+    <augumentString2>augumentString2</augumentString2>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/current.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/current.xml
new file mode 100644 (file)
index 0000000..1044367
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+       <uint32>1</uint32>
+       <string>currentString</string>
+    <decimal64>45.1</decimal64>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/defaultOperation.txt b/yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/defaultOperation.txt
new file mode 100644 (file)
index 0000000..c86c3f3
--- /dev/null
@@ -0,0 +1 @@
+none
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/merge.xml
new file mode 100644 (file)
index 0000000..7f047ee
--- /dev/null
@@ -0,0 +1,9 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <uint32 nc:operation="replace">88</uint32>
+    <decimal64 nc:operation="merge">88.1</decimal64>
+    <string>newString</string>
+    <binary >aaa</binary>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/result.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_noneContainer/result.xml
new file mode 100644 (file)
index 0000000..e5b4866
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <uint32>88</uint32>
+    <string>currentString</string>
+    <decimal64>88.1</decimal64>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_removeContainer/current.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_removeContainer/current.xml
new file mode 100644 (file)
index 0000000..36530ed
--- /dev/null
@@ -0,0 +1,3 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <uint32>1</uint32>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_removeContainer/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_removeContainer/merge.xml
new file mode 100644 (file)
index 0000000..8a03228
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+           nc:operation="remove"
+           >
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_replaceContainer/current.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_replaceContainer/current.xml
new file mode 100644 (file)
index 0000000..510f5ee
--- /dev/null
@@ -0,0 +1,4 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+       <uint32>1</uint32>
+       <string>currentString</string>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_replaceContainer/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_replaceContainer/merge.xml
new file mode 100644 (file)
index 0000000..33421a6
--- /dev/null
@@ -0,0 +1,7 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"
+           nc:operation="replace">
+    <!--Inner strategies under replace are ignored-->
+    <uint32 nc:operation="remove">88</uint32>
+    <string nc:operation="delete">string</string>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/containerTest_replaceContainer/result.xml b/yang/yang-data-operations/src/test/resources/xmls/containerTest_replaceContainer/result.xml
new file mode 100644 (file)
index 0000000..1cea85f
--- /dev/null
@@ -0,0 +1,4 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <uint32>88</uint32>
+    <string>string</string>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/leafListTest/current.xml b/yang/yang-data-operations/src/test/resources/xmls/leafListTest/current.xml
new file mode 100644 (file)
index 0000000..581faf9
--- /dev/null
@@ -0,0 +1,6 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+       <leafList>currentLeafList1</leafList>
+       <leafList>currentLeafList2</leafList>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/leafListTest/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/leafListTest/merge.xml
new file mode 100644 (file)
index 0000000..39a9d22
--- /dev/null
@@ -0,0 +1,10 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <leafList nc:operation="delete">currentLeafList1</leafList>
+    <leafList nc:operation="remove">random</leafList>
+    <leafList nc:operation="create">currentLeafList3</leafList>
+    <leafList nc:operation="replace">currentLeafList4</leafList>
+    <leafList nc:operation="merge">currentLeafList5</leafList>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/leafListTest/result.xml b/yang/yang-data-operations/src/test/resources/xmls/leafListTest/result.xml
new file mode 100644 (file)
index 0000000..5a7e98c
--- /dev/null
@@ -0,0 +1,8 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+    <leafList>currentLeafList2</leafList>
+    <leafList>currentLeafList3</leafList>
+    <leafList>currentLeafList4</leafList>
+    <leafList>currentLeafList5</leafList>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/listTest/current.xml b/yang/yang-data-operations/src/test/resources/xmls/listTest/current.xml
new file mode 100644 (file)
index 0000000..15334b8
--- /dev/null
@@ -0,0 +1,31 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+
+       <list>
+        <uint32>1</uint32>
+        <containerInList>
+            <uint32>32</uint32>
+        </containerInList>
+       </list>
+       <list>
+        <uint32>2</uint32>
+        <containerInList>
+            <uint32>32</uint32>
+        </containerInList>
+       </list>
+       <list>
+        <uint32>6</uint32>
+        <containerInList>
+            <uint32>32</uint32>
+        </containerInList>
+       </list>
+       <list>
+        <uint32>3</uint32>
+       </list>
+       <list>
+        <uint32>4</uint32>
+       </list>
+       <list>
+        <uint32>5</uint32>
+       </list>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/listTest/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/listTest/merge.xml
new file mode 100644 (file)
index 0000000..c4dc7ee
--- /dev/null
@@ -0,0 +1,34 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <list nc:operation="merge">
+        <uint32>1</uint32>
+        <containerInList>
+            <uint32>88</uint32>
+        </containerInList>
+    </list>
+    <list nc:operation="merge">
+        <uint32>2</uint32>
+        <containerInList nc:operation="replace">
+        </containerInList>
+    </list>
+    <list nc:operation="delete">
+        <uint32>3</uint32>
+    </list>
+    <list nc:operation="remove">
+        <uint32>4</uint32>
+    </list>
+    <list>
+        <uint32>5</uint32>
+        <containerInList nc:operation="create">
+            <uint32>88</uint32>
+        </containerInList>
+    </list>
+    <list>
+        <uint32>6</uint32>
+        <containerInList>
+            <uint32 nc:operation="delete">-1</uint32>
+        </containerInList>
+    </list>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/listTest/result.xml b/yang/yang-data-operations/src/test/resources/xmls/listTest/result.xml
new file mode 100644 (file)
index 0000000..f2e39f3
--- /dev/null
@@ -0,0 +1,25 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <list>
+        <uint32>1</uint32>
+        <containerInList>
+            <uint32>88</uint32>
+        </containerInList>
+    </list>
+    <list>
+        <uint32>2</uint32>
+        <containerInList>
+        </containerInList>
+    </list>
+    <list>
+        <uint32>6</uint32>
+        <containerInList>
+        </containerInList>
+    </list>
+    <list>
+        <uint32>5</uint32>
+        <containerInList>
+            <uint32>88</uint32>
+        </containerInList>
+    </list>
+
+</container>
diff --git a/yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/current.xml b/yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/current.xml
new file mode 100644 (file)
index 0000000..c2aac04
--- /dev/null
@@ -0,0 +1,9 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+       <list>
+        <uint32>1</uint32>
+        <containerInList>
+            <uint32>32</uint32>
+            <uint16>32</uint16>
+        </containerInList>
+       </list>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/defaultOperation.txt b/yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/defaultOperation.txt
new file mode 100644 (file)
index 0000000..c86c3f3
--- /dev/null
@@ -0,0 +1 @@
+none
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/merge.xml
new file mode 100644 (file)
index 0000000..8bf933d
--- /dev/null
@@ -0,0 +1,11 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <list>
+        <uint32>1</uint32>
+        <containerInList>
+            <uint16 nc:operation="delete">88</uint16>
+        </containerInList>
+    </list>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/result.xml b/yang/yang-data-operations/src/test/resources/xmls/listTest_alterInnerValue/result.xml
new file mode 100644 (file)
index 0000000..31bd961
--- /dev/null
@@ -0,0 +1,8 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <list>
+        <uint32>1</uint32>
+        <containerInList>
+            <uint32>32</uint32>
+        </containerInList>
+    </list>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/none_NoChange/current.xml b/yang/yang-data-operations/src/test/resources/xmls/none_NoChange/current.xml
new file mode 100644 (file)
index 0000000..1044367
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+       <uint32>1</uint32>
+       <string>currentString</string>
+    <decimal64>45.1</decimal64>
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/none_NoChange/defaultOperation.txt b/yang/yang-data-operations/src/test/resources/xmls/none_NoChange/defaultOperation.txt
new file mode 100644 (file)
index 0000000..c86c3f3
--- /dev/null
@@ -0,0 +1 @@
+none
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/none_NoChange/merge.xml b/yang/yang-data-operations/src/test/resources/xmls/none_NoChange/merge.xml
new file mode 100644 (file)
index 0000000..9836290
--- /dev/null
@@ -0,0 +1,9 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test"
+           xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0">
+
+    <uint32>88</uint32>
+    <decimal64>88.1</decimal64>
+    <string>newString</string>
+    <binary >aaa</binary>
+
+</container>
\ No newline at end of file
diff --git a/yang/yang-data-operations/src/test/resources/xmls/none_NoChange/result.xml b/yang/yang-data-operations/src/test/resources/xmls/none_NoChange/result.xml
new file mode 100644 (file)
index 0000000..fb0e5f7
--- /dev/null
@@ -0,0 +1,5 @@
+<container xmlns="urn:opendaylight:params:xml:ns:yang:controller:test">
+    <uint32>1</uint32>
+    <string>currentString</string>
+    <decimal64>45.1</decimal64>
+</container>
\ No newline at end of file
index 1dfaedea1b34dc5a3e98076b8c6dacb7591a730c..5cf126d0a253de5055fadcf41fc0cf02f14389b5 100644 (file)
             <groupId>org.opendaylight.yangtools</groupId>
             <artifactId>yang-binding</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.eclipse.xtend</groupId>
-            <artifactId>org.eclipse.xtend.lib</artifactId>
-        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
 
     <build>
         <plugins>
-            <plugin>
-                <groupId>org.eclipse.xtend</groupId>
-                <artifactId>xtend-maven-plugin</artifactId>
-            </plugin>
             <plugin>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
@@ -56,4 +48,5 @@
             </plugin>
         </plugins>
     </build>
+
 </project>
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java
new file mode 100644 (file)
index 0000000..14f4950
--- /dev/null
@@ -0,0 +1,783 @@
+/*
+ * 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.model.util;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+import com.google.common.base.Preconditions;
+
+import java.util.Set;
+
+/**
+ * The Schema Context Util contains support methods for searching through Schema
+ * Context modules for specified schema nodes via Schema Path or Revision Aware
+ * XPath. The Schema Context Util is designed as mixin, so it is not
+ * instantiable.
+ *
+ */
+public class SchemaContextUtil {
+
+    private SchemaContextUtil() {
+    }
+
+    /**
+     * Method attempts to find DataSchemaNode in Schema Context via specified
+     * Schema Path. The returned DataSchemaNode from method will be the node at
+     * the end of the SchemaPath. If the DataSchemaNode is not present in the
+     * Schema Context the method will return <code>null</code>. <br>
+     * In case that Schema Context or Schema Path are not specified correctly
+     * (i.e. contains <code>null</code> values) the method will return
+     * IllegalArgumentException.
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context
+     *            Schema Context
+     * @param schemaPath
+     *            Schema Path to search for
+     * @return SchemaNode from the end of the Schema Path or <code>null</code>
+     *         if the Node is not present.
+     */
+    public static SchemaNode findDataSchemaNode(SchemaContext context, SchemaPath schemaPath) {
+        Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
+        Preconditions.checkArgument(schemaPath != null, "Schema Path reference cannot be NULL");
+        List<QName> prefixedPath = (schemaPath.getPath());
+        if (prefixedPath != null) {
+            return findNodeInSchemaContext(context, prefixedPath);
+        }
+        return null;
+    }
+
+    /**
+     * Method attempts to find DataSchemaNode inside of provided Schema Context
+     * and Yang Module accordingly to Non-conditional Revision Aware XPath. The
+     * specified Module MUST be present in Schema Context otherwise the
+     * operation would fail and return <code>null</code>. <br>
+     * The Revision Aware XPath MUST be specified WITHOUT the conditional
+     * statement (i.e. without [cond]) in path, because in this state the Schema
+     * Context is completely unaware of data state and will be not able to
+     * properly resolve XPath. If the XPath contains condition the method will
+     * return IllegalArgumentException. <br>
+     * In case that Schema Context or Module or Revision Aware XPath contains
+     * <code>null</code> references the method will throw
+     * IllegalArgumentException <br>
+     * If the Revision Aware XPath is correct and desired Data Schema Node is
+     * present in Yang module or in depending module in Schema Context the
+     * method will return specified Data Schema Node, otherwise the operation
+     * will fail and method will return <code>null</code>.
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context
+     *            Schema Context
+     * @param module
+     *            Yang Module
+     * @param nonCondXPath
+     *            Non Conditional Revision Aware XPath
+     * @return Returns Data Schema Node for specified Schema Context for given
+     *         Non-conditional Revision Aware XPath, or <code>null</code> if the
+     *         DataSchemaNode is not present in Schema Context.
+     */
+    public static SchemaNode findDataSchemaNode(SchemaContext context, Module module, RevisionAwareXPath nonCondXPath) {
+        Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
+        Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
+        Preconditions.checkArgument(nonCondXPath != null, "Non Conditional Revision Aware XPath cannot be NULL");
+
+        String strXPath = nonCondXPath.toString();
+        if (strXPath != null) {
+            if (strXPath.contains("[")) {
+                throw new IllegalArgumentException("Revision Aware XPath cannot contains condition");
+            }
+            if (nonCondXPath.isAbsolute()) {
+                List<QName> qnamedPath = xpathToQNamePath(context, module, strXPath);
+                if (qnamedPath != null) {
+                    return findNodeInSchemaContext(context, qnamedPath);
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Method attempts to find DataSchemaNode inside of provided Schema Context
+     * and Yang Module accordingly to Non-conditional relative Revision Aware
+     * XPath. The specified Module MUST be present in Schema Context otherwise
+     * the operation would fail and return <code>null</code>. <br>
+     * The relative Revision Aware XPath MUST be specified WITHOUT the
+     * conditional statement (i.e. without [cond]) in path, because in this
+     * state the Schema Context is completely unaware of data state and will be
+     * not able to properly resolve XPath. If the XPath contains condition the
+     * method will return IllegalArgumentException. <br>
+     * The Actual Schema Node MUST be specified correctly because from this
+     * Schema Node will search starts. If the Actual Schema Node is not correct
+     * the operation will simply fail, because it will be unable to find desired
+     * DataSchemaNode. <br>
+     * In case that Schema Context or Module or Actual Schema Node or relative
+     * Revision Aware XPath contains <code>null</code> references the method
+     * will throw IllegalArgumentException <br>
+     * If the Revision Aware XPath doesn't have flag
+     * <code>isAbsolute == false</code> the method will throw
+     * IllegalArgumentException. <br>
+     * If the relative Revision Aware XPath is correct and desired Data Schema
+     * Node is present in Yang module or in depending module in Schema Context
+     * the method will return specified Data Schema Node, otherwise the
+     * operation will fail and method will return <code>null</code>.
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context
+     *            Schema Context
+     * @param module
+     *            Yang Module
+     * @param actualSchemaNode
+     *            Actual Schema Node
+     * @param relativeXPath
+     *            Relative Non Conditional Revision Aware XPath
+     * @return DataSchemaNode if is present in specified Schema Context for
+     *         given relative Revision Aware XPath, otherwise will return
+     *         <code>null</code>.
+     */
+    public static SchemaNode findDataSchemaNodeForRelativeXPath(SchemaContext context, Module module,
+            SchemaNode actualSchemaNode, RevisionAwareXPath relativeXPath) {
+        Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
+        Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
+        Preconditions.checkArgument(actualSchemaNode != null, "Actual Schema Node reference cannot be NULL");
+        Preconditions.checkArgument(relativeXPath != null, "Non Conditional Revision Aware XPath cannot be NULL");
+        Preconditions.checkState(!relativeXPath.isAbsolute(),
+                "Revision Aware XPath MUST be relative i.e. MUST contains ../, "
+                        + "for non relative Revision Aware XPath use findDataSchemaNode method");
+
+        SchemaPath actualNodePath = actualSchemaNode.getPath();
+        if (actualNodePath != null) {
+            List<QName> qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualSchemaNode);
+
+            if (qnamePath != null) {
+                return findNodeInSchemaContext(context, qnamePath);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns parent Yang Module for specified Schema Context in which Schema
+     * Node is declared. If the Schema Node is not present in Schema Context the
+     * operation will return <code>null</code>. <br>
+     * If Schema Context or Schema Node contains <code>null</code> references
+     * the method will throw IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context
+     *            Schema Context
+     * @param schemaNode
+     *            Schema Node
+     * @return Yang Module for specified Schema Context and Schema Node, if
+     *         Schema Node is NOT present, the method will returns
+     *         <code>null</code>
+     */
+    public static Module findParentModule(SchemaContext context, SchemaNode schemaNode) {
+        Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL!");
+        Preconditions.checkArgument(schemaNode != null, "Schema Node cannot be NULL!");
+        Preconditions.checkState(schemaNode.getPath() != null, "Schema Path for Schema Node is not "
+                + "set properly (Schema Path is NULL)");
+
+        List<QName> qnamedPath = schemaNode.getPath().getPath();
+        if (qnamedPath == null || qnamedPath.isEmpty()) {
+            throw new IllegalStateException("Schema Path contains invalid state of path parts."
+                    + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name"
+                    + "of path.");
+        }
+        QName qname = qnamedPath.get(qnamedPath.size() - 1);
+        return context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision());
+    }
+
+    public static SchemaNode findNodeInSchemaContext(SchemaContext context, List<QName> path) {
+        QName current = path.get(0);
+        Module module = context.findModuleByNamespaceAndRevision(current.getNamespace(), current.getRevision());
+        if (module == null)
+            return null;
+        return findNodeInModule(module, path);
+    }
+
+    public static GroupingDefinition findGrouping(SchemaContext context, Module module, List<QName> path) {
+        QName first = path.get(0);
+        Module m = context.findModuleByNamespace(first.getNamespace()).iterator().next();
+        DataNodeContainer currentParent = m;
+        for (QName qname : path) {
+            boolean found = false;
+            DataNodeContainer node = (DataNodeContainer) currentParent.getDataChildByName(qname.getLocalName());
+            if (node == null) {
+                Set<GroupingDefinition> groupings = currentParent.getGroupings();
+                for (GroupingDefinition gr : groupings) {
+                    if (gr.getQName().getLocalName().equals(qname.getLocalName())) {
+                        currentParent = gr;
+                        found = true;
+                    }
+                }
+            } else {
+                found = true;
+                currentParent = node;
+            }
+            if (!found) {
+                throw new IllegalArgumentException("Failed to find referenced grouping: " + path + "("
+                        + qname.getLocalName() + ")");
+            }
+        }
+
+        return (GroupingDefinition) currentParent;
+    }
+
+    private static SchemaNode findNodeInModule(Module module, List<QName> path) {
+        QName current = path.get(0);
+        SchemaNode node = module.getDataChildByName(current);
+        if (node != null)
+            return findNode((DataSchemaNode) node, nextLevel(path));
+        node = getRpcByName(module, current);
+        if (node != null)
+            return findNodeInRpc((RpcDefinition) node, nextLevel(path));
+        node = getNotificationByName(module, current);
+        if (node != null)
+            return findNodeInNotification((NotificationDefinition) node, nextLevel(path));
+        node = getGroupingByName(module, current);
+        if (node != null)
+            return findNodeInGrouping((GroupingDefinition) node, nextLevel(path));
+        return node;
+    }
+
+    private static SchemaNode findNodeInGrouping(GroupingDefinition grouping, List<QName> path) {
+        if (path.isEmpty())
+            return grouping;
+        QName current = path.get(0);
+        DataSchemaNode node = grouping.getDataChildByName(current);
+        if (node != null)
+            return findNode(node, nextLevel(path));
+        return null;
+    }
+
+    private static SchemaNode findNodeInRpc(RpcDefinition rpc, List<QName> path) {
+        if (path.isEmpty())
+            return rpc;
+        QName current = path.get(0);
+        switch (current.getLocalName()) {
+        case "input":
+            return findNode(rpc.getInput(), nextLevel(path));
+        case "output":
+            return findNode(rpc.getOutput(), nextLevel(path));
+        }
+        return null;
+    }
+
+    private static SchemaNode findNodeInNotification(NotificationDefinition rpc, List<QName> path) {
+        if (path.isEmpty())
+            return rpc;
+        QName current = path.get(0);
+        DataSchemaNode node = rpc.getDataChildByName(current);
+        if (node != null)
+            return findNode(node, nextLevel(path));
+        return null;
+    }
+
+    private static SchemaNode findNode(ChoiceNode parent, List<QName> path) {
+        if (path.isEmpty())
+            return parent;
+        QName current = path.get(0);
+        ChoiceCaseNode node = parent.getCaseNodeByName(current);
+        if (node != null)
+            return findNodeInCase(node, nextLevel(path));
+        return null;
+    }
+
+    private static SchemaNode findNode(ContainerSchemaNode parent, List<QName> path) {
+        if (path.isEmpty())
+            return parent;
+        QName current = path.get(0);
+        DataSchemaNode node = parent.getDataChildByName(current);
+        if (node != null)
+            return findNode(node, nextLevel(path));
+        return null;
+    }
+
+    private static SchemaNode findNode(ListSchemaNode parent, List<QName> path) {
+        if (path.isEmpty())
+            return parent;
+        QName current = path.get(0);
+        DataSchemaNode node = parent.getDataChildByName(current);
+        if (node != null)
+            return findNode(node, nextLevel(path));
+        return null;
+    }
+
+    private static SchemaNode findNode(DataSchemaNode parent, List<QName> path) {
+        SchemaNode result = null;
+        if (path.isEmpty()) {
+            result = parent;
+        } else {
+            if (parent instanceof ContainerSchemaNode) {
+                result = findNode((ContainerSchemaNode) parent, path);
+            } else if (parent instanceof ListSchemaNode) {
+                result = findNode((ListSchemaNode) parent, path);
+            } else if (parent instanceof ChoiceNode) {
+                result = findNode((ChoiceNode) parent, path);
+            } else {
+                throw new IllegalArgumentException("Path nesting violation");
+            }
+        }
+        return result;
+    }
+
+    public static SchemaNode findNodeInCase(ChoiceCaseNode parent, List<QName> path) {
+        if (path.isEmpty())
+            return parent;
+        QName current = path.get(0);
+        DataSchemaNode node = parent.getDataChildByName(current);
+        if (node != null)
+            return findNode(node, nextLevel(path));
+        return null;
+    }
+
+    public static RpcDefinition getRpcByName(Module module, QName name) {
+        for (RpcDefinition rpc : module.getRpcs()) {
+            if (rpc.getQName().equals(name)) {
+                return rpc;
+            }
+        }
+        return null;
+    }
+
+    private static List<QName> nextLevel(List<QName> path) {
+        return path.subList(1, path.size());
+    }
+
+    public static NotificationDefinition getNotificationByName(Module module, QName name) {
+        for (NotificationDefinition notification : module.getNotifications()) {
+            if (notification.getQName().equals(name)) {
+                return notification;
+            }
+        }
+        return null;
+    }
+
+    public static GroupingDefinition getGroupingByName(Module module, QName name) {
+        for (GroupingDefinition grouping : module.getGroupings()) {
+            if (grouping.getQName().equals(name)) {
+                return grouping;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Utility method which search for original node defined in grouping.
+     *
+     * @param node
+     * @return
+     */
+    public static DataSchemaNode findOriginal(DataSchemaNode node, SchemaContext ctx) {
+        DataSchemaNode result = findCorrectTargetFromGrouping(node, ctx);
+        if (result == null) {
+            result = findCorrectTargetFromAugment(node, ctx);
+            if (result != null) {
+                if (result.isAddedByUses()) {
+                    result = findOriginal(result, ctx);
+                }
+            }
+        }
+        return result;
+    }
+
+    private static DataSchemaNode findCorrectTargetFromGrouping(DataSchemaNode node, SchemaContext ctx) {
+        if (node.getPath().getPath().size() == 1) {
+            // uses is under module statement
+            Module m = findParentModule(ctx, node);
+            DataSchemaNode result = null;
+            for (UsesNode u : m.getUses()) {
+                SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPath());
+                if (!(targetGrouping instanceof GroupingDefinition)) {
+                    throw new IllegalArgumentException("Failed to generate code for augment in " + u);
+                }
+                GroupingDefinition gr = (GroupingDefinition) targetGrouping;
+                result = gr.getDataChildByName(node.getQName().getLocalName());
+            }
+            if (result == null) {
+                throw new IllegalArgumentException("Failed to generate code for augment");
+            }
+            return result;
+        } else {
+            DataSchemaNode result = null;
+            QName currentName = node.getQName();
+            List<QName> tmpPath = new ArrayList<>();
+            Object parent = null;
+
+            SchemaPath sp = node.getPath();
+            List<QName> names = sp.getPath();
+            List<QName> newNames = new ArrayList<>(names);
+            newNames.remove(newNames.size() - 1);
+            SchemaPath newSp = new SchemaPath(newNames, sp.isAbsolute());
+            parent = findDataSchemaNode(ctx, newSp);
+
+            do {
+                tmpPath.add(currentName);
+                if (parent instanceof DataNodeContainer) {
+                    DataNodeContainer dataNodeParent = (DataNodeContainer) parent;
+                    for (UsesNode u : dataNodeParent.getUses()) {
+                        if (result == null) {
+                            result = getResultFromUses(u, currentName.getLocalName(), ctx);
+                        }
+                    }
+                }
+                if (result == null) {
+                    currentName = ((SchemaNode) parent).getQName();
+                    if (parent instanceof SchemaNode) {
+                        SchemaPath nodeSp = ((SchemaNode) parent).getPath();
+                        List<QName> nodeNames = nodeSp.getPath();
+                        List<QName> nodeNewNames = new ArrayList<>(nodeNames);
+                        nodeNewNames.remove(nodeNewNames.size() - 1);
+                        if (nodeNewNames.isEmpty()) {
+                            parent = getParentModule((SchemaNode) parent, ctx);
+                        } else {
+                            SchemaPath nodeNewSp = new SchemaPath(nodeNewNames, nodeSp.isAbsolute());
+                            parent = findDataSchemaNode(ctx, nodeNewSp);
+                        }
+                    } else {
+                        throw new IllegalArgumentException("Failed to generate code for augment");
+                    }
+                }
+            } while (result == null && !(parent instanceof Module));
+
+            if (result != null) {
+                result = getTargetNode(tmpPath, result, ctx);
+            }
+            return result;
+        }
+    }
+
+    private static DataSchemaNode findCorrectTargetFromAugment(DataSchemaNode node, SchemaContext ctx) {
+        if (!node.isAugmenting()) {
+            return null;
+        }
+
+        QName currentName = node.getQName();
+        Object currentNode = node;
+        Object parent = node;
+        List<QName> tmpPath = new ArrayList<QName>();
+        List<SchemaNode> tmpTree = new ArrayList<SchemaNode>();
+
+        AugmentationSchema augment = null;
+        do {
+            SchemaPath sp = ((SchemaNode) parent).getPath();
+            List<QName> names = sp.getPath();
+            List<QName> newNames = new ArrayList<>(names);
+            newNames.remove(newNames.size() - 1);
+            SchemaPath newSp = new SchemaPath(newNames, sp.isAbsolute());
+            parent = findDataSchemaNode(ctx, newSp);
+            if (parent instanceof AugmentationTarget) {
+                tmpPath.add(currentName);
+                tmpTree.add((SchemaNode) currentNode);
+                augment = findNodeInAugment(((AugmentationTarget) parent).getAvailableAugmentations(), currentName);
+                if (augment == null) {
+                    currentName = ((DataSchemaNode) parent).getQName();
+                    currentNode = parent;
+                }
+            }
+        } while (((DataSchemaNode) parent).isAugmenting() && augment == null);
+
+        if (augment == null) {
+            return null;
+        } else {
+            Collections.reverse(tmpPath);
+            Collections.reverse(tmpTree);
+            Object actualParent = augment;
+            DataSchemaNode result = null;
+            for (QName name : tmpPath) {
+                if (actualParent instanceof DataNodeContainer) {
+                    result = ((DataNodeContainer) actualParent).getDataChildByName(name.getLocalName());
+                    actualParent = ((DataNodeContainer) actualParent).getDataChildByName(name.getLocalName());
+                } else {
+                    if (actualParent instanceof ChoiceNode) {
+                        result = ((ChoiceNode) actualParent).getCaseNodeByName(name.getLocalName());
+                        actualParent = ((ChoiceNode) actualParent).getCaseNodeByName(name.getLocalName());
+                    }
+                }
+            }
+
+            if (result.isAddedByUses()) {
+                result = findCorrectTargetFromAugmentGrouping(result, augment, tmpTree, ctx);
+            }
+
+            return result;
+        }
+    }
+
+    private static DataSchemaNode getResultFromUses(UsesNode u, String currentName, SchemaContext ctx) {
+        SchemaNode targetGrouping = findNodeInSchemaContext(ctx, u.getGroupingPath().getPath());
+        if (!(targetGrouping instanceof GroupingDefinition)) {
+            throw new IllegalArgumentException("Failed to generate code for augment in " + u);
+        }
+        GroupingDefinition gr = (GroupingDefinition) targetGrouping;
+        return gr.getDataChildByName(currentName);
+    }
+
+    private static Module getParentModule(SchemaNode node, SchemaContext ctx) {
+        QName qname = node.getPath().getPath().get(0);
+        URI namespace = qname.getNamespace();
+        Date revision = qname.getRevision();
+        return ctx.findModuleByNamespaceAndRevision(namespace, revision);
+    }
+
+    private static DataSchemaNode getTargetNode(List<QName> tmpPath, DataSchemaNode node, SchemaContext ctx) {
+        DataSchemaNode result = node;
+        if (tmpPath.size() == 1) {
+            if (result != null && result.isAddedByUses()) {
+                result = findOriginal(result, ctx);
+            }
+            return result;
+        } else {
+            DataSchemaNode newParent = result;
+            Collections.reverse(tmpPath);
+
+            tmpPath.remove(0);
+            for (QName name : tmpPath) {
+                // searching by local name is must, because node has different
+                // namespace in its original location
+                if (newParent == null) {
+                    break;
+                }
+                if (newParent instanceof DataNodeContainer) {
+                    newParent = ((DataNodeContainer) newParent).getDataChildByName(name.getLocalName());
+                } else {
+                    newParent = ((ChoiceNode) newParent).getCaseNodeByName(name.getLocalName());
+                }
+            }
+            if (newParent != null && newParent.isAddedByUses()) {
+                newParent = findOriginal(newParent, ctx);
+            }
+            return newParent;
+        }
+    }
+
+    private static AugmentationSchema findNodeInAugment(Collection<AugmentationSchema> augments, QName name) {
+        for (AugmentationSchema augment : augments) {
+            DataSchemaNode node = augment.getDataChildByName(name);
+            if (node != null) {
+                return augment;
+            }
+        }
+        return null;
+    }
+
+    private static DataSchemaNode findCorrectTargetFromAugmentGrouping(DataSchemaNode node,
+            AugmentationSchema parentNode, List<SchemaNode> dataTree, SchemaContext ctx) {
+
+        DataSchemaNode result = null;
+        QName currentName = node.getQName();
+        List<QName> tmpPath = new ArrayList<>();
+        tmpPath.add(currentName);
+        int i = 1;
+        Object parent = null;
+
+        do {
+            if (dataTree.size() < 2 || dataTree.size() == i) {
+                parent = parentNode;
+            } else {
+                parent = dataTree.get(dataTree.size() - (i + 1));
+                tmpPath.add(((SchemaNode) parent).getQName());
+            }
+
+            if (parent instanceof DataNodeContainer) {
+                DataNodeContainer dataNodeParent = (DataNodeContainer) parent;
+                for (UsesNode u : dataNodeParent.getUses()) {
+                    if (result == null) {
+                        result = getResultFromUses(u, currentName.getLocalName(), ctx);
+                    }
+                }
+            }
+
+            if (result == null) {
+                i = i + 1;
+                currentName = ((SchemaNode) parent).getQName();
+            }
+        } while (result == null);
+
+        if (result != null) {
+            result = getTargetNode(tmpPath, result, ctx);
+        }
+        return result;
+    }
+
+    /**
+     * Transforms string representation of XPath to Queue of QNames. The XPath
+     * is split by "/" and for each part of XPath is assigned correct module in
+     * Schema Path. <br>
+     * If Schema Context, Parent Module or XPath string contains
+     * <code>null</code> values, the method will throws IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context
+     *            Schema Context
+     * @param parentModule
+     *            Parent Module
+     * @param xpath
+     *            XPath String
+     * @return return a list of QName
+     */
+    private static List<QName> xpathToQNamePath(SchemaContext context, Module parentModule, String xpath) {
+        Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
+        Preconditions.checkArgument(parentModule != null, "Parent Module reference cannot be NULL");
+        Preconditions.checkArgument(xpath != null, "XPath string reference cannot be NULL");
+
+        List<QName> path = new LinkedList<QName>();
+        String[] prefixedPath = xpath.split("/");
+        for (String pathComponent : prefixedPath) {
+            if (!pathComponent.isEmpty()) {
+                path.add(stringPathPartToQName(context, parentModule, pathComponent));
+            }
+        }
+        return path;
+    }
+
+    /**
+     * Transforms part of Prefixed Path as java String to QName. <br>
+     * If the string contains module prefix separated by ":" (i.e.
+     * mod:container) this module is provided from from Parent Module list of
+     * imports. If the Prefixed module is present in Schema Context the QName
+     * can be constructed. <br>
+     * If the Prefixed Path Part does not contains prefix the Parent's Module
+     * namespace is taken for construction of QName. <br>
+     * If Schema Context, Parent Module or Prefixed Path Part refers to
+     * <code>null</code> the method will throw IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context
+     *            Schema Context
+     * @param parentModule
+     *            Parent Module
+     * @param prefixedPathPart
+     *            Prefixed Path Part string
+     * @return QName from prefixed Path Part String.
+     */
+    private static QName stringPathPartToQName(SchemaContext context, Module parentModule, String prefixedPathPart) {
+        Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
+        Preconditions.checkArgument(parentModule != null, "Parent Module reference cannot be NULL");
+        Preconditions.checkArgument(prefixedPathPart != null, "Prefixed Path Part cannot be NULL!");
+
+        if (prefixedPathPart.contains(":")) {
+            String[] prefixedName = prefixedPathPart.split(":");
+            Module module = resolveModuleForPrefix(context, parentModule, prefixedName[0]);
+            if (module == null) {
+                throw new IllegalArgumentException("Failed to resolve xpath: no module found for prefix "
+                        + prefixedName[0] + " in module " + parentModule.getName());
+            } else {
+                return new QName(module.getNamespace(), module.getRevision(), prefixedName[1]);
+            }
+        } else {
+            return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
+        }
+    }
+
+    /**
+     * Method will attempt to resolve and provide Module reference for specified
+     * module prefix. Each Yang module could contains multiple imports which
+     * MUST be associated with corresponding module prefix. The method simply
+     * looks into module imports and returns the module that is bounded with
+     * specified prefix. If the prefix is not present in module or the prefixed
+     * module is not present in specified Schema Context, the method will return
+     * <code>null</code>. <br>
+     * If String prefix is the same as prefix of the specified Module the
+     * reference to this module is returned. <br>
+     * If Schema Context, Module or Prefix are referring to <code>null</code>
+     * the method will return IllegalArgumentException
+     *
+     * @throws IllegalArgumentException
+     *
+     * @param context
+     *            Schema Context
+     * @param module
+     *            Yang Module
+     * @param prefix
+     *            Module Prefix
+     * @return Module for given prefix in specified Schema Context if is
+     *         present, otherwise returns <code>null</code>
+     */
+    private static Module resolveModuleForPrefix(SchemaContext context, Module module, String prefix) {
+        Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
+        Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
+        Preconditions.checkArgument(prefix != null, "Prefix string cannot be NULL");
+
+        if (prefix.equals(module.getPrefix())) {
+            return module;
+        }
+
+        Set<ModuleImport> imports = module.getImports();
+        for (ModuleImport mi : imports) {
+            if (prefix.equals(mi.getPrefix())) {
+                return context.findModuleByName(mi.getModuleName(), mi.getRevision());
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @throws IllegalArgumentException
+     *
+     * @param context
+     *            Schema Context
+     * @param module
+     *            Yang Module
+     * @param relativeXPath
+     *            Non conditional Revision Aware Relative XPath
+     * @param leafrefSchemaPath
+     *            Schema Path for Leafref
+     * @return list of QName
+     */
+    private static List<QName> resolveRelativeXPath(SchemaContext context, Module module,
+            RevisionAwareXPath relativeXPath, SchemaNode leafrefParentNode) {
+        Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
+        Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
+        Preconditions.checkArgument(relativeXPath != null, "Non Conditional Revision Aware XPath cannot be NULL");
+        Preconditions.checkState(!relativeXPath.isAbsolute(),
+                "Revision Aware XPath MUST be relative i.e. MUST contains ../, "
+                        + "for non relative Revision Aware XPath use findDataSchemaNode method");
+        Preconditions.checkState(leafrefParentNode.getPath() != null,
+                "Schema Path reference for Leafref cannot be NULL");
+
+        List<QName> absolutePath = new LinkedList<QName>();
+        String strXPath = relativeXPath.toString();
+        String[] xpaths = strXPath.split("/");
+
+        int colCount = 0;
+        while (xpaths[colCount].contains("..")) {
+            colCount = colCount + 1;
+        }
+        List<QName> path = leafrefParentNode.getPath().getPath();
+        if (path != null) {
+            int lenght = path.size() - colCount;
+            absolutePath.addAll(path.subList(0, lenght));
+            List<String> xpathsList = Arrays.asList(xpaths);
+            List<String> sublistedXPath = xpathsList.subList(colCount, xpaths.length);
+            List<QName> sublist = new ArrayList<>();
+            for (String pathPart : sublistedXPath) {
+                sublist.add(stringPathPartToQName(context, module, pathPart));
+            }
+            absolutePath.addAll(sublist);
+        }
+
+        return absolutePath;
+    }
+}
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.xtend b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.xtend
deleted file mode 100644 (file)
index 72d1e18..0000000
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * 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.model.util;
-
-import java.net.URI;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-
-import org.opendaylight.yangtools.yang.common.QName;
-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.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.ModuleImport;
-import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.api.RpcDefinition
-import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
-import java.util.Date
-import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
-import java.util.Set
-
-/**
- * The Schema Context Util contains support methods for searching through Schema Context modules for specified schema
- * nodes via Schema Path or Revision Aware XPath. The Schema Context Util is designed as mixin,
- * so it is not instantiable.
- *
- * @author Lukas Sedlak <lsedlak@cisco.com>
- */
-public  class SchemaContextUtil {
-
-    private new() {
-    }
-
-    /**
-     * Method attempts to find DataSchemaNode in Schema Context via specified Schema Path. The returned
-     * DataSchemaNode from method will be the node at the end of the SchemaPath. If the DataSchemaNode is not present
-     * in the Schema Context the method will return <code>null</code>.
-     * <br>
-     * In case that Schema Context or Schema Path are not specified correctly (i.e. contains <code>null</code>
-     * values) the method will return IllegalArgumentException.
-     *
-     * @throws IllegalArgumentException
-     *
-     * @param context
-     *            Schema Context
-     * @param schemaPath
-     *            Schema Path to search for
-     * @return DataSchemaNode from the end of the Schema Path or
-     *         <code>null</code> if the Node is not present.
-     */
-    public static def SchemaNode findDataSchemaNode( SchemaContext context,  SchemaPath schemaPath) {
-        if (context === null) {
-            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
-        }
-        if (schemaPath === null) {
-            throw new IllegalArgumentException("Schema Path reference cannot be NULL");
-        }
-        val prefixedPath = (schemaPath.getPath());
-        if (prefixedPath != null) {
-            return findNodeInSchemaContext(context,prefixedPath);
-        }
-        return null;
-    }
-
-    /**
-     * Method attempts to find DataSchemaNode inside of provided Schema Context and Yang Module accordingly to
-     * Non-conditional Revision Aware XPath. The specified Module MUST be present in Schema Context otherwise the
-     * operation would fail and return <code>null</code>.
-     * <br>
-     * The Revision Aware XPath MUST be specified WITHOUT the conditional statement (i.e. without [cond]) in path,
-     * because in this state the Schema Context is completely unaware of data state and will be not able to properly
-     * resolve XPath. If the XPath contains condition the method will return IllegalArgumentException.
-     * <br>
-     * In case that Schema Context or Module or Revision Aware XPath contains <code>null</code> references the method
-     * will throw IllegalArgumentException
-     * <br>
-     * If the Revision Aware XPath is correct and desired Data Schema Node is present in Yang module or in depending
-     * module in Schema Context the method will return specified Data Schema Node, otherwise the operation will fail
-     * and method will return <code>null</code>.
-     *
-     * @throws IllegalArgumentException
-     *
-     * @param context Schema Context
-     * @param module Yang Module
-     * @param nonCondXPath Non Conditional Revision Aware XPath
-     * @return Returns Data Schema Node for specified Schema Context for given Non-conditional Revision Aware XPath,
-     * or <code>null</code> if the DataSchemaNode is not present in Schema Context.
-     */
-    public static def SchemaNode findDataSchemaNode( SchemaContext context,  Module module,
-             RevisionAwareXPath nonCondXPath) {
-        if (context === null) {
-            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
-        }
-        if (module === null) {
-            throw new IllegalArgumentException("Module reference cannot be NULL!");
-        }
-        if (nonCondXPath === null) {
-            throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!");
-        }
-
-         val  strXPath = nonCondXPath.toString();
-        if (strXPath != null) {
-            if (strXPath.contains("[")) {
-                throw new IllegalArgumentException("Revision Aware XPath cannot contains condition!");
-            }
-            if (nonCondXPath.isAbsolute()) {
-                 val qnamedPath = xpathToQNamePath(context, module, strXPath);
-                if (qnamedPath != null) {
-                    return findNodeInSchemaContext(context,qnamedPath);
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Method attempts to find DataSchemaNode inside of provided Schema Context and Yang Module accordingly to
-     * Non-conditional relative Revision Aware XPath. The specified Module MUST be present in Schema Context otherwise
-     * the operation would fail and return <code>null</code>.
-     * <br>
-     * The relative Revision Aware XPath MUST be specified WITHOUT the conditional statement (i.e. without [cond]) in
-     * path, because in this state the Schema Context is completely unaware of data state and will be not able to
-     * properly resolve XPath. If the XPath contains condition the method will return IllegalArgumentException.
-     * <br>
-     * The Actual Schema Node MUST be specified correctly because from this Schema Node will search starts. If the
-     * Actual Schema Node is not correct the operation will simply fail, because it will be unable to find desired
-     * DataSchemaNode.
-     * <br>
-     * In case that Schema Context or Module or Actual Schema Node or relative Revision Aware XPath contains
-     * <code>null</code> references the method will throw IllegalArgumentException
-     * <br>
-     * If the Revision Aware XPath doesn't have flag <code>isAbsolute == false</code> the method will
-     * throw IllegalArgumentException.
-     * <br>
-     * If the relative Revision Aware XPath is correct and desired Data Schema Node is present in Yang module or in
-     * depending module in Schema Context the method will return specified Data Schema Node,
-     * otherwise the operation will fail
-     * and method will return <code>null</code>.
-     *
-     * @throws IllegalArgumentException
-     *
-     * @param context Schema Context
-     * @param module Yang Module
-     * @param actualSchemaNode Actual Schema Node
-     * @param relativeXPath Relative Non Conditional Revision Aware XPath
-     * @return DataSchemaNode if is present in specified Schema Context for given relative Revision Aware XPath,
-     * otherwise will return <code>null</code>.
-     */
-    public static def SchemaNode findDataSchemaNodeForRelativeXPath( SchemaContext context,  Module module,
-             SchemaNode actualSchemaNode,  RevisionAwareXPath relativeXPath) {
-        if (context === null) {
-            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
-        }
-        if (module === null) {
-            throw new IllegalArgumentException("Module reference cannot be NULL!");
-        }
-        if (actualSchemaNode === null) {
-            throw new IllegalArgumentException("Actual Schema Node reference cannot be NULL!");
-        }
-        if (relativeXPath === null) {
-            throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!");
-        }
-        if (relativeXPath.isAbsolute()) {
-            throw new IllegalArgumentException("Revision Aware XPath MUST be relative i.e. MUST contains ../, "
-                    + "for non relative Revision Aware XPath use findDataSchemaNode method!");
-        }
-
-         val actualNodePath = actualSchemaNode.getPath();
-        if (actualNodePath != null) {
-             val qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualSchemaNode);
-
-            if (qnamePath != null) {
-                return findNodeInSchemaContext(context,qnamePath);
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns parent Yang Module for specified Schema Context in which Schema Node is declared. If the Schema Node
-     * is not present in Schema Context the operation will return <code>null</code>.
-     * <br>
-     * If Schema Context or Schema Node contains <code>null</code> references the method will throw IllegalArgumentException
-     *
-     * @throws IllegalArgumentException
-     *
-     * @param context Schema Context
-     * @param schemaNode Schema Node
-     * @return Yang Module for specified Schema Context and Schema Node, if Schema Node is NOT present,
-     * the method will returns <code>null</code>
-     */
-    public static def Module findParentModule( SchemaContext context,  SchemaNode schemaNode) {
-        if (context === null) {
-            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
-        }
-        if (schemaNode === null) {
-            throw new IllegalArgumentException("Schema Node cannot be NULL!");
-        }
-
-        val schemaPath = schemaNode.getPath();
-        if (schemaPath === null) {
-            throw new IllegalStateException("Schema Path for Schema Node is not "
-                    + "set properly (Schema Path is NULL)");
-        }
-        val qnamedPath = schemaPath.path;
-        if (qnamedPath === null || qnamedPath.empty) {
-            throw new IllegalStateException("Schema Path contains invalid state of path parts."
-                    + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name"
-                    + "of path.");
-        }
-        val qname = qnamedPath.get(qnamedPath.size() - 1);
-        return context.findModuleByNamespaceAndRevision(qname.namespace,qname.revision);
-    }
-
-    /**
-     * Method will attempt to find DataSchemaNode from specified Module and Queue of QNames through the Schema
-     * Context. The QNamed path could be defined across multiple modules in Schema Context so the method is called
-     * recursively. If the QNamed path contains QNames that are not part of any Module or Schema Context Path the
-     * operation will fail and returns <code>null</code>
-     * <br>
-     * If Schema Context, Module or Queue of QNames refers to <code>null</code> values,
-     * the method will throws IllegalArgumentException
-     *
-     * @throws IllegalArgumentException
-     *
-     * @param context Schema Context
-     * @param module Yang Module
-     * @param qnamedPath Queue of QNames
-     * @return DataSchemaNode if is present in Module(s) for specified Schema Context and given QNamed Path,
-     * otherwise will return <code>null</code>.
-     */
-    private static def SchemaNode findSchemaNodeForGivenPath( SchemaContext context,  Module module,
-             Queue<QName> qnamedPath) {
-        if (context === null) {
-            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
-        }
-        if (module === null) {
-            throw new IllegalArgumentException("Module reference cannot be NULL!");
-        }
-        if (module.getNamespace() === null) {
-            throw new IllegalArgumentException("Namespace for Module cannot contains NULL reference!");
-        }
-        if (qnamedPath === null || qnamedPath.isEmpty()) {
-            throw new IllegalStateException("Schema Path contains invalid state of path parts."
-                    + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name"
-                    + "of path.");
-        }
-
-        var DataNodeContainer nextNode = module;
-        val moduleNamespace = module.getNamespace();
-
-        var QName childNodeQName;
-        var SchemaNode schemaNode = null;
-        while ((nextNode != null) && !qnamedPath.isEmpty()) {
-            childNodeQName = qnamedPath.peek();
-            if (childNodeQName != null) {
-                schemaNode = nextNode.getDataChildByName(childNodeQName.getLocalName());
-                if(schemaNode === null && nextNode instanceof Module) {
-                    schemaNode = (nextNode as Module).getNotificationByName(childNodeQName);
-                }
-                if(schemaNode === null && nextNode instanceof Module) {
-                    
-                }
-                val URI childNamespace = childNodeQName.getNamespace();
-                val Date childRevision = childNodeQName.getRevision();
-                
-                if (schemaNode != null) {
-                    if (schemaNode instanceof ContainerSchemaNode) {
-                        nextNode = schemaNode as ContainerSchemaNode;
-                    } else if (schemaNode instanceof ListSchemaNode) {
-                        nextNode = schemaNode as ListSchemaNode;
-                    } else if (schemaNode instanceof ChoiceNode) {
-                        val choice =  schemaNode as ChoiceNode;
-                        qnamedPath.poll();
-                        if (!qnamedPath.isEmpty()) {
-                            childNodeQName = qnamedPath.peek();
-                            nextNode = choice.getCaseNodeByName(childNodeQName);
-                            schemaNode = nextNode as DataSchemaNode;
-                        }
-                    } else {
-                        nextNode = null;
-                    }
-                } else if (!childNamespace.equals(moduleNamespace)) {
-                    val Module nextModule = context.findModuleByNamespaceAndRevision(childNamespace,childRevision);
-                    schemaNode = findSchemaNodeForGivenPath(context, nextModule, qnamedPath);
-                    return schemaNode;
-                }
-                qnamedPath.poll();
-            }
-        }
-        return schemaNode;
-    }
-
-
-    public static def SchemaNode findNodeInSchemaContext(SchemaContext context, List<QName> path) {
-        val current = path.get(0);
-        val module = context.findModuleByNamespaceAndRevision(current.namespace,current.revision);
-        if(module === null) return null;
-        return findNodeInModule(module,path);
-    }
-
-    public static def GroupingDefinition findGrouping(SchemaContext context, Module module, List<QName> path) {
-        var first = path.get(0);
-        var Module m = context.findModuleByNamespace(first.namespace).iterator().next();
-        var DataNodeContainer currentParent = m;
-        for (qname : path) {
-            var boolean found = false;
-            var DataNodeContainer node = currentParent.getDataChildByName(qname.localName) as DataNodeContainer;
-            if (node == null) {
-                var Set<GroupingDefinition> groupings = currentParent.getGroupings();
-                for (gr : groupings) {
-                    if(gr.getQName().localName.equals(qname.localName)) {
-                        currentParent = gr;
-                        found = true;
-                    }
-                }
-            } else {
-                found = true;
-                currentParent = node;
-            }
-            if (!found) {
-                throw new IllegalArgumentException("Failed to find referenced grouping: " + path + "(" + qname.localName + ")");
-            }
-        }
-        
-        return currentParent as GroupingDefinition;
-    }
-
-    private static def SchemaNode findNodeInModule(Module module, List<QName> path) {
-        val current = path.get(0)
-        var SchemaNode node = module.getDataChildByName(current);
-        if (node != null) return findNode(node as DataSchemaNode,path.nextLevel);
-        node = module.getRpcByName(current);
-        if (node != null) return findNodeInRpc(node as RpcDefinition,path.nextLevel)
-        node = module.getNotificationByName(current);
-        if (node != null) return findNodeInNotification(node as NotificationDefinition,path.nextLevel)
-        node = module.getGroupingByName(current);
-        if (node != null) return findNodeInGrouping(node as GroupingDefinition, path.nextLevel);
-        return node
-    }
-
-    private static def SchemaNode findNodeInGrouping(GroupingDefinition grouping, List<QName> path) {
-        if (path.empty) return grouping;
-        val current = path.get(0)
-        val node = grouping.getDataChildByName(current);
-        if (node != null) return findNode(node, path.nextLevel);
-        return null;
-    }
-
-    private static def SchemaNode findNodeInRpc(RpcDefinition rpc,List<QName> path) {
-        if(path.empty) return rpc;
-        val current = path.get(0);
-        switch (current.localName) {
-            case "input": return findNode(rpc.input,path.nextLevel)
-            case "output": return  findNode(rpc.output,path.nextLevel)
-        }
-        return null
-    }
-    
-    private static def SchemaNode findNodeInNotification(NotificationDefinition rpc,List<QName> path) {
-        if(path.empty) return rpc;
-        val current = path.get(0)
-        val node = rpc.getDataChildByName(current)
-        if(node != null) return findNode(node,path.nextLevel)
-        return null
-    }
-    
-    private static dispatch def SchemaNode findNode(ChoiceNode parent,List<QName> path) {
-        if(path.empty) return parent;
-        val current = path.get(0)
-        val node = parent.getCaseNodeByName(current)
-        if (node != null) return findNodeInCase(node,path.nextLevel)
-        return null
-    }
-    
-    private static dispatch def SchemaNode findNode(ContainerSchemaNode parent,List<QName> path) {
-        if(path.empty) return parent;
-         val current = path.get(0)
-        val node = parent.getDataChildByName(current)
-        if (node != null) return findNode(node,path.nextLevel)
-        return null
-    }
-    
-    private static dispatch def SchemaNode findNode(ListSchemaNode parent,List<QName> path) {
-        if(path.empty) return parent;
-         val current = path.get(0)
-        val node = parent.getDataChildByName(current)
-        if (node != null) return findNode(node,path.nextLevel)
-        return null
-    }
-    
-    private static dispatch def SchemaNode findNode(DataSchemaNode parent,List<QName> path){
-        if(path.empty) {
-            return parent
-        } else {
-            throw new IllegalArgumentException("Path nesting violation");
-        }
-    }
-    
-    public static  def SchemaNode findNodeInCase(ChoiceCaseNode parent,List<QName> path) {
-        if(path.empty) return parent;
-         val current = path.get(0)
-        val node = parent.getDataChildByName(current)
-        if (node != null) return findNode(node,path.nextLevel)
-        return null
-    }
-    
-     
-    public static def RpcDefinition getRpcByName(Module module, QName name) {
-        for (rpc : module.rpcs) {
-            if (rpc.QName.equals(name)) {
-                return rpc;
-            }
-        }
-        return null;
-    }
-    
-    
-    private static def nextLevel(List<QName> path){
-        return path.subList(1,path.size)
-    }
-    
-    public static def NotificationDefinition getNotificationByName(Module module, QName name) {
-        for(notification : module.notifications) {
-            if(notification.QName.equals(name)) {
-                return notification;
-            }
-        }
-        return null;
-    }
-    
-    public static def GroupingDefinition getGroupingByName(Module module, QName name) {
-        for (grouping : module.groupings) {
-            if (grouping.QName.equals(name)) {
-                return grouping;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Transforms string representation of XPath to Queue of QNames. The XPath is split by "/" and for each part of
-     * XPath is assigned correct module in Schema Path.
-     * <br>
-     * If Schema Context, Parent Module or XPath string contains <code>null</code> values,
-     * the method will throws IllegalArgumentException
-     *
-     * @throws IllegalArgumentException
-     *
-     * @param context Schema Context
-     * @param parentModule Parent Module
-     * @param xpath XPath String
-     * @return return a list of QName
-     */
-    private static def xpathToQNamePath( SchemaContext context,  Module parentModule,
-             String xpath) {
-        if (context === null) {
-            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
-        }
-        if (parentModule === null) {
-            throw new IllegalArgumentException("Parent Module reference cannot be NULL!");
-        }
-        if (xpath === null) {
-            throw new IllegalArgumentException("XPath string reference cannot be NULL!");
-        }
-
-        val path = new LinkedList<QName>();
-        val String[] prefixedPath = xpath.split("/");
-        for (pathComponent : prefixedPath) {
-            if (!pathComponent.isEmpty()) {
-                path.add(stringPathPartToQName(context, parentModule, pathComponent));
-            }
-        }
-        return path;
-    }
-
-    /**
-     * Transforms part of Prefixed Path as java String to QName.
-     * <br>
-     * If the string contains module prefix separated by ":" (i.e. mod:container) this module is provided from from
-     * Parent Module list of imports. If the Prefixed module is present in Schema Context the QName can be
-     * constructed.
-     * <br>
-     * If the Prefixed Path Part does not contains prefix the Parent's Module namespace is taken for construction of
-     * QName.
-     * <br>
-     * If Schema Context, Parent Module or Prefixed Path Part refers to <code>null</code> the method will throw
-     * IllegalArgumentException
-     *
-     * @throws IllegalArgumentException
-     *
-     * @param context Schema Context
-     * @param parentModule Parent Module
-     * @param prefixedPathPart Prefixed Path Part string
-     * @return QName from prefixed Path Part String.
-     */
-    private static def QName stringPathPartToQName( SchemaContext context,  Module parentModule,
-             String prefixedPathPart) {
-        if (context === null) {
-            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
-        }
-        if (parentModule === null) {
-            throw new IllegalArgumentException("Parent Module reference cannot be NULL!");
-        }
-        if (prefixedPathPart === null) {
-            throw new IllegalArgumentException("Prefixed Path Part cannot be NULL!");
-        }
-
-        if (prefixedPathPart.contains(":")) {
-            val String[] prefixedName = prefixedPathPart.split(":");
-            val module = resolveModuleForPrefix(context, parentModule, prefixedName.get(0));
-            if (module == null) {
-                throw new IllegalArgumentException(
-                    "Failed to resolve xpath: no module found for prefix " + prefixedName.get(0) + " in module " +
-                        parentModule.name)
-            } else {
-                return new QName(module.getNamespace(), module.getRevision(), prefixedName.get(1));
-            }
-        } else {
-            return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
-        }
-    }
-
-    /**
-     * Method will attempt to resolve and provide Module reference for specified module prefix. Each Yang module
-     * could contains multiple imports which MUST be associated with corresponding module prefix. The method simply
-     * looks into module imports and returns the module that is bounded with specified prefix. If the prefix is not
-     * present in module or the prefixed module is not present in specified Schema Context,
-     * the method will return <code>null</code>.
-     * <br>
-     * If String prefix is the same as prefix of the specified Module the reference to this module is returned.
-     * <br>
-     * If Schema Context, Module or Prefix are referring to <code>null</code> the method will return
-     * IllegalArgumentException
-     *
-     * @throws IllegalArgumentException
-     *
-     * @param context Schema Context
-     * @param module Yang Module
-     * @param prefix Module Prefix
-     * @return Module for given prefix in specified Schema Context if is present, otherwise returns <code>null</code>
-     */
-    private static def Module resolveModuleForPrefix( SchemaContext context,  Module module,  String prefix) {
-        if (context === null) {
-            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
-        }
-        if (module === null) {
-            throw new IllegalArgumentException("Module reference cannot be NULL!");
-        }
-        if (prefix === null) {
-            throw new IllegalArgumentException("Prefix string cannot be NULL!");
-        }
-
-        if (prefix.equals(module.getPrefix())) {
-            return module;
-        }
-
-        val imports = module.getImports();
-        for ( ModuleImport mi : imports) {
-            if (prefix.equals(mi.getPrefix())) {
-                return context.findModuleByName(mi.getModuleName(), mi.getRevision());
-            }
-        }
-        return null;
-    }
-
-    /**
-     * @throws IllegalArgumentException
-     *
-     * @param context Schema Context
-     * @param module Yang Module
-     * @param relativeXPath Non conditional Revision Aware Relative XPath
-     * @param leafrefSchemaPath Schema Path for Leafref
-     * @return list of QName
-     */
-    private static def resolveRelativeXPath( SchemaContext context,  Module module,
-             RevisionAwareXPath relativeXPath,  SchemaNode leafrefParentNode) {
-
-        if (context === null) {
-            throw new IllegalArgumentException("Schema Context reference cannot be NULL!");
-        }
-        if (module === null) {
-            throw new IllegalArgumentException("Module reference cannot be NULL!");
-        }
-        if (relativeXPath === null) {
-            throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!");
-        }
-        if (relativeXPath.isAbsolute()) {
-            throw new IllegalArgumentException("Revision Aware XPath MUST be relative i.e. MUST contains ../, "
-                    + "for non relative Revision Aware XPath use findDataSchemaNode method!");
-        }
-        if (leafrefParentNode.getPath() === null) {
-            throw new IllegalArgumentException("Schema Path reference for Leafref cannot be NULL!");
-        }
-        val absolutePath = new LinkedList<QName>();
-        val String strXPath = relativeXPath.toString();
-        if (strXPath != null) {
-            val String[] xpaths = strXPath.split("/");
-            if (xpaths != null) {
-                var int colCount = 0;
-                while (xpaths.get(colCount).contains("..")) {
-                    colCount = colCount+ 1;
-                }
-                val path = leafrefParentNode.getPath().getPath();
-                if (path != null) {
-                    val int lenght = path.size() - colCount;
-                    absolutePath.addAll(path.subList(0,lenght));
-                    val List<QName> sublist = xpaths.subList(colCount,xpaths.length).map[stringPathPartToQName(context, module,it)]
-                    absolutePath.addAll(sublist)
-                }
-            }
-        }
-        return absolutePath;
-    }
-}
index 0231aa80c6f513ba36b134c6c918381426a38107..7e436362f4a8bee0d56a93472a79d451308149ec 100644 (file)
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.eclipse.xtend</groupId>
-            <artifactId>org.eclipse.xtend.lib</artifactId>
-        </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
                     <listener>true</listener>
                 </configuration>
             </plugin>
-            <plugin>
-                <groupId>org.eclipse.xtend</groupId>
-                <artifactId>xtend-maven-plugin</artifactId>
-            </plugin>
             <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>build-helper-maven-plugin</artifactId>
index 1ad6ca37527984221c66d159b4e7166ee8abff0e..7448f130b2c3f615ab22d4e2f695b7ccc4bd1879 100644 (file)
@@ -854,7 +854,7 @@ public final class YangParserImpl implements YangModelParser {
                 newPath.add(new QName(ns, rev, localPrefix, qn.getLocalName()));
             }
         }
-        augment.setTargetNodeSchemaPath(new SchemaPath(newPath, augment.getTargetPath().isAbsolute()));
+        augment.setTargetNodeSchemaPath(new SchemaPath(newPath, true));
 
         for (DataSchemaNodeBuilder childNode : augment.getChildNodeBuilders()) {
             correctPathForAugmentNodes(childNode, augment.getTargetNodeSchemaPath());
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserUtils.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserUtils.java
new file mode 100644 (file)
index 0000000..2547296
--- /dev/null
@@ -0,0 +1,605 @@
+/*
+ * 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.parser.util;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
+import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceCaseBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.NotificationBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.RpcDefinitionBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.api.GroupingMember;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import java.util.HashSet;
+import java.net.URI;
+
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.yangtools.yang.parser.builder.impl.AnyXmlBuilder;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ListSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.GroupingBuilderImpl;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+
+import com.google.common.base.Preconditions;
+
+public final class ParserUtils {
+
+    private ParserUtils() {
+    }
+
+    /**
+     * Create new SchemaPath from given path and qname.
+     *
+     * @param schemaPath
+     *            base path
+     * @param qname
+     *            one or more qnames added to base path
+     * @return new SchemaPath from given path and qname
+     */
+    public static SchemaPath createSchemaPath(SchemaPath schemaPath, QName... qname) {
+        List<QName> path = new ArrayList<>(schemaPath.getPath());
+        path.addAll(Arrays.asList(qname));
+        return new SchemaPath(path, schemaPath.isAbsolute());
+    }
+
+    /**
+     * Get module import referenced by given prefix.
+     *
+     * @param builder
+     *            module to search
+     * @param prefix
+     *            prefix associated with import
+     * @return ModuleImport based on given prefix
+     */
+    public static ModuleImport getModuleImport(ModuleBuilder builder, String prefix) {
+        for (ModuleImport mi : builder.getModuleImports()) {
+            if (mi.getPrefix().equals(prefix)) {
+                return mi;
+
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Find dependent module based on given prefix
+     *
+     * @param modules
+     *            all available modules
+     * @param module
+     *            current module
+     * @param prefix
+     *            target module prefix
+     * @param line
+     *            current line in yang model
+     * @return module builder if found, null otherwise
+     */
+    public static ModuleBuilder findModuleFromBuilders(Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            ModuleBuilder module, String prefix, int line) {
+        ModuleBuilder dependentModule = null;
+        Date dependentModuleRevision = null;
+
+        if (prefix == null) {
+            dependentModule = module;
+        } else if (prefix.equals(module.getPrefix())) {
+            dependentModule = module;
+        } else {
+            ModuleImport dependentModuleImport = getModuleImport(module, prefix);
+            if (dependentModuleImport == null) {
+                throw new YangParseException(module.getName(), line, "No import found with prefix '" + prefix + "'.");
+            }
+            String dependentModuleName = dependentModuleImport.getModuleName();
+            dependentModuleRevision = dependentModuleImport.getRevision();
+
+            TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
+            if (moduleBuildersByRevision == null) {
+                return null;
+            }
+            if (dependentModuleRevision == null) {
+                dependentModule = moduleBuildersByRevision.lastEntry().getValue();
+            } else {
+                dependentModule = moduleBuildersByRevision.get(dependentModuleRevision);
+            }
+        }
+        return dependentModule;
+    }
+
+    /**
+     * Find module from context based on prefix.
+     *
+     * @param context
+     *            schema context
+     * @param currentModule
+     *            current module
+     * @param prefix
+     *            current prefix used to reference dependent module
+     * @param line
+     *            current line in yang model
+     * @return module based on given prefix if found in context, null otherwise
+     */
+    public static Module findModuleFromContext(SchemaContext context, ModuleBuilder currentModule, String prefix,
+            int line) {
+        if (context == null) {
+            throw new YangParseException(currentModule.getName(), line, "Cannot find module with prefix '" + prefix
+                    + "'.");
+        }
+        TreeMap<Date, Module> modulesByRevision = new TreeMap<>();
+
+        ModuleImport dependentModuleImport = ParserUtils.getModuleImport(currentModule, prefix);
+        if (dependentModuleImport == null) {
+            throw new YangParseException(currentModule.getName(), line, "No import found with prefix '" + prefix + "'.");
+        }
+        String dependentModuleName = dependentModuleImport.getModuleName();
+        Date dependentModuleRevision = dependentModuleImport.getRevision();
+
+        for (Module contextModule : context.getModules()) {
+            if (contextModule.getName().equals(dependentModuleName)) {
+                Date revision = contextModule.getRevision();
+                if (revision == null) {
+                    revision = new Date(0L);
+                }
+                modulesByRevision.put(revision, contextModule);
+            }
+        }
+
+        Module result = null;
+        if (dependentModuleRevision == null) {
+            result = modulesByRevision.get(modulesByRevision.firstKey());
+        } else {
+            result = modulesByRevision.get(dependentModuleRevision);
+        }
+        return result;
+    }
+
+    /**
+     * Parse XPath string.
+     *
+     * @param xpathString
+     *            XPath as String
+     * @return SchemaPath from given String
+     */
+    public static SchemaPath parseXPathString(String xpathString) {
+        boolean absolute = xpathString.startsWith("/");
+        String[] splittedPath = xpathString.split("/");
+        List<QName> path = new ArrayList<QName>();
+        QName name;
+        for (String pathElement : splittedPath) {
+            if (pathElement.length() > 0) {
+                String[] splittedElement = pathElement.split(":");
+                if (splittedElement.length == 1) {
+                    name = new QName(null, null, null, splittedElement[0]);
+                } else {
+                    name = new QName(null, null, splittedElement[0], splittedElement[1]);
+                }
+                path.add(name);
+            }
+        }
+        return new SchemaPath(path, absolute);
+    }
+
+    /**
+     * Add all augment's child nodes to given target.
+     *
+     * @param augment
+     *            builder of augment statement
+     * @param target
+     *            augmentation target node
+     */
+    public static void fillAugmentTarget(AugmentationSchemaBuilder augment, Builder target) {
+        if (target instanceof DataNodeContainerBuilder) {
+            fillAugmentTarget(augment, (DataNodeContainerBuilder) target);
+        } else if (target instanceof ChoiceBuilder) {
+            fillAugmentTarget(augment, (ChoiceBuilder) target);
+        } else {
+            throw new YangParseException(
+                    augment.getModuleName(),
+                    augment.getLine(),
+                    "Error in augment parsing: The target node MUST be either a container, list, choice, case, input, output, or notification node.");
+        }
+    }
+
+    /**
+     * Add all augment's child nodes to given target.
+     *
+     * @param augment
+     *            builder of augment statement
+     * @param target
+     *            augmentation target node
+     */
+    private static void fillAugmentTarget(AugmentationSchemaBuilder augment, DataNodeContainerBuilder target) {
+        for (DataSchemaNodeBuilder child : augment.getChildNodeBuilders()) {
+            DataSchemaNodeBuilder childCopy = CopyUtils.copy(child, target, false);
+            if (augment.getParent() instanceof UsesNodeBuilder) {
+                setNodeAddedByUses(childCopy);
+            }
+            setNodeAugmenting(childCopy);
+            try {
+                target.addChildNode(childCopy);
+            } catch (YangParseException e) {
+
+                // more descriptive message
+                throw new YangParseException(augment.getModuleName(), augment.getLine(),
+                        "Failed to perform augmentation: " + e.getMessage());
+            }
+        }
+    }
+
+    /**
+     * Add all augment's child nodes to given target.
+     *
+     * @param augment
+     *            builder of augment statement
+     * @param target
+     *            augmentation target choice node
+     */
+    private static void fillAugmentTarget(AugmentationSchemaBuilder augment, ChoiceBuilder target) {
+        for (DataSchemaNodeBuilder builder : augment.getChildNodeBuilders()) {
+            DataSchemaNodeBuilder childCopy = CopyUtils.copy(builder, target, false);
+            if (augment.getParent() instanceof UsesNodeBuilder) {
+                setNodeAddedByUses(childCopy);
+            }
+            setNodeAugmenting(childCopy);
+            target.addCase(childCopy);
+        }
+        for (UsesNodeBuilder usesNode : augment.getUsesNodeBuilders()) {
+            if (usesNode != null) {
+                throw new YangParseException(augment.getModuleName(), augment.getLine(),
+                        "Error in augment parsing: cannot augment choice with nodes from grouping");
+            }
+        }
+    }
+
+    /**
+     * Set augmenting flag to true for node and all its child nodes.
+     *
+     * @param node
+     */
+    private static void setNodeAugmenting(DataSchemaNodeBuilder node) {
+        node.setAugmenting(true);
+        if (node instanceof DataNodeContainerBuilder) {
+            DataNodeContainerBuilder dataNodeChild = (DataNodeContainerBuilder) node;
+            for (DataSchemaNodeBuilder inner : dataNodeChild.getChildNodeBuilders()) {
+                setNodeAugmenting(inner);
+            }
+        } else if (node instanceof ChoiceBuilder) {
+            ChoiceBuilder choiceChild = (ChoiceBuilder) node;
+            for (ChoiceCaseBuilder inner : choiceChild.getCases()) {
+                setNodeAugmenting(inner);
+            }
+        }
+    }
+
+    /**
+     * Set addedByUses flag to true for node and all its child nodes.
+     *
+     * @param node
+     */
+    public static void setNodeAddedByUses(GroupingMember node) {
+        node.setAddedByUses(true);
+        if (node instanceof DataNodeContainerBuilder) {
+            DataNodeContainerBuilder dataNodeChild = (DataNodeContainerBuilder) node;
+            for (DataSchemaNodeBuilder inner : dataNodeChild.getChildNodeBuilders()) {
+                setNodeAddedByUses(inner);
+            }
+        } else if (node instanceof ChoiceBuilder) {
+            ChoiceBuilder choiceChild = (ChoiceBuilder) node;
+            for (ChoiceCaseBuilder inner : choiceChild.getCases()) {
+                setNodeAddedByUses(inner);
+            }
+        }
+    }
+
+    /**
+     * Set config flag to new value.
+     *
+     * @param node
+     *            node to update
+     * @param config
+     *            new config value
+     */
+    public static void setNodeConfig(DataSchemaNodeBuilder node, Boolean config) {
+        if (node instanceof ContainerSchemaNodeBuilder || node instanceof LeafSchemaNodeBuilder
+                || node instanceof LeafListSchemaNodeBuilder || node instanceof ListSchemaNodeBuilder
+                || node instanceof ChoiceBuilder || node instanceof AnyXmlBuilder) {
+            node.setConfiguration(config);
+        }
+        if (node instanceof DataNodeContainerBuilder) {
+            DataNodeContainerBuilder dataNodeChild = (DataNodeContainerBuilder) node;
+            for (DataSchemaNodeBuilder inner : dataNodeChild.getChildNodeBuilders()) {
+                setNodeConfig(inner, config);
+            }
+        } else if (node instanceof ChoiceBuilder) {
+            ChoiceBuilder choiceChild = (ChoiceBuilder) node;
+            for (ChoiceCaseBuilder inner : choiceChild.getCases()) {
+                setNodeConfig(inner, config);
+            }
+        }
+    }
+
+    public static DataSchemaNodeBuilder findSchemaNode(List<QName> path, SchemaNodeBuilder parentNode) {
+        DataSchemaNodeBuilder node = null;
+        SchemaNodeBuilder parent = parentNode;
+        int i = 0;
+        while (i < path.size()) {
+            String name = path.get(i).getLocalName();
+            if (parent instanceof DataNodeContainerBuilder) {
+                node = ((DataNodeContainerBuilder) parent).getDataChildByName(name);
+            } else if (parent instanceof ChoiceBuilder) {
+                node = ((ChoiceBuilder) parent).getCaseNodeByName(name);
+            } else if (parent instanceof RpcDefinitionBuilder) {
+                if ("input".equals(name)) {
+                    node = ((RpcDefinitionBuilder) parent).getInput();
+                } else if ("output".equals(name)) {
+                    node = ((RpcDefinitionBuilder) parent).getOutput();
+                } else {
+                    return null;
+                }
+            } else {
+                return null;
+            }
+
+            if (i < path.size() - 1) {
+                parent = node;
+            }
+            i = i + 1;
+        }
+
+        return node;
+    }
+
+    public static SchemaNodeBuilder findSchemaNodeInModule(List<QName> pathToNode, ModuleBuilder module) {
+        List<QName> path = new ArrayList<>(pathToNode);
+        QName first = path.remove(0);
+
+        SchemaNodeBuilder node = module.getDataChildByName(first.getLocalName());
+        if (node == null) {
+            Set<NotificationBuilder> notifications = module.getAddedNotifications();
+            for (NotificationBuilder notification : notifications) {
+                if (notification.getQName().getLocalName().equals(first.getLocalName())) {
+                    node = notification;
+                }
+            }
+        }
+        if (node == null) {
+            Set<RpcDefinitionBuilder> rpcs = module.getAddedRpcs();
+            for (RpcDefinitionBuilder rpc : rpcs) {
+                if (rpc.getQName().getLocalName().equals(first.getLocalName())) {
+                    node = rpc;
+                }
+            }
+        }
+        if (node == null) {
+            return null;
+        }
+
+        if (!path.isEmpty()) {
+            node = findSchemaNode(path, node);
+        }
+
+        return node;
+    }
+
+    /**
+     * Find augment target node and perform augmentation.
+     *
+     * @param augment
+     * @param firstNodeParent
+     *            parent of first node in path
+     * @param path
+     *            path to augment target
+     * @return true if augmentation process succeed, false otherwise
+     */
+    public static boolean processAugmentation(AugmentationSchemaBuilder augment, ModuleBuilder firstNodeParent) {
+        List<QName> path = augment.getTargetPath().getPath();
+        Builder targetNode = findSchemaNodeInModule(path, firstNodeParent);
+        if (targetNode == null) {
+            return false;
+        }
+
+        fillAugmentTarget(augment, targetNode);
+        ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
+        augment.setResolved(true);
+        return true;
+    }
+
+    public static IdentitySchemaNodeBuilder findBaseIdentity(Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            ModuleBuilder module, String baseString, int line) {
+        IdentitySchemaNodeBuilder result = null;
+        if (baseString.contains(":")) {
+            String[] splittedBase = baseString.split(":");
+            if (splittedBase.length > 2) {
+                throw new YangParseException(module.getName(), line, "Failed to parse identityref base: " + baseString);
+            }
+            String prefix = splittedBase[0];
+            String name = splittedBase[1];
+            ModuleBuilder dependentModule = findModuleFromBuilders(modules, module, prefix, line);
+            if (dependentModule != null) {
+                result = findIdentity(dependentModule.getAddedIdentities(), name);
+            }
+        } else {
+            result = findIdentity(module.getAddedIdentities(), baseString);
+        }
+        return result;
+    }
+
+    public static IdentitySchemaNode findBaseIdentityFromContext(Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            ModuleBuilder module, String baseString, int line, SchemaContext context) {
+        IdentitySchemaNode result = null;
+
+        String[] splittedBase = baseString.split(":");
+        if (splittedBase.length > 2) {
+            throw new YangParseException(module.getName(), line, "Failed to parse identityref base: " + baseString);
+        }
+        String prefix = splittedBase[0];
+        String name = splittedBase[1];
+        Module dependentModule = findModuleFromContext(context, module, prefix, line);
+        result = findIdentityNode(dependentModule.getIdentities(), name);
+
+        if (result == null) {
+            throw new YangParseException(module.getName(), line, "Failed to find base identity");
+        }
+        return result;
+    }
+
+    private static IdentitySchemaNodeBuilder findIdentity(Set<IdentitySchemaNodeBuilder> identities, String name) {
+        for (IdentitySchemaNodeBuilder identity : identities) {
+            if (identity.getQName().getLocalName().equals(name)) {
+                return identity;
+            }
+        }
+        return null;
+    }
+
+    private static IdentitySchemaNode findIdentityNode(Set<IdentitySchemaNode> identities, String name) {
+        for (IdentitySchemaNode identity : identities) {
+            if (identity.getQName().getLocalName().equals(name)) {
+                return identity;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get module in which this node is defined.
+     *
+     * @param node
+     * @return builder of module where this node is defined
+     */
+    public static ModuleBuilder getParentModule(Builder node) {
+        if (node instanceof ModuleBuilder) {
+            return (ModuleBuilder) node;
+        }
+        Builder parent = node.getParent();
+        while (!(parent instanceof ModuleBuilder)) {
+            parent = parent.getParent();
+        }
+        Preconditions.checkState(parent instanceof ModuleBuilder);
+        ModuleBuilder parentModule = (ModuleBuilder) parent;
+        if (parentModule.isSubmodule()) {
+            parentModule = parentModule.getParent();
+        }
+        return parentModule;
+    }
+
+    public static Set<DataSchemaNodeBuilder> wrapChildNodes(String moduleName, int line, Set<DataSchemaNode> nodes,
+            SchemaPath parentPath, URI ns, Date rev, String pref) {
+        Set<DataSchemaNodeBuilder> result = new HashSet<>();
+
+        for (DataSchemaNode node : nodes) {
+            QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
+            DataSchemaNodeBuilder wrapped = wrapChildNode(moduleName, line, node, parentPath, qname);
+            result.add(wrapped);
+        }
+        return result;
+    }
+
+    public static DataSchemaNodeBuilder wrapChildNode(String moduleName, int line, DataSchemaNode node,
+            SchemaPath parentPath, QName qname) {
+        List<QName> path = new ArrayList<>(parentPath.getPath());
+        path.add(qname);
+        SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute());
+
+        if (node instanceof AnyXmlSchemaNode) {
+            return new AnyXmlBuilder(moduleName, line, qname, schemaPath, ((AnyXmlSchemaNode) node));
+        } else if (node instanceof ChoiceNode) {
+            return new ChoiceBuilder(moduleName, line, qname, schemaPath, ((ChoiceNode) node));
+        } else if (node instanceof ContainerSchemaNode) {
+            return new ContainerSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((ContainerSchemaNode) node));
+        } else if (node instanceof LeafSchemaNode) {
+            return new LeafSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((LeafSchemaNode) node));
+        } else if (node instanceof LeafListSchemaNode) {
+            return new LeafListSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((LeafListSchemaNode) node));
+        } else if (node instanceof ListSchemaNode) {
+            return new ListSchemaNodeBuilder(moduleName, line, qname, schemaPath, ((ListSchemaNode) node));
+        } else if (node instanceof ChoiceCaseNode) {
+            return new ChoiceCaseBuilder(moduleName, line, qname, schemaPath, ((ChoiceCaseNode) node));
+        } else {
+            throw new YangParseException(moduleName, line, "Failed to copy node: Unknown type of DataSchemaNode: "
+                    + node);
+        }
+    }
+
+    public static Set<GroupingBuilder> wrapGroupings(String moduleName, int line, Set<GroupingDefinition> nodes,
+            SchemaPath parentPath, URI ns, Date rev, String pref) {
+        Set<GroupingBuilder> result = new HashSet<>();
+        for (GroupingDefinition node : nodes) {
+            QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
+            List<QName> path = new ArrayList<>(parentPath.getPath());
+            path.add(qname);
+            SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute());
+            result.add(new GroupingBuilderImpl(moduleName, line, qname, schemaPath, node));
+        }
+        return result;
+    }
+
+    public static Set<TypeDefinitionBuilder> wrapTypedefs(String moduleName, int line, DataNodeContainer dataNode,
+            SchemaPath parentPath, URI ns, Date rev, String pref) {
+        Set<TypeDefinition<?>> nodes = dataNode.getTypeDefinitions();
+        Set<TypeDefinitionBuilder> result = new HashSet<>();
+        for (TypeDefinition<?> node : nodes) {
+            QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
+            List<QName> path = new ArrayList<>(parentPath.getPath());
+            path.add(qname);
+            SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute());
+            result.add(new TypeDefinitionBuilderImpl(moduleName, line, qname, schemaPath, ((ExtendedType) node)));
+        }
+        return result;
+    }
+
+    public static List<UnknownSchemaNodeBuilder> wrapUnknownNodes(String moduleName, int line,
+            List<UnknownSchemaNode> nodes, SchemaPath parentPath, URI ns, Date rev, String pref) {
+        List<UnknownSchemaNodeBuilder> result = new ArrayList<>();
+        for (UnknownSchemaNode node : nodes) {
+            QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
+            List<QName> path = new ArrayList<>(parentPath.getPath());
+            path.add(qname);
+            SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute());
+            result.add(new UnknownSchemaNodeBuilder(moduleName, line, qname, schemaPath, node));
+        }
+        return result;
+    }
+
+}
diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserUtils.xtend b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserUtils.xtend
deleted file mode 100644 (file)
index b78906b..0000000
+++ /dev/null
@@ -1,572 +0,0 @@
-/*
- * 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.parser.util;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
-import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.ModuleImport;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
-import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceCaseBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.RpcDefinitionBuilder
-import org.opendaylight.yangtools.yang.parser.builder.api.GroupingMember
-import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
-import java.util.HashSet
-import java.net.URI
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
-import org.opendaylight.yangtools.yang.parser.builder.impl.AnyXmlBuilder
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode
-import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode
-import org.opendaylight.yangtools.yang.parser.builder.impl.ContainerSchemaNodeBuilder
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
-import org.opendaylight.yangtools.yang.parser.builder.impl.ListSchemaNodeBuilder
-import org.opendaylight.yangtools.yang.parser.builder.impl.LeafListSchemaNodeBuilder
-import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder
-import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
-import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder
-import org.opendaylight.yangtools.yang.parser.builder.impl.GroupingBuilderImpl
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition
-import org.opendaylight.yangtools.yang.parser.builder.impl.TypeDefinitionBuilderImpl
-import org.opendaylight.yangtools.yang.model.util.ExtendedType
-import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder
-import org.opendaylight.yangtools.yang.parser.builder.impl.UnknownSchemaNodeBuilder
-import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode
-import org.opendaylight.yangtools.yang.model.api.DataNodeContainer
-import com.google.common.base.Preconditions
-
-public final class ParserUtils {
-
-    private new() {
-    }
-
-    /**
-     * Create new SchemaPath from given path and qname.
-     *
-     * @param schemaPath
-     * @param qname
-     * @return new SchemaPath from given path and qname
-     */
-    public static def SchemaPath createSchemaPath(SchemaPath schemaPath, QName... qname) {
-        val path = new ArrayList<QName>(schemaPath.getPath());
-        path.addAll(Arrays.asList(qname));
-        return new SchemaPath(path, schemaPath.isAbsolute());
-    }
-
-    /**
-     * Get module import referenced by given prefix.
-     *
-     * @param builder
-     *            module to search
-     * @param prefix
-     *            prefix associated with import
-     * @return ModuleImport based on given prefix
-     */
-    public static def ModuleImport getModuleImport(ModuleBuilder builder, String prefix) {
-        for (ModuleImport mi : builder.getModuleImports()) {
-            if (mi.getPrefix().equals(prefix)) {
-                return mi;
-
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Find dependent module based on given prefix
-     *
-     * @param modules
-     *            all available modules
-     * @param module
-     *            current module
-     * @param prefix
-     *            target module prefix
-     * @param line
-     *            current line in yang model
-     * @return module builder if found, null otherwise
-     */
-    public static def ModuleBuilder findModuleFromBuilders(Map<String, TreeMap<Date, ModuleBuilder>> modules,
-        ModuleBuilder module, String prefix, int line) {
-        var ModuleBuilder dependentModule = null;
-        var Date dependentModuleRevision = null;
-
-        if(prefix == null) {
-            dependentModule = module;
-        } else if (prefix.equals(module.getPrefix())) {
-            dependentModule = module;
-        } else {
-            val ModuleImport dependentModuleImport = getModuleImport(module, prefix);
-            if (dependentModuleImport === null) {
-                throw new YangParseException(module.getName(), line, "No import found with prefix '" + prefix + "'.");
-            }
-            val String dependentModuleName = dependentModuleImport.getModuleName();
-            dependentModuleRevision = dependentModuleImport.getRevision();
-
-            val TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
-            if (moduleBuildersByRevision === null) {
-                return null;
-            }
-            if (dependentModuleRevision === null) {
-                dependentModule = moduleBuildersByRevision.lastEntry().getValue();
-            } else {
-                dependentModule = moduleBuildersByRevision.get(dependentModuleRevision);
-            }
-        }
-        return dependentModule;
-    }
-
-    /**
-     * Find module from context based on prefix.
-     *
-     * @param context
-     *            schema context
-     * @param currentModule
-     *            current module
-     * @param prefix
-     *            current prefix used to reference dependent module
-     * @param line
-     *            current line in yang model
-     * @return module based on given prefix if found in context, null otherwise
-     */
-    public static def Module findModuleFromContext(SchemaContext context, ModuleBuilder currentModule,
-        String prefix, int line) {
-        if (context === null) {
-            throw new YangParseException(currentModule.getName(), line,
-                "Cannot find module with prefix '" + prefix + "'.");
-        }
-        val modulesByRevision = new TreeMap<Date, Module>();
-
-        val dependentModuleImport = ParserUtils.getModuleImport(currentModule, prefix);
-        if (dependentModuleImport === null) {
-            throw new YangParseException(currentModule.getName(), line, "No import found with prefix '" + prefix + "'.");
-        }
-        val dependentModuleName = dependentModuleImport.getModuleName();
-        val dependentModuleRevision = dependentModuleImport.getRevision();
-
-        for (Module contextModule : context.getModules()) {
-            if (contextModule.getName().equals(dependentModuleName)) {
-                var revision = contextModule.getRevision();
-                if (revision === null) {
-                    revision = new Date(0L);
-                }
-                modulesByRevision.put(revision, contextModule);
-            }
-        }
-
-        var Module result = null;
-        if (dependentModuleRevision === null) {
-            result = modulesByRevision.get(modulesByRevision.firstKey());
-        } else {
-            result = modulesByRevision.get(dependentModuleRevision);
-        }
-        return result;
-    }
-
-    /**
-     * Parse XPath string.
-     *
-     * @param xpathString
-     *            as String
-     * @return SchemaPath from given String
-     */
-    public static def SchemaPath parseXPathString(String xpathString) {
-        val absolute = xpathString.startsWith("/");
-        val String[] splittedPath = xpathString.split("/");
-        val path = new ArrayList<QName>();
-        var QName name;
-        for (String pathElement : splittedPath) {
-            if (pathElement.length() > 0) {
-                val String[] splittedElement = pathElement.split(":");
-                if (splittedElement.length == 1) {
-                    name = new QName(null, null, null, splittedElement.get(0));
-                } else {
-                    name = new QName(null, null, splittedElement.get(0), splittedElement.get(1));
-                }
-                path.add(name);
-            }
-        }
-        return new SchemaPath(path, absolute);
-    }
-
-    public static def dispatch fillAugmentTarget(AugmentationSchemaBuilder augment, Builder target) {
-    }
-
-    /**
-     * Add all augment's child nodes to given target.
-     *
-     * @param augment
-     *            builder of augment statement
-     * @param target
-     *            augmentation target node
-     */
-    public static def dispatch fillAugmentTarget(AugmentationSchemaBuilder augment, DataNodeContainerBuilder target) {
-        for (DataSchemaNodeBuilder child : augment.getChildNodeBuilders()) {
-            val childCopy = CopyUtils.copy(child, target, false);
-            if (augment.parent instanceof UsesNodeBuilder) {
-                setNodeAddedByUses(childCopy);
-            }
-            setNodeAugmenting(childCopy);
-            try {
-                target.addChildNode(childCopy);
-            } catch (YangParseException e) {
-
-                // more descriptive message
-                throw new YangParseException(augment.getModuleName(), augment.getLine(),
-                    "Failed to perform augmentation: " + e.getMessage());
-            }
-        }
-    }
-
-    /**
-     * Add all augment's child nodes to given target.
-     *
-     * @param augment
-     *            builder of augment statement
-     * @param target
-     *            augmentation target choice node
-     */
-    public static def dispatch fillAugmentTarget(AugmentationSchemaBuilder augment, ChoiceBuilder target) {
-        for (DataSchemaNodeBuilder builder : augment.getChildNodeBuilders()) {
-            val childCopy = CopyUtils.copy(builder, target, false);
-            if (augment.parent instanceof UsesNodeBuilder) {
-                setNodeAddedByUses(childCopy);
-            }
-            setNodeAugmenting(childCopy)
-            target.addCase(childCopy);
-        }
-        for (UsesNodeBuilder usesNode : augment.getUsesNodeBuilders()) {
-            if (usesNode !== null) {
-                throw new YangParseException(augment.getModuleName(), augment.getLine(),
-                    "Error in augment parsing: cannot augment choice with nodes from grouping");
-            }
-        }
-    }
-
-    /**
-     * Set augmenting flag to true for node and all its child nodes.
-     */
-    private static def void setNodeAugmenting(DataSchemaNodeBuilder child) {
-        child.setAugmenting(true);
-        if (child instanceof DataNodeContainerBuilder) {
-            val DataNodeContainerBuilder dataNodeChild = child as DataNodeContainerBuilder;
-            for (inner : dataNodeChild.getChildNodeBuilders()) {
-                setNodeAugmenting(inner);
-            }
-        } else if (child instanceof ChoiceBuilder) {
-            val ChoiceBuilder choiceChild = child as ChoiceBuilder;
-            for (inner : choiceChild.cases) {
-                setNodeAugmenting(inner);
-            }
-        }
-    }
-
-    /**
-     * Set addedByUses flag to true for node and all its child nodes. 
-     */
-    public static def void setNodeAddedByUses(GroupingMember child) {
-        child.setAddedByUses(true);
-        if (child instanceof DataNodeContainerBuilder) {
-            val DataNodeContainerBuilder dataNodeChild = child as DataNodeContainerBuilder;
-            for (inner : dataNodeChild.getChildNodeBuilders()) {
-                setNodeAddedByUses(inner);
-            }
-        } else if (child instanceof ChoiceBuilder) {
-            val ChoiceBuilder choiceChild = child as ChoiceBuilder;
-            for (inner : choiceChild.cases) {
-                setNodeAddedByUses(inner);
-            }
-        }
-    }
-
-    public static def void setNodeConfig(DataSchemaNodeBuilder child, Boolean config) {
-        if (child instanceof ContainerSchemaNodeBuilder || child instanceof LeafSchemaNodeBuilder ||
-            child instanceof LeafListSchemaNodeBuilder || child instanceof ListSchemaNodeBuilder ||
-            child instanceof ChoiceBuilder || child instanceof AnyXmlBuilder) {
-            child.setConfiguration(config);
-        }
-        if (child instanceof DataNodeContainerBuilder) {
-            val DataNodeContainerBuilder dataNodeChild = child as DataNodeContainerBuilder;
-            for (inner : dataNodeChild.getChildNodeBuilders()) {
-                setNodeConfig(inner, config);
-            }
-        } else if (child instanceof ChoiceBuilder) {
-            val ChoiceBuilder choiceChild = child as ChoiceBuilder;
-            for (inner : choiceChild.cases) {
-                setNodeConfig(inner, config);
-            }
-        }
-    }
-
-    public static def DataSchemaNodeBuilder findSchemaNode(List<QName> path, SchemaNodeBuilder parentNode) {
-        var DataSchemaNodeBuilder node
-        var SchemaNodeBuilder parent = parentNode
-        var int i = 0;
-        while (i < path.size) {
-            val String name = path.get(i).localName
-            if (parent instanceof DataNodeContainerBuilder) {
-                node = (parent as DataNodeContainerBuilder).getDataChildByName(name)
-            } else if (parent instanceof ChoiceBuilder) {
-                node = (parent as ChoiceBuilder).getCaseNodeByName(name)
-            } else if (parent instanceof RpcDefinitionBuilder) {
-                if ("input".equals(name)) {
-                    node = (parent as RpcDefinitionBuilder).input
-                } else if ("output".equals(name)) {
-                    node = (parent as RpcDefinitionBuilder).output
-                } else {
-                    return null
-                }
-            } else {
-                return null
-            }
-
-            if (i < path.size - 1) {
-                parent = node
-            }
-            i = i + 1
-        }
-
-        return node
-    }
-
-    public static def SchemaNodeBuilder findSchemaNodeInModule(List<QName> pathToNode, ModuleBuilder module) {
-        val List<QName> path = new ArrayList(pathToNode)
-        val QName first = path.remove(0)
-
-        var SchemaNodeBuilder node = module.getDataChildByName(first.localName)
-        if (node == null) {
-            val notifications = module.getAddedNotifications
-            for (notification : notifications) {
-                if (notification.QName.localName.equals(first.localName)) {
-                    node = notification
-                }
-            }
-        }
-        if (node == null) {
-            val rpcs = module.getAddedRpcs
-            for (rpc : rpcs) {
-                if (rpc.QName.localName.equals(first.localName)) {
-                    node = rpc
-                }
-            }
-        }
-        if (node == null) {
-            return null;
-        }
-
-        if (!path.empty) {
-            node = findSchemaNode(path, node)
-        }
-
-        return node
-    }
-
-    /**
-     * Find augment target node and perform augmentation.
-     *
-     * @param augment
-     * @param firstNodeParent
-     *            parent of first node in path
-     * @param path
-     *            path to augment target
-     * @return true if augmentation process succeed, false otherwise
-     */
-    public static def boolean processAugmentation(AugmentationSchemaBuilder augment, ModuleBuilder firstNodeParent) {
-        val path = augment.targetPath.path
-        var Builder targetNode = findSchemaNodeInModule(path, firstNodeParent)
-        if(targetNode === null) return false;
-
-        if (!(targetNode instanceof DataNodeContainerBuilder || targetNode instanceof ChoiceBuilder)) {
-            throw new YangParseException(augment.getModuleName(), augment.getLine(),
-                "Error in augment parsing: The target node MUST be either a container, list, choice, case, input, output, or notification node.");
-        }
-        fillAugmentTarget(augment, targetNode);
-        (targetNode as AugmentationTargetBuilder).addAugmentation(augment);
-        augment.setResolved(true);
-        return true;
-    }
-
-    public static def IdentitySchemaNodeBuilder findBaseIdentity(Map<String, TreeMap<Date, ModuleBuilder>> modules,
-        ModuleBuilder module, String baseString, int line) {
-        var IdentitySchemaNodeBuilder result = null;
-        if (baseString.contains(":")) {
-            val String[] splittedBase = baseString.split(":");
-            if (splittedBase.length > 2) {
-                throw new YangParseException(module.getName(), line,
-                    "Failed to parse identityref base: " + baseString);
-            }
-            val prefix = splittedBase.get(0);
-            val name = splittedBase.get(1);
-            val dependentModule = findModuleFromBuilders(modules, module, prefix, line);
-            if (dependentModule !== null) {
-                result = findIdentity(dependentModule.getAddedIdentities, name);
-            }
-        } else {
-            result = findIdentity(module.getAddedIdentities, baseString);
-        }
-        return result;
-    }
-
-    public static def IdentitySchemaNode findBaseIdentityFromContext(Map<String, TreeMap<Date, ModuleBuilder>> modules,
-        ModuleBuilder module, String baseString, int line, SchemaContext context) {
-        var IdentitySchemaNode result = null;
-
-        val String[] splittedBase = baseString.split(":");
-        if (splittedBase.length > 2) {
-            throw new YangParseException(module.getName(), line, "Failed to parse identityref base: " + baseString);
-        }
-        val prefix = splittedBase.get(0);
-        val name = splittedBase.get(1);
-        val dependentModule = findModuleFromContext(context, module, prefix, line);
-        result = findIdentityNode(dependentModule.identities, name);
-
-        if (result == null) {
-            throw new YangParseException(module.name, line, "Failed to find base identity");
-        }
-        return result;
-    }
-
-    private static def IdentitySchemaNodeBuilder findIdentity(Set<IdentitySchemaNodeBuilder> identities, String name) {
-        for (identity : identities) {
-            if (identity.QName.localName.equals(name)) {
-                return identity;
-            }
-        }
-        return null;
-    }
-
-    private static def IdentitySchemaNode findIdentityNode(Set<IdentitySchemaNode> identities, String name) {
-        for (identity : identities) {
-            if (identity.QName.localName.equals(name)) {
-                return identity;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Get module in which this node is defined.
-     *
-     * @param node
-     * @return builder of module where this node is defined
-     */
-    public static def ModuleBuilder getParentModule(Builder node) {
-        if (node instanceof ModuleBuilder) {
-            return node as ModuleBuilder;
-        }
-        var parent = node.getParent();
-        while (!(parent instanceof ModuleBuilder)) {
-            parent = parent.getParent();
-        }
-        Preconditions.checkState(parent instanceof ModuleBuilder)
-        var parentModule = parent as ModuleBuilder
-        if(parentModule.submodule) {
-           parentModule = parentModule.parent; 
-        }
-        return parentModule;
-    }
-
-    public static def Set<DataSchemaNodeBuilder> wrapChildNodes(String moduleName, int line, Set<DataSchemaNode> nodes,
-        SchemaPath parentPath, URI ns, Date rev, String pref) {
-        val Set<DataSchemaNodeBuilder> result = new HashSet()
-
-        for (DataSchemaNode node : nodes) {
-            val qname = new QName(ns, rev, pref, node.QName.localName)
-            val DataSchemaNodeBuilder wrapped = wrapChildNode(moduleName, line, node, parentPath, qname)
-            result.add(wrapped)
-        }
-        return result
-    }
-
-    public static def DataSchemaNodeBuilder wrapChildNode(String moduleName, int line, DataSchemaNode node,
-        SchemaPath parentPath, QName qname) {
-        val List<QName> path = new ArrayList(parentPath.getPath())
-        path.add(qname)
-        val SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute())
-
-        if (node instanceof AnyXmlSchemaNode) {
-            return new AnyXmlBuilder(moduleName, line, qname, schemaPath, (node as AnyXmlSchemaNode));
-        } else if (node instanceof ChoiceNode) {
-            return new ChoiceBuilder(moduleName, line, qname, schemaPath, (node as ChoiceNode));
-        } else if (node instanceof ContainerSchemaNode) {
-            return new ContainerSchemaNodeBuilder(moduleName, line, qname, schemaPath, (node as ContainerSchemaNode));
-        } else if (node instanceof LeafSchemaNode) {
-            return new LeafSchemaNodeBuilder(moduleName, line, qname, schemaPath, (node as LeafSchemaNode));
-        } else if (node instanceof LeafListSchemaNode) {
-            return new LeafListSchemaNodeBuilder(moduleName, line, qname, schemaPath, (node as LeafListSchemaNode));
-        } else if (node instanceof ListSchemaNode) {
-            return new ListSchemaNodeBuilder(moduleName, line, qname, schemaPath, (node as ListSchemaNode));
-        } else if (node instanceof ChoiceCaseNode) {
-            return new ChoiceCaseBuilder(moduleName, line, qname, schemaPath, (node as ChoiceCaseNode));
-        } else {
-            throw new YangParseException(moduleName, line,
-                "Failed to copy node: Unknown type of DataSchemaNode: " + node)
-        }
-    }
-
-    public static def Set<GroupingBuilder> wrapGroupings(String moduleName, int line, Set<GroupingDefinition> nodes,
-        SchemaPath parentPath, URI ns, Date rev, String pref) {
-        val Set<GroupingBuilder> result = new HashSet()
-        for (GroupingDefinition node : nodes) {
-            val qname = new QName(ns, rev, pref, node.QName.localName)
-            val List<QName> path = new ArrayList(parentPath.getPath())
-            path.add(qname)
-            val SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute())
-            result.add(new GroupingBuilderImpl(moduleName, line, qname, schemaPath, node))
-        }
-        return result
-    }
-
-    public static def Set<TypeDefinitionBuilder> wrapTypedefs(String moduleName, int line, DataNodeContainer dataNode,
-        SchemaPath parentPath, URI ns, Date rev, String pref) {
-        val Set<TypeDefinition<?>> nodes = dataNode.typeDefinitions
-        val Set<TypeDefinitionBuilder> result = new HashSet()
-        for (TypeDefinition<?> node : nodes) {
-            val qname = new QName(ns, rev, pref, node.QName.localName)
-            val List<QName> path = new ArrayList(parentPath.getPath())
-            path.add(qname)
-            val SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute())
-            result.add(new TypeDefinitionBuilderImpl(moduleName, line, qname, schemaPath, (node as ExtendedType)))
-        }
-        return result
-    }
-
-    public static def List<UnknownSchemaNodeBuilder> wrapUnknownNodes(String moduleName, int line,
-        List<UnknownSchemaNode> nodes, SchemaPath parentPath, URI ns, Date rev, String pref) {
-        val List<UnknownSchemaNodeBuilder> result = new ArrayList()
-        for (UnknownSchemaNode node : nodes) {
-            val qname = new QName(ns, rev, pref, node.QName.localName)
-            val List<QName> path = new ArrayList(parentPath.getPath())
-            path.add(qname)
-            val SchemaPath schemaPath = new SchemaPath(path, parentPath.isAbsolute())
-            result.add(new UnknownSchemaNodeBuilder(moduleName, line, qname, schemaPath, node))
-        }
-        return result
-    }
-
-}