Merge branch 'split-mdsal' of ../controller
authorAndrew Grimberg <agrimberg@linuxfoundation.org>
Wed, 19 Aug 2015 20:35:44 +0000 (13:35 -0700)
committerAndrew Grimberg <agrimberg@linuxfoundation.org>
Wed, 19 Aug 2015 20:35:44 +0000 (13:35 -0700)
520 files changed:
code-generator/binding-data-codec/pom.xml [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTree.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTreeFactory.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTreeNode.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeCachingCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeSerializer.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeWriterFactory.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AbstractGenerator.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AbstractStreamWriterGenerator.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AugmentableDataNodeContainerEmitterSource.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataNodeContainerSerializerSource.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataObjectSerializerGenerator.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataObjectSerializerPrototype.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataObjectSerializerSource.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/StreamWriterGenerator.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/spi/AbstractSource.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/spi/StaticConstantDefinition.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AbstractBindingNormalizedNodeCacheHolder.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AugmentationNodeContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingNormalizedNodeCache.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingNormalizedNodeCodecRegistry.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingToNormalizedStreamWriter.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BitsCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeSerializer.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CaseNodeCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CompositeValueCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ContainerNodeCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataContainerCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataContainerCodecPrototype.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataObjectCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/EncapsulatedValueCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/EnumerationCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ForwardingBindingStreamEventWriter.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IdentifiableItemCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IdentityCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IncorrectNestingException.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/InstanceIdentifierCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/KeyedListNodeCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/LazyDataObject.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/LeafNodeCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ListNodeCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingClassInLoadingStrategyException.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaException.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaForClassException.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NodeCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NodeContextSupplier.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NonCachingCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NormalizedNodeWriterWithAddChild.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NotificationCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ReflectionBasedCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/SchemaRootCodecContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/UnionTypeCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/UnionValueOptionContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ValueContext.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ValueTypeCodec.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/util/AugmentableDispatchSerializer.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/util/AugmentationReader.java [new file with mode: 0644]
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/util/ChoiceDispatchSerializer.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AbstractBindingRuntimeTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AugmentationClassDiscoveredAfterCodecTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AugmentationSubstitutionTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/CachingCodecTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/CaseSubstitutionTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/EmptyLeafTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/ExceptionReportingTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierSerializeDeserializeTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/LeafReferenceTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NotificationProcessingTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/RpcDataSerializationTest.java [new file with mode: 0644]
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/UnionTypeTest.java [new file with mode: 0644]
code-generator/binding-generator-api/pom.xml [new file with mode: 0644]
code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/BindingGenerator.java [new file with mode: 0644]
code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/ClassLoadingStrategy.java [new file with mode: 0644]
code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/ModuleInfoRegistry.java [new file with mode: 0644]
code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/package-info.java [new file with mode: 0644]
code-generator/binding-generator-impl/pom.xml [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingSchemaContextUtils.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/CodecTypeUtils.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedClassLoadingStrategy.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/ModuleContext.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/ModuleInfoBackedContext.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/SchemaLock.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGeneratorException.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/YangTemplate.xtend [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/BindingRuntimeContext.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/ClassCustomizer.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/ClassGenerator.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/CodeGenerationException.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/DefaultSourceCodeGenerator.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/FieldGenerator.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/JavassistUtils.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/MethodGenerator.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/NullSourceCodeGenerator.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGenerator.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGeneratorFactory.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/XtendHelper.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/YangSchemaUtils.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/AbstractTypesTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/AugmentRelativeXPathTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/AugmentedTypeTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BaseTypeProvider.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BinaryTypeTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImplTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BitAndUnionTOEnclosingTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ChoiceCaseGenTypesTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ControllerTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/DefinedTypesProviderTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ExtendedTypedefTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GenEnumResolvingTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GenTypesSubSetTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GenerateInnerClassForBitsAndUnionInLeavesTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesBitsTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesLeafrefTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesStringTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/IdentityrefTypeTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/NameTypePattern.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ReplaceAllIllegalCharsTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/SupportTestUtil.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/TypeProviderIntegrationTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/UnionTypeDefTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/UsesTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/NodeWrappedTypeTest.java [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/abstract-topology.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/augment-relative-xpath-models/abstract-topology@2013-02-08.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/augment-relative-xpath-models/augment-abstract-topology@2013-05-03.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/augment-relative-xpath-models/ietf-interfaces@2012-11-15.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/augment-test-models/abstract-topology@2013-02-08.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/augment-test-models/augment-abstract-topology@2013-05-03.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/augment-test-models/augment-network-link-attributes@2013-05-03.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/augment-test-models/augment-topology-tunnels@2013-05-03.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/augment-test-models/ietf-interfaces@2012-11-15.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/binary-type-test-models/binary-type-test.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/binary-type-test-models/binary-types@2013-06-13.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/binding-generator-impl-test/choice-test.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/binding-generator-impl-test/notification-test.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/bit_and_union.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/bit_and_union_in_leaf.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/augment-monitoring@2013-07-01.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/choice-monitoring@2013-07-01.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/controller-models/controller-network.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/controller-models/controller-openflow.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/demo-topology.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/enum-test-models/abstract-topology@2013-02-08.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/enum-test-models/ietf-interfaces@2012-11-15.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/identityref.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/ietf/iana-if-type.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/ietf/ietf-inet-types.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/ietf/ietf-interfaces.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/ietf/ietf-yang-types.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/leafref-test-invalid-model/foo.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/leafref-test-models/abstract-topology@2013-02-08.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/list-composite-key.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/refine.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/simple-bits-demo.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/simple-container-demo.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/simple-leaf-list-demo.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/simple-list-demo.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/simple-string-demo.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/type-provider/test.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/typedef-of-typedef/typedef_of_typedef.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/union-test-models/abstract-topology.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-augment.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-case.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-container.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-dependencies.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-grouping.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-list.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-modul.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-notification.yang [new file with mode: 0644]
code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-rpc.yang [new file with mode: 0644]
code-generator/binding-generator-spi/pom.xml [new file with mode: 0644]
code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/BindingGeneratorServiceProvider.java [new file with mode: 0644]
code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/TypeProvider.java [new file with mode: 0644]
code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/TypeProviderFactory.java [new file with mode: 0644]
code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/package-info.java [new file with mode: 0644]
code-generator/binding-generator-util/pom.xml [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/AbstractBaseType.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingTypes.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/ReferencedTypeImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/TypeConstants.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/Types.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractGeneratedType.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractGeneratedTypeBuilder.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractTypeMember.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractTypeMemberBuilder.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AnnotationTypeBuilderImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/ConstantImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/EnumerationBuilderImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyBuilderImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTypeBuilderImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodParameterImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureBuilderImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureImpl.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/package-info.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/AbstractBaseTypeTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtilTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/BindingTypesTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/ReferencedTypeImplTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/TypesTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractGeneratedTypeBuilderTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractTypeMemberTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AnnotationBuilderTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/ConstantImplTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/EnumerationBuilderImplTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyBuilderImplTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyImplTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderImplTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTypeBuilderTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodParameterImplTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureBuilderImplTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureBuilderTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureImplTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/test/resources/module.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/pom.xml [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractBigRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractPrimitiveRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractSubIntegerRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AlphabeticallyTypeMemberComparator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BaseTemplate.xtend [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BigDecimalRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BigIntegerRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderTemplate.xtend [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ByteRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/Constants.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/EnumGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/EnumTemplate.xtend [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/GeneratorJavaFile.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/GeneratorUtil.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/IntegerRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/InterfaceGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/InterfaceTemplate.xtend [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/LengthGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/LongRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ShortRangeGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/TOGenerator.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/TypeUtils.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionBuilderTemplate.xtend [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionTemplate.xtend [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/YangModuleInfoTemplate.xtend [new file with mode: 0644]
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/package-info.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/AugmentToUsesInAugmentCompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/BaseCompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/Bug1276Test.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/Bug532Test.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CascadeUsesCompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/ClassCodeGeneratorTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTestUtils.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/EndodingInJavaDocTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/GeneratorJavaFileTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/NestedGroupingCompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/TypedefCompilationTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/UnionTypedefUnusedImportTest.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/package-info.java [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/abstract-topology.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/bar.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/baz.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/bar.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/bar.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/baz.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/bug1172/nested-uses-augment.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/bug1276/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/bug1377/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/bug586/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/bar.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/baz.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/class-name-collision/class-name-collision [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/class-name-collision/configuration [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/class-name-collision/other-module [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/context-reference/bar.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/context-reference/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/encoding-javadoc/encoding-javadoc.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/leaf-return-types/test.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/list-gen/test.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/nested-grouping/test.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/typedef/foo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/compilation/union-typedef/union-typedef-test.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/demo-topology.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/list-composite-key.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/simple-container-demo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/simple-leaf-list-demo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/simple-list-demo.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/yang/abstract-topology@2013-02-08.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/yang/iana-if-type@2012-06-05.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/yang/ietf-inet-types@2010-09-24.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/yang/ietf-interfaces@2012-11-15.yang [new file with mode: 0644]
code-generator/binding-java-api-generator/src/test/resources/yang/ietf-yang-types@2010-09-24.yang [new file with mode: 0644]
code-generator/binding-model-api/pom.xml [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/AccessModifier.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/AnnotationType.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/CodeGenerator.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/ConcreteType.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Constant.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/DocumentedType.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Enumeration.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedProperty.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedTransferIdentityObject.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedTransferObject.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedType.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/MethodSignature.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/ParameterizedType.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Restrictions.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Type.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/TypeMember.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/WildcardType.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/package-info.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/AnnotationTypeBuilder.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/ConstantBuilder.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/EnumBuilder.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedPropertyBuilder.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTOBuilder.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTypeBuilder.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTypeBuilderBase.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/MethodSignatureBuilder.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/TypeMemberBuilder.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/package-info.java [new file with mode: 0644]
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/provider/package-info.java [new file with mode: 0644]
code-generator/binding-parent/pom.xml [new file with mode: 0644]
code-generator/binding-test-model/pom.xml [new file with mode: 0644]
code-generator/binding-test-model/src/main/java/org/opendaylight/controller/md/sal/test/model/util/ListsBindingUtils.java [new file with mode: 0644]
code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/binding/rev140701/Int32StringUnionBuilder.java [new file with mode: 0644]
code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/TopLevelBuilder.java [new file with mode: 0644]
code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/UnionTestTypeBuilder.java [new file with mode: 0644]
code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang [new file with mode: 0644]
code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-binding-test.yang [new file with mode: 0644]
code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-union-test.yang [new file with mode: 0644]
code-generator/binding-type-provider/pom.xml [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/BaseYangTypes.java [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/GroupingDefinitionDependencySort.java [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/NodeWrappedType.java [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/UnionDependencySort.java [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/package-info.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/BaseYangTypesTest.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/GroupingDefinitionDependencySortTest.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/LeafrefTypeWithNullToStringInXpath.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/LeafrefTypeWithNullXpath.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/NodeWrappedTypeTest.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TestIntegerTypeDefinition.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TestLeafSchemaNode.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImplTest.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderModel.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderTest.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/UnionDependencySortTest.java [new file with mode: 0644]
code-generator/binding-type-provider/src/test/resources/base-yang-types.yang [new file with mode: 0644]
code-generator/binding-type-provider/src/test/resources/leafref/leafref-absolute-invalid.yang [new file with mode: 0644]
code-generator/binding-type-provider/src/test/resources/leafref/leafref-relative-invalid.yang [new file with mode: 0644]
code-generator/binding-type-provider/src/test/resources/leafref/leafref-valid.yang [new file with mode: 0644]
code-generator/binding-type-provider/src/test/resources/test-type-provider-b.yang [new file with mode: 0644]
code-generator/binding-type-provider/src/test/resources/test-type-provider.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/pom.xml [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/maven/sal/api/gen/plugin/CodeGeneratorImpl.java [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/DocumentationGeneratorImpl.java [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/wadl/generator/WadlRestconfGenerator.xtend [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/wadl/generator/maven/WadlGenerator.java [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/DocGenTest.java [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/YangModuleInfoCompilationTest.java [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/wadl/generator/maven/WadlGenTest.java [new file with mode: 0644]
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/network-topology@2013-07-12.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]
code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/controller-network-rpcs.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/controller-network.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/controller-openflow.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/demo-topology.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/ietf-inet-types@2010-09-24.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/ietf-yang-types@2010-09-24.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/import-module.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/main-module.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/submodule1.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/submodule2.yang [new file with mode: 0644]
code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/submodule3.yang [new file with mode: 0644]
code-generator/pom.xml [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/pom.xml [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/java/Example.java [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/augment-monitoring@2013-07-01.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/bit_and_union_in_leaf.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/choice-monitoring@2013-07-01.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network-ne.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/controller-openflow-ipv6.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/controller-openflow.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/demo-topology.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/ietf-inet-types@2010-09-24.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/ietf-yang-types@2010-09-24.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/simple-string-demo.yang [new file with mode: 0644]
code-generator/samples/maven-code-gen-sample/src/main/yang/typedef_of_typedef.yang [new file with mode: 0644]
code-generator/samples/modeling-sample/pom.xml [new file with mode: 0644]
code-generator/samples/modeling-sample/src/main/yang/toaster.yang [new file with mode: 0644]
code-generator/src/site/site.xml [new file with mode: 0644]
model/iana/iana-afn-safi/pom.xml [new file with mode: 0644]
model/iana/iana-afn-safi/src/main/yang/iana-afn-safi@2013-07-04.yang [new file with mode: 0644]
model/iana/iana-if-type-2014-05-08/pom.xml [new file with mode: 0644]
model/iana/iana-if-type-2014-05-08/src/main/yang/iana-if-type@2014-05-08.yang [new file with mode: 0644]
model/iana/iana-if-type/pom.xml [new file with mode: 0644]
model/iana/iana-if-type/src/main/yang/iana-if-type@2013-07-04.yang [new file with mode: 0644]
model/iana/pom.xml [new file with mode: 0644]
model/iana/src/main/yang/.gitignore [new file with mode: 0644]
model/ietf/ietf-inet-types/pom.xml [new file with mode: 0644]
model/ietf/ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/HostBuilder.java [new file with mode: 0644]
model/ietf/ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/IpAddressBuilder.java [new file with mode: 0644]
model/ietf/ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/IpPrefixBuilder.java [new file with mode: 0644]
model/ietf/ietf-inet-types/src/main/yang/ietf-inet-types.yang [new file with mode: 0644]
model/ietf/ietf-inet-types/src/test/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/HostBuilderTest.java [new file with mode: 0644]
model/ietf/ietf-interfaces/pom.xml [new file with mode: 0644]
model/ietf/ietf-interfaces/src/main/yang/ietf-interfaces.yang [new file with mode: 0644]
model/ietf/ietf-restconf/pom.xml [new file with mode: 0644]
model/ietf/ietf-restconf/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/DatastoreIdentifierBuilder.java [new file with mode: 0644]
model/ietf/ietf-restconf/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/restconf/restconf/modules/ModuleRevisionBuilder.java [new file with mode: 0644]
model/ietf/ietf-restconf/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/restconf/restconf/modules/RevisionBuilder.java [new file with mode: 0644]
model/ietf/ietf-restconf/src/main/yang/ietf-restconf@2013-10-19.yang [new file with mode: 0644]
model/ietf/ietf-restconf/src/test/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/restconf/restconf/modules/RevisionBuilderTest.java [new file with mode: 0644]
model/ietf/ietf-ted/pom.xml [new file with mode: 0644]
model/ietf/ietf-ted/src/main/yang/ted@2013-07-12.yang [new file with mode: 0644]
model/ietf/ietf-ted/src/main/yang/ted@2013-10-21.yang [new file with mode: 0644]
model/ietf/ietf-topology-isis/pom.xml [new file with mode: 0644]
model/ietf/ietf-topology-isis/src/main/yang/isis-topology@2013-07-12.yang [new file with mode: 0644]
model/ietf/ietf-topology-isis/src/main/yang/isis-topology@2013-10-21.yang [new file with mode: 0644]
model/ietf/ietf-topology-l3-unicast-igp/pom.xml [new file with mode: 0644]
model/ietf/ietf-topology-l3-unicast-igp/src/main/yang/l3-unicast-igp-topology@2013-07-12.yang [new file with mode: 0644]
model/ietf/ietf-topology-l3-unicast-igp/src/main/yang/l3-unicast-igp-topology@2013-10-21.yang [new file with mode: 0644]
model/ietf/ietf-topology-ospf/pom.xml [new file with mode: 0644]
model/ietf/ietf-topology-ospf/src/main/yang/ospf-topology@2013-07-12.yang [new file with mode: 0644]
model/ietf/ietf-topology-ospf/src/main/yang/ospf-topology@2013-10-21.yang [new file with mode: 0644]
model/ietf/ietf-topology/pom.xml [new file with mode: 0644]
model/ietf/ietf-topology/src/main/yang/network-topology@2013-07-12.yang [new file with mode: 0644]
model/ietf/ietf-topology/src/main/yang/network-topology@2013-10-21.yang [new file with mode: 0644]
model/ietf/ietf-yang-types-20130715/pom.xml [new file with mode: 0644]
model/ietf/ietf-yang-types-20130715/src/main/yang/ietf-yang-types@2013-07-15.yang [new file with mode: 0644]
model/ietf/ietf-yang-types/pom.xml [new file with mode: 0644]
model/ietf/ietf-yang-types/src/main/yang/ietf-yang-types.yang [new file with mode: 0644]
model/ietf/pom.xml [new file with mode: 0644]
model/ietf/src/main/yang/.gitignore [new file with mode: 0644]
model/l2-types/pom.xml [new file with mode: 0644]
model/l2-types/src/main/yang/opendaylight-l2-types.yang [new file with mode: 0644]
model/pom.xml [new file with mode: 0644]
model/src/main/yang/.gitignore [new file with mode: 0644]
model/src/site/site.xml [new file with mode: 0644]
model/yang-ext/pom.xml [new file with mode: 0644]
model/yang-ext/src/main/yang/yang-ext.yang [new file with mode: 0644]
yang/yang-binding/pom.xml [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentable.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentation.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AugmentationHolder.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BaseIdentity.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingCodec.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingDeserializer.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingMapping.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingSerializer.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingStreamEventWriter.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/ChildOf.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataContainer.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObject.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectSerializer.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectSerializerImplementation.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectSerializerRegistry.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataRoot.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Identifiable.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Identifier.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierBuilderImpl.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifier.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Notification.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/NotificationListener.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/RpcImplementation.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/RpcInput.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/RpcService.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/YangModelBindingProvider.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/YangModuleInfo.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/annotations/ModuleQName.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/annotations/QName.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/annotations/RoutingContext.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/package-info.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/AbstractMappedRpcInvoker.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/AugmentationFieldGetter.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/BindingReflections.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/ClassBasedRpcServiceInvoker.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/ClassLoaderUtils.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/DataObjectReadingUtil.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/LocalNameRpcServiceInvoker.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/NotificationListenerInvoker.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/QNameRpcServiceInvoker.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcMethodInvoker.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcMethodInvokerWithInput.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcMethodInvokerWithoutInput.java [new file with mode: 0644]
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcServiceInvoker.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierTest.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/FooChild.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/GroupingFoo.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/InstantiatedFoo.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/Node.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeChild.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeChildKey.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeKey.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/Nodes.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/util/BindingReflectionsTest.java [new file with mode: 0644]
yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/util/DataObjectReadingUtilTest.java [new file with mode: 0644]

diff --git a/code-generator/binding-data-codec/pom.xml b/code-generator/binding-data-codec/pom.xml
new file mode 100644 (file)
index 0000000..f6a179f
--- /dev/null
@@ -0,0 +1,97 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>binding-data-codec</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.javassist</groupId>
+            <artifactId>javassist</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-type-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-test-model</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+            <dependency><groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <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>
+                        <Export-Package>
+                            org.opendaylight.yangtools.binding.data.codec.*,
+                            org.opendaylight.yangtools.binding.data.codec.gen.impl.*,
+                            org.opendaylight.yangtools.binding.data.codec.impl.*,
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTree.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTree.java
new file mode 100644 (file)
index 0000000..ea28281
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.api;
+
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+/**
+ *
+ * Navigable tree representing hierarchy of Binding to Normalized Node codecs
+ *
+ * This navigable tree is associated to conrete set of YANG models, represented
+ * by SchemaContext and provides access to subtree specific serialization
+ * context.
+ *
+ * TODO: Add more detailed documentation
+ **/
+public interface BindingCodecTree {
+
+      @Nullable <T extends DataObject> BindingCodecTreeNode<T> getSubtreeCodec(InstanceIdentifier<T> path);
+
+      @Nullable BindingCodecTreeNode<?> getSubtreeCodec(YangInstanceIdentifier path);
+
+      @Nullable BindingCodecTreeNode<?> getSubtreeCodec(SchemaPath path);
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTreeFactory.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTreeFactory.java
new file mode 100644 (file)
index 0000000..25f45be
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public interface BindingCodecTreeFactory {
+
+    /**
+     *
+     * Creates Binding Codec Tree for specified Binding runtime context.
+     *
+     * @param context
+     *            Binding Runtime Context for which Binding codecs should be
+     *            instantiated.
+     * @return Binding Codec Tree for specified Binding runtime context.
+     */
+    BindingCodecTree create(BindingRuntimeContext context);
+
+    /**
+     *
+     * Creates Binding Codec Tree for specified Binding runtime context.
+     *
+     * @param context
+     *            Binding Runtime Context for which Binding codecs should be
+     *            instantiated.
+     * @param bindingClasses
+     *            Binding Runtime Context will be constructed using bindings
+     *            which contains specified classes, in order to support
+     *            deserialization in multi-classloader environment.
+     * @return Binding Codec Tree for specified Binding runtime context.
+     */
+    @Beta
+   BindingCodecTree create(SchemaContext context, Class<?>... bindingClasses);
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTreeNode.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingCodecTreeNode.java
new file mode 100644 (file)
index 0000000..bc9c1a3
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.api;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableCollection;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+
+/**
+ * Subtree codec specific to model subtree between Java Binding and
+ * NormalizedNode.
+ *
+ */
+@Beta
+public interface BindingCodecTreeNode<T extends DataObject> extends BindingNormalizedNodeCodec<T> {
+
+    /**
+     *
+     * Returns binding class of interface which represents API of current
+     * schema node.
+     *
+     * The result is same as invoking {@link DataObject#getImplementedInterface()}
+     * on instance of data.
+     *
+     * @return interface which defines API of binding representation of data.
+     */
+    @Nonnull
+    Class<T> getBindingClass();
+
+    /**
+     *
+     * Returns child context as if it was walked by
+     * {@link BindingStreamEventWriter}. This means that to enter case, one must
+     * issue getChild(ChoiceClass).getChild(CaseClass).
+     *
+     * @param childClass Child class by Biding Stream navigation
+     * @return Context of child
+     * @throws IllegalArgumentException
+     *             If supplied child class is not valid in specified context.
+     */
+    @Nonnull
+    <E extends DataObject> BindingCodecTreeNode<E> streamChild(@Nonnull Class<E> childClass);
+
+    /**
+     *
+     * Returns child context as if it was walked by
+     * {@link BindingStreamEventWriter}. This means that to enter case, one must
+     * issue getChild(ChoiceClass).getChild(CaseClass).
+     *
+     * This method differs from {@link #streamChild(Class)}, that is less
+     * stricter for interfaces representing augmentation and cases, that
+     * may return {@link BindingCodecTreeNode} even if augmentation interface
+     * containing same data was supplied and does not represent augmentation
+     * of this node.
+     *
+     * @param childClass
+     * @return Context of child or Optional absent is supplied class is not
+     *         applicable in context.
+     */
+    <E extends DataObject> Optional<? extends BindingCodecTreeNode<E>> possibleStreamChild(@Nonnull Class<E> childClass);
+
+    /**
+     * Returns nested node context using supplied YANG Instance Identifier
+     *
+     * @param child
+     *            Yang Instance Identifier Argument
+     * @return Context of child
+     * @throws IllegalArgumentException
+     *             If supplied argument does not represent valid child.
+     */
+    @Nonnull
+    BindingCodecTreeNode<?> yangPathArgumentChild(@Nonnull YangInstanceIdentifier.PathArgument child);
+
+    /**
+     * Returns nested node context using supplied Binding Instance Identifier
+     * and adds YANG instance identifiers to supplied list.
+     *
+     * @param arg
+     *            Binding Instance Identifier Argument
+     * @param builder
+     *            Mutable instance of list, which is appended by YangInstanceIdentifiers
+     *            as tree is walked. Use null if such side-product is not needed.
+     * @return Context of child
+     * @throws IllegalArgumentException
+     *             If supplied argument does not represent valid child.
+     */
+    @Nonnull
+    BindingCodecTreeNode<?> bindingPathArgumentChild(@Nonnull InstanceIdentifier.PathArgument arg,
+            @Nullable List<YangInstanceIdentifier.PathArgument> builder);
+
+    /**
+     *
+     * Returns codec which uses caches serialization / deserialization results
+     *
+     * Caching may introduce performance penalty to serialization / deserialization
+     * but may decrease use of heap for repetitive objects.
+     *
+     *
+     * @param cacheSpecifier Set of objects, for which cache may be in place
+     * @return Codec whihc uses cache for serialization / deserialization.
+     */
+    @Nonnull
+    BindingNormalizedNodeCachingCodec<T> createCachingCodec(@Nonnull
+            ImmutableCollection<Class<? extends DataObject>> cacheSpecifier);
+
+    @Beta
+    void writeAsNormalizedNode(T data, NormalizedNodeStreamWriter writer);
+
+    /**
+     * Serializes path argument for current node.
+     *
+     * @param arg Binding Path Argument, may be null if Binding Instance Identifier does not have
+     *        representation for current node (e.g. choice or case).
+     * @return Yang Path Argument, may be null if Yang Instance Identifier does not have
+     *         representation for current node (e.g. case).
+     * @throws IllegalArgumentException If supplied {@code arg} is not valid.
+     */
+    @Beta
+    @Nullable YangInstanceIdentifier.PathArgument serializePathArgument(@Nullable InstanceIdentifier.PathArgument arg);
+
+    /**
+     * Deserializes path argument for current node.
+     *
+     * @param arg Yang Path Argument, may be null if Yang Instance Identifier does not have
+     *         representation for current node (e.g. case).
+     * @return Binding Path Argument, may be null if Binding Instance Identifier does not have
+     *        representation for current node (e.g. choice or case).
+     * @throws IllegalArgumentException If supplied {@code arg} is not valid.
+     */
+    @Beta
+    @Nullable InstanceIdentifier.PathArgument deserializePathArgument(@Nullable YangInstanceIdentifier.PathArgument arg);
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeCachingCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeCachingCodec.java
new file mode 100644 (file)
index 0000000..f0a41ae
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.api;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ * Caching variant of Binding to Normalized Node codec.
+ *
+ * Caching may introduce performance penalty to serialization / deserialization
+ * but may decrease use of heap for repetitive objects.
+ *
+ * @param <T> Binding representtion of data
+ */
+@Beta
+public interface BindingNormalizedNodeCachingCodec<T extends DataObject> extends BindingNormalizedNodeCodec<T>, AutoCloseable {
+    /**
+     * Invoking close will invalidate this codec and any of its child
+     * codecs and will invalidate cache.
+     *
+     * Any subsequent calls to this codec will fail with {@link IllegalStateException}
+     * thrown.
+     */
+    @Override
+    void close();
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeCodec.java
new file mode 100644 (file)
index 0000000..ca48ea8
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.api;
+
+import com.google.common.annotations.Beta;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+/**
+ *
+ * Codec providing serialization and deserializiation between Binding
+ * and NormalizedNode representation of data.
+ *
+ *
+ * @param <T> Binding representation of data
+ */
+@Beta
+public interface BindingNormalizedNodeCodec<T extends DataObject> {
+
+    /**
+     * Converts from Normalized Node to Binding representation of data.
+     *
+     * @param data Normalized Node representation of data
+     * @return Binding representation of data
+     */
+    @Nonnull T deserialize(@Nonnull NormalizedNode<?,?> data);
+
+    /**
+     * Converts from  Binding to Normalized Node representation of data.
+     *
+     * @param data Binding representation of data
+     * @return Normalized Node representation of data
+     */
+    @Nonnull NormalizedNode<?,?> serialize(@Nonnull T data);
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeSerializer.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeSerializer.java
new file mode 100644 (file)
index 0000000..d16fa50
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.binding.data.codec.api;
+
+import java.util.Map.Entry;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+/**
+ * Serialization service, which provides two-way serialization between Java
+ * Binding Data representation and NormalizedNode representation.
+ */
+public interface BindingNormalizedNodeSerializer {
+
+    /**
+     * Translates supplied Binding Instance Identifier into NormalizedNode
+     * instance identifier.
+     *
+     * @param binding
+     *            Binding Instance Identifier
+     * @return DOM Instance Identifier
+     * @throws IllegalArgumentException
+     *             If supplied Instance Identifier is not valid.
+     */
+    YangInstanceIdentifier toYangInstanceIdentifier(@Nonnull InstanceIdentifier<?> binding);
+
+    /**
+     * Translates supplied YANG Instance Identifier into Binding instance
+     * identifier.
+     *
+     * @param dom
+     *            YANG Instance Identifier
+     * @return Binding Instance Identifier, or null if the instance identifier
+     *         is not representable.
+     */
+    @Nullable
+    InstanceIdentifier<?> fromYangInstanceIdentifier(@Nonnull YangInstanceIdentifier dom);
+
+    /**
+     * Translates supplied Binding Instance Identifier and data into
+     * NormalizedNode representation.
+     *
+     * @param path
+     *            Binding Instance Identifier pointing to data
+     * @param data
+     *            Data object representing data
+     * @return NormalizedNode representation
+     * @throws IllegalArgumentException
+     *             If supplied Instance Identifier is not valid.
+     */
+    <T extends DataObject> Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> toNormalizedNode(
+            InstanceIdentifier<T> path, T data);
+
+    /**
+     * Translates supplied YANG Instance Identifier and NormalizedNode into
+     * Binding data.
+     *
+     * @param path Binding Instance Identifier
+     * @param data NormalizedNode representing data
+     * @return DOM Instance Identifier
+     */
+    @Nullable
+    Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode(@Nonnull YangInstanceIdentifier path,
+            NormalizedNode<?, ?> data);
+
+    /**
+     * Translates supplied NormalizedNode Notification into Binding data.
+     *
+     * @param path Schema Path of Notification, schema path is absolute, and consists of Notification QName.
+     * @param data NormalizedNode representing data
+     * @return Binding representation of Notification
+     */
+    @Nullable Notification fromNormalizedNodeNotification(@Nonnull SchemaPath path,@Nonnull ContainerNode data);
+
+    /**
+     * Translates supplied NormalizedNode RPC input or output into Binding data.
+     *
+     * @param path Schema path of RPC data, Schema path consists of rpc QName and input / output QName.
+     * @param data NormalizedNode representing data
+     * @return Binding representation of RPC data
+     */
+    @Nullable DataObject fromNormalizedNodeRpcData(@Nonnull SchemaPath path,@Nonnull ContainerNode data);
+
+    /**
+     * Translates supplied Binding Notification or output into NormalizedNode notification.
+     *
+     * @param data NormalizedNode representing notification data
+     * @return NormalizedNode representation of notification
+     */
+    @Nonnull ContainerNode toNormalizedNodeNotification(@Nonnull Notification data);
+
+    /**
+     * Translates supplied Binding RPC input or output into NormalizedNode data.
+     *
+     * @param data NormalizedNode representing rpc data
+     * @return NormalizedNode representation of rpc data
+     */
+    @Nonnull ContainerNode toNormalizedNodeRpcData(@Nonnull DataContainer data);
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeWriterFactory.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/api/BindingNormalizedNodeWriterFactory.java
new file mode 100644 (file)
index 0000000..fe8bb26
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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.binding.data.codec.api;
+
+import java.util.Map.Entry;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+
+/**
+ *
+ * Factory for {@link BindingStreamEventWriter}, which provides stream writers
+ * which translates data and delegates calls to
+ * {@link NormalizedNodeStreamWriter}.
+ *
+ */
+public interface BindingNormalizedNodeWriterFactory {
+
+    /**
+     *
+     * Creates a {@link BindingStreamEventWriter} for data tree path which will
+     * translate to NormalizedNode model and invoke proper events on supplied
+     * {@link NormalizedNodeStreamWriter}.
+     * <p>
+     * Also provides translation of supplied Instance Identifier to
+     * {@link YangInstanceIdentifier} so client code, does not need to translate
+     * that separately.
+     * <p>
+     * If {@link YangInstanceIdentifier} is not needed, please use
+     * {@link #newWriter(InstanceIdentifier, NormalizedNodeStreamWriter)}
+     * method to conserve resources.
+     *
+     * @param path
+     *            Binding Path in conceptual data tree, for which writer should
+     *            be instantiated
+     * @param domWriter
+     *            Stream writer on which events will be invoked.
+     * @return Instance Identifier and {@link BindingStreamEventWriter}
+     *         which will write to supplied {@link NormalizedNodeStreamWriter}.
+     * @throws IllegalArgumentException If supplied Instance Identifier is not valid.
+     */
+    @Nonnull Entry<YangInstanceIdentifier, BindingStreamEventWriter> newWriterAndIdentifier(@Nonnull InstanceIdentifier<?> path,
+            @Nonnull NormalizedNodeStreamWriter domWriter);
+
+    /**
+     *
+     * Creates a {@link BindingStreamEventWriter} for data tree path which will
+     * translate to NormalizedNode model and invoke proper events on supplied
+     * {@link NormalizedNodeStreamWriter}.
+     * <p>
+     *
+     * This variation does not provide YANG instance identifier and is useful
+     * for use-cases, where {@link InstanceIdentifier} translation is done
+     * in other way, or YANG instance identifier is unnecessary (e.g. notifications, RPCs).
+     *
+     * @param path Binding Path in conceptual data tree, for which writer should
+     *            be instantiated
+     * @param domWriter Stream writer on which events will be invoked.
+     * @return {@link BindingStreamEventWriter}
+     *         which will write to supplied {@link NormalizedNodeStreamWriter}.
+     * @throws IllegalArgumentException If supplied Instance Identifier is not valid.
+     */
+    @Nonnull
+    BindingStreamEventWriter newWriter(@Nonnull InstanceIdentifier<?> path,
+            @Nonnull NormalizedNodeStreamWriter domWriter);
+
+    /**
+     *
+     * Creates a {@link BindingStreamEventWriter} for rpc data which will
+     * translate to NormalizedNode model and invoke proper events on supplied
+     * {@link NormalizedNodeStreamWriter}.
+     *
+     * @param rpcInputOrOutput Binding class representing RPC input or output,
+     *            for which writer should be instantiated
+     * @param domWriter
+     *            Stream writer on which events will be invoked.
+     * @return {@link BindingStreamEventWriter} which will write to supplied
+     *         {@link NormalizedNodeStreamWriter}.
+     */
+    @Nonnull
+    BindingStreamEventWriter newRpcWriter(@Nonnull Class<? extends DataContainer> rpcInputOrOutput,
+            @Nonnull NormalizedNodeStreamWriter domWriter);
+
+    /**
+     *
+     * Creates a {@link BindingStreamEventWriter} for notification which will
+     * translate to NormalizedNode model and invoke proper events on supplied
+     * {@link NormalizedNodeStreamWriter}.
+     *
+     * @param notification Binding class representing notification,
+     *            for which writer should be instantiated
+     * @param domWriter
+     *            Stream writer on which events will be invoked.
+     * @return {@link BindingStreamEventWriter} which will write to supplied
+     *         {@link NormalizedNodeStreamWriter}.
+     */
+    @Nonnull
+    BindingStreamEventWriter newNotificationWriter(@Nonnull Class<? extends Notification> notification,
+            @Nonnull NormalizedNodeStreamWriter domWriter);
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AbstractGenerator.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AbstractGenerator.java
new file mode 100644 (file)
index 0000000..3d35c03
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * 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.binding.data.codec.gen.impl;
+
+/**
+ * Package-private base class for sharing the loading capability.
+ */
+abstract class AbstractGenerator {
+    /**
+     * Ensure that the serializer class for specified class is loaded
+     * and return its name.
+     *
+     * @param cls Data object class
+     * @return Serializer class name
+     */
+    protected abstract String loadSerializerFor(final Class<?> cls);
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AbstractStreamWriterGenerator.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AbstractStreamWriterGenerator.java
new file mode 100644 (file)
index 0000000..8efdc87
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * 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.binding.data.codec.gen.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Map.Entry;
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.Modifier;
+import javassist.NotFoundException;
+import org.opendaylight.yangtools.binding.data.codec.gen.spi.StaticConstantDefinition;
+import org.opendaylight.yangtools.binding.data.codec.util.AugmentableDispatchSerializer;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.ClassCustomizer;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractStreamWriterGenerator extends AbstractGenerator implements DataObjectSerializerGenerator {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractStreamWriterGenerator.class);
+
+    protected static final String SERIALIZE_METHOD_NAME = "serialize";
+    protected static final AugmentableDispatchSerializer AUGMENTABLE = new AugmentableDispatchSerializer();
+    private static final Field FIELD_MODIFIERS;
+
+    private final LoadingCache<Class<?>, DataObjectSerializerImplementation> implementations;
+    private final CtClass[] serializeArguments;
+    private final JavassistUtils javassist;
+    private BindingRuntimeContext context;
+
+    static {
+        /*
+         * Cache reflection access to field modifiers field. We need this to set
+         * fix the static declared fields to final once we initialize them. If we
+         * cannot get access, that's fine, too.
+         */
+        Field f = null;
+        try {
+            f = Field.class.getDeclaredField("modifiers");
+            f.setAccessible(true);
+        } catch (NoSuchFieldException | SecurityException e) {
+            LOG.warn("Could not get Field modifiers field, serializers run at decreased efficiency", e);
+        }
+
+        FIELD_MODIFIERS = f;
+    }
+
+    protected AbstractStreamWriterGenerator(final JavassistUtils utils) {
+        super();
+        this.javassist = Preconditions.checkNotNull(utils,"JavassistUtils instance is required.");
+        this.serializeArguments = new CtClass[] {
+                javassist.asCtClass(DataObjectSerializerRegistry.class),
+                javassist.asCtClass(DataObject.class),
+                javassist.asCtClass(BindingStreamEventWriter.class),
+        };
+        javassist.appendClassLoaderIfMissing(DataObjectSerializerPrototype.class.getClassLoader());
+        this.implementations = CacheBuilder.newBuilder().weakKeys().build(new SerializerImplementationLoader());
+    }
+
+    @Override
+    public final DataObjectSerializerImplementation getSerializer(final Class<?> type) {
+        return implementations.getUnchecked(type);
+    }
+
+    @Override
+    public final void onBindingRuntimeContextUpdated(final BindingRuntimeContext runtime) {
+        this.context = runtime;
+    }
+
+    @Override
+    protected final String loadSerializerFor(final Class<?> cls) {
+        return implementations.getUnchecked(cls).getClass().getName();
+    }
+
+    private final class SerializerImplementationLoader extends CacheLoader<Class<?>, DataObjectSerializerImplementation> {
+
+        private static final String GETINSTANCE_METHOD_NAME = "getInstance";
+        private static final String SERIALIZER_SUFFIX = "$StreamWriter";
+
+        private String getSerializerName(final Class<?> type) {
+            return type.getName() + SERIALIZER_SUFFIX;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public DataObjectSerializerImplementation load(final Class<?> type) throws Exception {
+            Preconditions.checkArgument(BindingReflections.isBindingClass(type));
+            Preconditions.checkArgument(DataContainer.class.isAssignableFrom(type),"DataContainer is not assingnable from %s from classloader %s.",type,type.getClassLoader());
+
+            final String serializerName = getSerializerName(type);
+
+            Class<? extends DataObjectSerializerImplementation> cls;
+            try {
+                cls = (Class<? extends DataObjectSerializerImplementation>) ClassLoaderUtils
+                        .loadClass(type.getClassLoader(), serializerName);
+            } catch (final ClassNotFoundException e) {
+                cls = generateSerializer(type, serializerName);
+            }
+
+            final DataObjectSerializerImplementation obj =
+                    (DataObjectSerializerImplementation) cls.getDeclaredMethod(GETINSTANCE_METHOD_NAME).invoke(null);
+            LOG.debug("Loaded serializer {} for class {}", obj, type);
+            return obj;
+        }
+
+        private Class<? extends DataObjectSerializerImplementation> generateSerializer(final Class<?> type,
+                final String serializerName) throws CannotCompileException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, NoSuchFieldException {
+            final DataObjectSerializerSource source = generateEmitterSource(type, serializerName);
+            final CtClass poolClass = generateEmitter0(type, source, serializerName);
+            @SuppressWarnings("unchecked")
+            final Class<? extends DataObjectSerializerImplementation> cls = poolClass.toClass(type.getClassLoader(), type.getProtectionDomain());
+
+            /*
+             * Due to OSGi class loader rules we cannot initialize the fields during
+             * construction, as the initializer expressions do not see our implementation
+             * classes. This should be almost as good as that, as we are resetting the
+             * fields to final before ever leaking the class.
+             */
+            for (final StaticConstantDefinition constant : source.getStaticConstants()) {
+                final Field field = cls.getDeclaredField(constant.getName());
+                field.setAccessible(true);
+                field.set(null, constant.getValue());
+
+                if (FIELD_MODIFIERS != null) {
+                    FIELD_MODIFIERS.setInt(field, field.getModifiers() | Modifier.FINAL);
+                }
+            }
+
+            return cls;
+        }
+    }
+
+    private DataObjectSerializerSource generateEmitterSource(final Class<?> type, final String serializerName) {
+        Types.typeForClass(type);
+        javassist.appendClassLoaderIfMissing(type.getClassLoader());
+        final Entry<GeneratedType, Object> typeWithSchema = context.getTypeWithSchema(type);
+        final GeneratedType generatedType = typeWithSchema.getKey();
+        final Object schema = typeWithSchema.getValue();
+
+        final DataObjectSerializerSource source;
+        if (schema instanceof ContainerSchemaNode) {
+            source = generateContainerSerializer(generatedType, (ContainerSchemaNode) schema);
+        } else if (schema instanceof ListSchemaNode){
+            final ListSchemaNode casted = (ListSchemaNode) schema;
+            if (casted.getKeyDefinition().isEmpty()) {
+                source = generateUnkeyedListEntrySerializer(generatedType, casted);
+            } else {
+                source = generateMapEntrySerializer(generatedType, casted);
+            }
+        } else if(schema instanceof AugmentationSchema) {
+            source = generateSerializer(generatedType,(AugmentationSchema) schema);
+        } else if(schema instanceof ChoiceCaseNode) {
+            source = generateCaseSerializer(generatedType,(ChoiceCaseNode) schema);
+        } else if(schema instanceof NotificationDefinition) {
+            source = generateNotificationSerializer(generatedType,(NotificationDefinition) schema);
+        } else {
+            throw new UnsupportedOperationException("Schema type " + schema.getClass() + " is not supported");
+        }
+        return source;
+    }
+
+    private CtClass generateEmitter0(final Class<?> type, final DataObjectSerializerSource source, final String serializerName) {
+        final CtClass product;
+        try {
+            product = javassist.instantiatePrototype(DataObjectSerializerPrototype.class.getName(), serializerName, new ClassCustomizer() {
+                @Override
+                public void customizeClass(final CtClass cls) throws CannotCompileException, NotFoundException {
+                    /* getSerializerBody() has side effects, such as loading classes
+                     * and codecs, it should be run in model class loader in order to
+                     * correctly reference load child classes
+                     */
+                    final String body = ClassLoaderUtils.withClassLoader(type.getClassLoader(), new Supplier<String>() {
+                            @Override
+                            public String get() {
+                                return source.getSerializerBody().toString();
+                            }
+                        }
+                    );
+
+                    // Generate any static fields
+                    for (final StaticConstantDefinition def : source.getStaticConstants()) {
+                        final CtField field = new CtField(javassist.asCtClass(def.getType()), def.getName(), cls);
+                        field.setModifiers(Modifier.PRIVATE + Modifier.STATIC);
+                        cls.addField(field);
+                    }
+
+                    // Replace serialize() -- may reference static fields
+                    final CtMethod serializeTo = cls.getDeclaredMethod(SERIALIZE_METHOD_NAME, serializeArguments);
+                    serializeTo.setBody(body);
+
+                    // The prototype is not visible, so we need to take care of that
+                    cls.setModifiers(Modifier.setPublic(cls.getModifiers()));
+                }
+            });
+        } catch (final NotFoundException e) {
+            LOG.error("Failed to instatiate serializer {}", source, e);
+            throw new LinkageError("Unexpected instantation problem: serializer prototype not found", e);
+        }
+        return product;
+    }
+
+    /**
+     * Generates serializer source code for supplied container node,
+     * which will read supplied binding type and invoke proper methods
+     * on supplied {@link BindingStreamEventWriter}.
+     * <p>
+     * Implementation is required to recursively invoke events
+     * for all reachable binding objects.
+     *
+     * @param type Binding type of container
+     * @param node Schema of container
+     * @return Source for container node writer
+     */
+    protected abstract DataObjectSerializerSource generateContainerSerializer(GeneratedType type, ContainerSchemaNode node);
+
+    /**
+     * Generates serializer source for supplied case node,
+     * which will read supplied binding type and invoke proper methods
+     * on supplied {@link BindingStreamEventWriter}.
+     * <p>
+     * Implementation is required to recursively invoke events
+     * for all reachable binding objects.
+     *
+     * @param type Binding type of case
+     * @param node Schema of case
+     * @return Source for case node writer
+     */
+    protected abstract DataObjectSerializerSource generateCaseSerializer(GeneratedType type, ChoiceCaseNode node);
+
+    /**
+     * Generates serializer source for supplied list node,
+     * which will read supplied binding type and invoke proper methods
+     * on supplied {@link BindingStreamEventWriter}.
+     * <p>
+     * Implementation is required to recursively invoke events
+     * for all reachable binding objects.
+     *
+     * @param type Binding type of list
+     * @param node Schema of list
+     * @return Source for list node writer
+     */
+    protected abstract DataObjectSerializerSource generateMapEntrySerializer(GeneratedType type, ListSchemaNode node);
+
+    /**
+     * Generates serializer source for supplied list node,
+     * which will read supplied binding type and invoke proper methods
+     * on supplied {@link BindingStreamEventWriter}.
+     * <p>
+     * Implementation is required to recursively invoke events
+     * for all reachable binding objects.
+     *
+     * @param type Binding type of list
+     * @param node Schema of list
+     * @return Source for list node writer
+     */
+    protected abstract DataObjectSerializerSource generateUnkeyedListEntrySerializer(GeneratedType type, ListSchemaNode node);
+
+    /**
+     * Generates serializer source for supplied augmentation node,
+     * which will read supplied binding type and invoke proper methods
+     * on supplied {@link BindingStreamEventWriter}.
+     * <p>
+     * Implementation is required to recursively invoke events
+     * for all reachable binding objects.
+     *
+     * @param type Binding type of augmentation
+     * @param schema Schema of augmentation
+     * @return Source for augmentation node writer
+     */
+    protected abstract DataObjectSerializerSource generateSerializer(GeneratedType type, AugmentationSchema schema);
+
+    /**
+     * Generates serializer source for notification node,
+     * which will read supplied binding type and invoke proper methods
+     * on supplied {@link BindingStreamEventWriter}.
+     * <p>
+     * Implementation is required to recursively invoke events
+     * for all reachable binding objects.
+     *
+     * @param type Binding type of notification
+     * @param node Schema of notification
+     * @return Source for notification node writer
+     */
+    protected abstract DataObjectSerializerSource generateNotificationSerializer(GeneratedType type, NotificationDefinition node);
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AugmentableDataNodeContainerEmitterSource.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/AugmentableDataNodeContainerEmitterSource.java
new file mode 100644 (file)
index 0000000..7614e77
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.binding.data.codec.gen.impl;
+
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+
+abstract class AugmentableDataNodeContainerEmitterSource extends DataNodeContainerSerializerSource {
+    private static final String AUGMENTABLE_SERIALIZER = "AUGMENTABLE_SERIALIZER";
+
+    public AugmentableDataNodeContainerEmitterSource(final AbstractStreamWriterGenerator generator, final GeneratedType type, final DataNodeContainer node) {
+        super(generator, type, node);
+        /*
+         * Eventhough intuition says the serializer could reference the generator directly,
+         * that is not true in OSGi environment -- so we need to resolve the reference first
+         * and inject it as a static constant.
+         */
+        staticConstant(AUGMENTABLE_SERIALIZER, DataObjectSerializerImplementation.class, StreamWriterGenerator.AUGMENTABLE);
+    }
+
+    @Override
+    protected void emitAfterBody(final StringBuilder b) {
+        b.append(statement(invoke(AUGMENTABLE_SERIALIZER, "serialize", REGISTRY, INPUT, STREAM)));
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataNodeContainerSerializerSource.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataNodeContainerSerializerSource.java
new file mode 100644 (file)
index 0000000..d9094ac
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2014, 2015 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.binding.data.codec.gen.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.HashMap;
+import java.util.Map;
+import org.opendaylight.yangtools.binding.data.codec.util.ChoiceDispatchSerializer;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.BindingSerializer;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+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.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSource {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DataNodeContainerSerializerSource.class);
+
+    protected static final String INPUT = "_input";
+    private static final String CHOICE_PREFIX = "CHOICE_";
+
+    protected final DataNodeContainer schemaNode;
+    private final GeneratedType dtoType;
+
+    DataNodeContainerSerializerSource(final AbstractGenerator generator, final GeneratedType type, final DataNodeContainer node) {
+        super(generator);
+        this.dtoType = Preconditions.checkNotNull(type);
+        this.schemaNode = Preconditions.checkNotNull(node);
+    }
+
+    /**
+     * Return the character sequence which should be used for start event.
+     *
+     * @return Start event character sequence
+     */
+    protected abstract CharSequence emitStartEvent();
+
+    @Override
+    protected CharSequence getSerializerBody() {
+        final StringBuilder b = new StringBuilder();
+        b.append("{\n");
+        b.append(statement(assign(DataObjectSerializerRegistry.class.getName(), REGISTRY, "$1")));
+        b.append(statement(assign(dtoType.getFullyQualifiedName(), INPUT,
+                cast(dtoType.getFullyQualifiedName(), "$2"))));
+        b.append(statement(assign(BindingStreamEventWriter.class.getName(), STREAM, cast(BindingStreamEventWriter.class.getName(), "$3"))));
+        b.append(statement(assign(BindingSerializer.class.getName(), SERIALIZER, null)));
+        b.append("if (");
+        b.append(STREAM);
+        b.append(" instanceof ");
+        b.append(BindingSerializer.class.getName());
+        b.append(") {");
+        b.append(statement(assign(SERIALIZER, cast(BindingSerializer.class.getName(), STREAM))));
+        b.append('}');
+        b.append(statement(emitStartEvent()));
+
+        emitBody(b);
+        emitAfterBody(b);
+        b.append(statement(endNode()));
+        b.append(statement("return null"));
+        b.append('}');
+        return b;
+    }
+
+    /**
+     * Allows for customization of emitting code, which is processed after
+     * normal DataNodeContainer body. Ideal for augmentations or others.
+     */
+    protected void emitAfterBody(final StringBuilder b) {
+        // No-op
+    }
+
+    private static Map<String, Type> collectAllProperties(final GeneratedType type, final Map<String, Type> hashMap) {
+        for (final MethodSignature definition : type.getMethodDefinitions()) {
+            hashMap.put(definition.getName(), definition.getReturnType());
+        }
+        for (final Type parent : type.getImplements()) {
+            if (parent instanceof GeneratedType) {
+                collectAllProperties((GeneratedType) parent, hashMap);
+            }
+        }
+        return hashMap;
+    }
+
+    private static String getGetterName(final DataSchemaNode node) {
+        final TypeDefinition<?> type ;
+        if (node instanceof LeafSchemaNode) {
+            type = ((LeafSchemaNode) node).getType();
+        } else if(node instanceof LeafListSchemaNode) {
+            type = ((LeafListSchemaNode) node).getType();
+        } else {
+            type = null;
+        }
+        String prefix = "get";
+        if(type != null) {
+            TypeDefinition<?> rootType = type;
+            while (rootType.getBaseType() != null) {
+                rootType = rootType.getBaseType();
+            }
+            if(rootType instanceof BooleanTypeDefinition || rootType instanceof EmptyTypeDefinition) {
+                prefix = "is";
+            }
+        }
+
+        return prefix + BindingMapping.getClassName(node.getQName().getLocalName());
+    }
+
+    private void emitBody(final StringBuilder b) {
+        final Map<String, Type> getterToType = collectAllProperties(dtoType, new HashMap<String, Type>());
+        for (final DataSchemaNode schemaChild : schemaNode.getChildNodes()) {
+            if (!schemaChild.isAugmenting()) {
+                final String getter = getGetterName(schemaChild);
+                final Type childType = getterToType.get(getter);
+                if (childType == null) {
+                    // FIXME AnyXml nodes are ignored, since their type cannot be found in generated bindnig
+                    // Bug-706 https://bugs.opendaylight.org/show_bug.cgi?id=706
+                    if (schemaChild instanceof AnyXmlSchemaNode) {
+                        LOG.warn("Node {} will be ignored. AnyXml is not yet supported from binding aware code." +
+                                "Binding Independent code can be used to serialize anyXml nodes.", schemaChild.getPath());
+                        continue;
+                    } else {
+                        throw new IllegalStateException(
+                                String.format("Unable to find type for child node %s. Expected child nodes: %s",
+                                        schemaChild.getPath(), getterToType));
+                    }
+                }
+                emitChild(b, getter, childType, schemaChild);
+            }
+        }
+    }
+
+    private void emitChild(final StringBuilder b, final String getterName, final Type childType,
+            final DataSchemaNode schemaChild) {
+        b.append(statement(assign(childType, getterName, cast(childType, invoke(INPUT, getterName)))));
+
+        b.append("if (").append(getterName).append(" != null) {\n");
+        emitChildInner(b, getterName, childType, schemaChild);
+        b.append("}\n");
+    }
+
+    private void emitChildInner(final StringBuilder b, final String getterName, final Type childType,
+            final DataSchemaNode child) {
+        if (child instanceof LeafSchemaNode) {
+            b.append(statement(leafNode(child.getQName().getLocalName(), getterName)));
+        } else if (child instanceof AnyXmlSchemaNode) {
+            b.append(statement(anyxmlNode(child.getQName().getLocalName(), getterName)));
+        } else if (child instanceof LeafListSchemaNode) {
+            b.append(statement(startLeafSet(child.getQName().getLocalName(),invoke(getterName, "size"))));
+            final Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0];
+            b.append(forEach(getterName, valueType, statement(leafSetEntryNode(CURRENT))));
+            b.append(statement(endNode()));
+        } else if (child instanceof ListSchemaNode) {
+            final Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0];
+            final ListSchemaNode casted = (ListSchemaNode) child;
+            emitList(b, getterName, valueType, casted);
+        } else if (child instanceof ContainerSchemaNode) {
+            b.append(tryToUseCacheElse(getterName,statement(staticInvokeEmitter(childType, getterName))));
+        } else if (child instanceof ChoiceSchemaNode) {
+            final String propertyName = CHOICE_PREFIX + childType.getName();
+            staticConstant(propertyName, DataObjectSerializerImplementation.class, ChoiceDispatchSerializer.from(loadClass(childType)));
+            b.append(tryToUseCacheElse(getterName,statement(invoke(propertyName, StreamWriterGenerator.SERIALIZE_METHOD_NAME, REGISTRY, cast(DataObject.class.getName(),getterName), STREAM))));
+        }
+    }
+
+    private StringBuilder tryToUseCacheElse(final String getterName, final CharSequence statement) {
+        final StringBuilder b = new StringBuilder();
+
+        b.append("if ( ");
+        b.append(SERIALIZER).append("== null || ");
+        b.append(invoke(SERIALIZER, "serialize", getterName)).append("== null");
+        b.append(") {");
+        b.append(statement);
+        b.append("}");
+        return b;
+    }
+
+    private void emitList(final StringBuilder b, final String getterName, final Type valueType,
+            final ListSchemaNode child) {
+        final CharSequence startEvent;
+
+        b.append(statement(assign("int", "_count", invoke(getterName, "size"))));
+        if (child.getKeyDefinition().isEmpty()) {
+            startEvent = startUnkeyedList(classReference(valueType), "_count");
+        } else if (child.isUserOrdered()) {
+            startEvent = startOrderedMapNode(classReference(valueType), "_count");
+        } else {
+            startEvent = startMapNode(classReference(valueType), "_count");
+        }
+        b.append(statement(startEvent));
+        b.append(forEach(getterName, valueType, tryToUseCacheElse(CURRENT,statement(staticInvokeEmitter(valueType, CURRENT)))));
+        b.append(statement(endNode()));
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataObjectSerializerGenerator.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataObjectSerializerGenerator.java
new file mode 100644 (file)
index 0000000..7ec766c
--- /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.binding.data.codec.gen.impl;
+
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
+
+/**
+ * Public interface exposed from generator implementation.
+ */
+public interface DataObjectSerializerGenerator {
+    /**
+     * Get a serializer for a particular type.
+     *
+     * @param type Type class
+     * @return Serializer instance.
+     */
+    DataObjectSerializerImplementation getSerializer(Class<?> type);
+
+    /**
+     * Notify the generator that the runtime context has been updated.
+     * @param runtime New runtime context
+     */
+    void onBindingRuntimeContextUpdated(BindingRuntimeContext runtime);
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataObjectSerializerPrototype.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataObjectSerializerPrototype.java
new file mode 100644 (file)
index 0000000..3f38f26
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.binding.data.codec.gen.impl;
+
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
+
+/**
+ * Prototype of a DataObjectSerializerImplementation. This is a template class, which the
+ * {@link AbstractStreamWriterGenerator} uses to instantiate {@link DataObjectSerializerImplementation}
+ * on a per-type basis. During that time, the {@link #serialize(DataObjectSerializerRegistry, DataObject, BindingStreamEventWriter)}
+ * method will be replaced by the real implementation.
+ */
+final class DataObjectSerializerPrototype implements DataObjectSerializerImplementation {
+    private static final DataObjectSerializerPrototype INSTANCE = new DataObjectSerializerPrototype();
+
+    private DataObjectSerializerPrototype() {
+        // Intentionally hidden, subclasses can replace it
+    }
+
+    /**
+     * Return the shared serializer instance.
+     *
+     * @return Global singleton instance.
+     */
+    public static DataObjectSerializerPrototype getInstance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public void serialize(final DataObjectSerializerRegistry reg, final DataObject obj, final BindingStreamEventWriter stream) {
+        throw new UnsupportedOperationException("Prototype body, this code should never be invoked.");
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataObjectSerializerSource.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/DataObjectSerializerSource.java
new file mode 100644 (file)
index 0000000..30f5f77
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * 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.binding.data.codec.gen.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.binding.data.codec.gen.spi.AbstractSource;
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
+
+abstract class DataObjectSerializerSource extends AbstractSource {
+
+    private static final ClassLoadingStrategy STRATEGY = GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy();
+
+    protected static final String SERIALIZER = "_serializer";
+    protected static final String STREAM = "_stream";
+    protected static final String ITERATOR = "_iterator";
+    protected static final String CURRENT = "_current";
+    protected static final String REGISTRY = "_registry";
+
+    private final AbstractGenerator generator;
+
+    /**
+     * @param generator Parent generator
+     */
+    DataObjectSerializerSource(final AbstractGenerator generator) {
+        this.generator = Preconditions.checkNotNull(generator);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected Class<? extends DataContainer> loadClass(final Type childType) {
+        try {
+            return (Class<? extends DataContainer>) STRATEGY.loadClass(childType);
+        } catch (final ClassNotFoundException e) {
+            throw new IllegalStateException("Could not load referenced class ", e);
+        }
+    }
+
+    /**
+     * Returns body of static serialize method.
+     *
+     * <ul>
+     * <li> {@link DataObjectSerializerRegistry} - registry of serializers
+     * <li> {@link DataObject} - object to be serialized
+     * <li> {@link BindingStreamEventWriter} - writer to which events should be serialized.
+     * </ul>
+     *
+     * @return Valid javassist code describing static serialization body.
+     */
+    protected abstract CharSequence getSerializerBody();
+
+    protected final CharSequence leafNode(final String localName, final CharSequence value) {
+        return invoke(STREAM, "leafNode", escape(localName), value);
+    }
+
+    protected final CharSequence startLeafSet(final String localName,final CharSequence expected) {
+        return invoke(STREAM, "startLeafSet", escape(localName),expected);
+    }
+
+    protected final CharSequence leafSetEntryNode(final CharSequence value) {
+        return invoke(STREAM, "leafSetEntryNode", value);
+    }
+
+    protected final CharSequence startContainerNode(final CharSequence type, final CharSequence expected) {
+        return invoke(STREAM, "startContainerNode", (type),expected);
+    }
+
+    protected final CharSequence escape(final String localName) {
+        return '"' + localName + '"';
+    }
+
+    protected final CharSequence startUnkeyedList(final CharSequence type, final CharSequence expected) {
+        return invoke(STREAM, "startUnkeyedList", (type),expected);
+    }
+
+    protected final CharSequence startUnkeyedListItem(final CharSequence expected) {
+        return invoke(STREAM, "startUnkeyedListItem",expected);
+    }
+
+    protected final CharSequence startMapNode(final CharSequence type,final CharSequence expected) {
+        return invoke(STREAM, "startMapNode", (type),expected);
+    }
+
+    protected final CharSequence startOrderedMapNode(final CharSequence type,final CharSequence expected) {
+        return invoke(STREAM, "startOrderedMapNode", (type),expected);
+    }
+
+    protected final CharSequence startMapEntryNode(final CharSequence key, final CharSequence expected) {
+        return invoke(STREAM,"startMapEntryNode",key,expected);
+    }
+
+    protected final CharSequence startAugmentationNode(final CharSequence key) {
+        return invoke(STREAM,"startAugmentationNode",key);
+    }
+
+    protected final CharSequence startChoiceNode(final CharSequence localName,final CharSequence expected) {
+        return invoke(STREAM, "startChoiceNode", (localName),expected);
+    }
+
+    protected final CharSequence startCaseNode(final CharSequence localName,final CharSequence expected) {
+        return invoke(STREAM, "startCase", (localName),expected);
+    }
+
+    protected final CharSequence anyxmlNode(final String name, final String value) throws IllegalArgumentException {
+        return invoke(STREAM, "anyxmlNode", escape(name),name);
+    }
+
+    protected final CharSequence endNode() {
+        return invoke(STREAM, "endNode");
+    }
+
+    protected final CharSequence forEach(final String iterable,final Type valueType,final CharSequence body) {
+        return forEach(iterable, ITERATOR, valueType.getFullyQualifiedName(), CURRENT, body);
+    }
+
+    protected final CharSequence classReference(final Type type) {
+        return type.getFullyQualifiedName() + ".class";
+    }
+
+    protected final CharSequence staticInvokeEmitter(final Type childType, final String name) {
+        final Class<?> cls;
+        try {
+            cls = STRATEGY.loadClass(childType);
+        } catch (final ClassNotFoundException e) {
+            throw new IllegalStateException("Failed to invoke emitter", e);
+        }
+
+        final String className = this.generator.loadSerializerFor(cls) + ".getInstance()";
+        return invoke(className, AbstractStreamWriterGenerator.SERIALIZE_METHOD_NAME, REGISTRY, name, STREAM);
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/StreamWriterGenerator.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/impl/StreamWriterGenerator.java
new file mode 100644 (file)
index 0000000..46c6ab2
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * 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.binding.data.codec.gen.impl;
+
+import org.opendaylight.yangtools.binding.data.codec.util.AugmentableDispatchSerializer;
+import org.opendaylight.yangtools.binding.data.codec.util.ChoiceDispatchSerializer;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+
+/**
+ * Concrete implementation of {@link AbstractStreamWriterGenerator}
+ * which in runtime generates classes implementing {@link DataObjectSerializerImplementation}
+ * interface and are used to serialize Binding {@link DataObject}.
+ *
+ * Actual implementation of codecs is done via static methods, which allows
+ * for static wiring of codecs. Choice codec and Augmentable codecs
+ * are static properties of parent codec and stateless implementations
+ * are used ( {@link ChoiceDispatchSerializer}, {@link AugmentableDispatchSerializer},
+ * which uses registry to dispatch to concrete item codec.
+ *
+ */
+public class StreamWriterGenerator extends AbstractStreamWriterGenerator {
+
+
+    private static final String UNKNOWN_SIZE = BindingStreamEventWriter.class.getName() + ".UNKNOWN_SIZE";
+
+    private StreamWriterGenerator(final JavassistUtils utils, final Void ignore) {
+        super(utils);
+    }
+
+    /**
+     * Deprecated, use {@link #create(JavassistUtils)} instead.
+     * @param utils
+     */
+    @Deprecated
+    public StreamWriterGenerator(final JavassistUtils utils) {
+        this(utils, null);
+    }
+
+    /**
+     * Create a new instance backed by a specific {@link JavassistUtils} instance.
+     *
+     * @param utils JavassistUtils instance to use
+     * @return A new generator
+     */
+    public static DataObjectSerializerGenerator create(final JavassistUtils utils) {
+        return new StreamWriterGenerator(utils, null);
+    }
+
+    private static CharSequence getChildSizeFromSchema(final DataNodeContainer node) {
+        return Integer.toString(node.getChildNodes().size());
+    }
+
+
+    @Override
+    protected DataObjectSerializerSource generateContainerSerializer(final GeneratedType type, final ContainerSchemaNode node) {
+
+        return new AugmentableDataNodeContainerEmitterSource(this, type, node) {
+            @Override
+            public CharSequence emitStartEvent() {
+                return startContainerNode(classReference(type), UNKNOWN_SIZE);
+            }
+        };
+    }
+
+    @Override
+    protected DataObjectSerializerSource generateNotificationSerializer(final GeneratedType type, final NotificationDefinition node) {
+
+        return new AugmentableDataNodeContainerEmitterSource(this, type, node) {
+            @Override
+            public CharSequence emitStartEvent() {
+                return startContainerNode(classReference(type), UNKNOWN_SIZE);
+            }
+        };
+    }
+
+    @Override
+    protected DataObjectSerializerSource generateCaseSerializer(final GeneratedType type, final ChoiceCaseNode node) {
+        return new AugmentableDataNodeContainerEmitterSource(this, type, node) {
+            @Override
+            public CharSequence emitStartEvent() {
+                return startCaseNode(classReference(type),UNKNOWN_SIZE);
+            }
+        };
+    }
+
+    @Override
+    protected DataObjectSerializerSource generateUnkeyedListEntrySerializer(final GeneratedType type, final ListSchemaNode node) {
+        return new AugmentableDataNodeContainerEmitterSource(this, type, node) {
+
+            @Override
+            public CharSequence emitStartEvent() {
+                return startUnkeyedListItem(UNKNOWN_SIZE);
+            }
+        };
+    }
+
+    @Override
+    protected DataObjectSerializerSource generateSerializer(final GeneratedType type, final AugmentationSchema schema) {
+        return new DataNodeContainerSerializerSource(this, type, schema) {
+
+            @Override
+            public CharSequence emitStartEvent() {
+                return startAugmentationNode(classReference(type));
+            }
+        };
+    }
+
+    @Override
+    protected DataObjectSerializerSource generateMapEntrySerializer(final GeneratedType type, final ListSchemaNode node) {
+        return new AugmentableDataNodeContainerEmitterSource(this, type, node) {
+            @Override
+            public CharSequence emitStartEvent() {
+                return startMapEntryNode(invoke(INPUT, "getKey"), UNKNOWN_SIZE);
+            }
+        };
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/spi/AbstractSource.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/spi/AbstractSource.java
new file mode 100644 (file)
index 0000000..4d19b4e
--- /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.binding.data.codec.gen.spi;
+
+import com.google.common.collect.Iterators;
+import com.google.common.collect.UnmodifiableIterator;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+public abstract class AbstractSource {
+
+    private final Set<StaticConstantDefinition> staticConstants = new HashSet<>();
+
+    public final <T> void staticConstant(final String name, final Class<T> type, final T value) {
+        staticConstants.add(new StaticConstantDefinition(name, type, value));
+    }
+
+    public final Set<StaticConstantDefinition> getStaticConstants() {
+        return Collections.unmodifiableSet(staticConstants);
+    }
+
+    protected final CharSequence invoke(final CharSequence object, final String methodName, final Object... args) {
+        StringBuilder builder = new StringBuilder();
+        if (object != null) {
+            builder.append(object);
+            builder.append('.');
+        }
+        builder.append(methodName);
+        builder.append('(');
+
+        UnmodifiableIterator<Object> iterator = Iterators.forArray(args);
+        while (iterator.hasNext()) {
+            builder.append(iterator.next());
+            if (iterator.hasNext()) {
+                builder.append(',');
+            }
+        }
+        builder.append(')');
+        return builder;
+    }
+
+    protected final CharSequence assign(final String var, final CharSequence value) {
+        return assign((String) null, var, value);
+    }
+
+    protected final CharSequence assign(final String type, final String var, final CharSequence value) {
+        StringBuilder builder = new StringBuilder();
+        if(type != null) {
+            builder.append(type);
+            builder.append(' ');
+        }
+        builder.append(var);
+        builder.append(" = ");
+        builder.append(value);
+        return builder;
+    }
+
+    protected final CharSequence assign(final Type type, final String var, final CharSequence value) {
+        return assign(type.getFullyQualifiedName(), var, value);
+    }
+
+    protected final CharSequence cast(final Type type, final CharSequence value) {
+        return cast(type.getFullyQualifiedName(), value);
+    }
+
+    protected final CharSequence forEach(final String iterable,final String iteratorName, final String valueType,final String valueName, final CharSequence body) {
+        StringBuilder b = new StringBuilder();
+        b.append(statement(assign(java.util.Iterator.class.getName(), iteratorName,invoke(iterable, "iterator"))));
+        b.append("while (").append(invoke(iteratorName, "hasNext")).append(") {\n");
+        b.append(statement(assign(valueType, valueName,cast(valueType, invoke(iteratorName, "next")))));
+        b.append(body);
+        b.append("\n}\n");
+        return b;
+    }
+
+    protected final CharSequence statement(final CharSequence statement) {
+        return new StringBuilder().append(statement).append(";\n");
+    }
+
+    protected final CharSequence cast(final String type, final CharSequence value) {
+        StringBuilder builder = new StringBuilder();
+        builder.append("((");
+        builder.append(type);
+        builder.append(") ");
+        builder.append(value);
+        builder.append(')');
+        return builder;
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/spi/StaticConstantDefinition.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/gen/spi/StaticConstantDefinition.java
new file mode 100644 (file)
index 0000000..72ba33b
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.binding.data.codec.gen.spi;
+
+import com.google.common.base.Preconditions;
+
+/**
+ *
+ * Definition of static property for generated class
+ * <p>
+ * This definition consists of
+ * <ul>
+ * <li>name - property name</li>
+ * <li>type - Java type for property</li>
+ * <li>value - value to which property should be initialized</li>
+ * </ul>
+ */
+public class StaticConstantDefinition {
+
+    private final String name;
+    private final Class<?> type;
+    private final Object value;
+
+    public StaticConstantDefinition(final String name, final Class<?> type, final Object value) {
+        super();
+        this.name = Preconditions.checkNotNull(name);
+        this.type = Preconditions.checkNotNull(type);
+        this.value = Preconditions.checkNotNull(value);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public Class<?> getType() {
+        return type;
+    }
+
+    public Object getValue() {
+        return value;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + name.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        StaticConstantDefinition other = (StaticConstantDefinition) obj;
+        if (!name.equals(other.name)) {
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AbstractBindingNormalizedNodeCacheHolder.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AbstractBindingNormalizedNodeCacheHolder.java
new file mode 100644 (file)
index 0000000..07d7464
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+/**
+ *
+ * Abstract Holder of Binding to Normalized Node caches indexed by {@link DataContainerCodecContext}
+ * to which cache is associated.
+ *
+ */
+abstract class AbstractBindingNormalizedNodeCacheHolder {
+
+    private final Set<Class<? extends DataObject>> cachedValues;
+    private final LoadingCache<DataContainerCodecContext<?, ?>, BindingNormalizedNodeCache> caches = CacheBuilder
+            .newBuilder().build(new CacheLoader<DataContainerCodecContext<?, ?>, BindingNormalizedNodeCache>() {
+
+                @Override
+                public BindingNormalizedNodeCache load(final DataContainerCodecContext<?, ?> key) throws Exception {
+                    return new BindingNormalizedNodeCache(AbstractBindingNormalizedNodeCacheHolder.this, key);
+                }
+
+            });
+
+    protected AbstractBindingNormalizedNodeCacheHolder(final Set<Class<? extends DataObject>> cacheSpec) {
+        cachedValues = Preconditions.checkNotNull(cacheSpec);
+    }
+
+    BindingNormalizedNodeCache getCachingSerializer(final DataContainerCodecContext<?, ?> childCtx) {
+        if (isCached(childCtx.getBindingClass())) {
+            return caches.getUnchecked(childCtx);
+        }
+        return null;
+    }
+
+    boolean isCached(final Class<?> type) {
+        return cachedValues.contains(type);
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AugmentationNodeContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/AugmentationNodeContext.java
new file mode 100644 (file)
index 0000000..dd9e41d
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+
+final class AugmentationNodeContext<D extends DataObject & Augmentation<?>> extends DataObjectCodecContext<D,AugmentationSchema> {
+
+    public AugmentationNodeContext(final DataContainerCodecPrototype<AugmentationSchema> prototype) {
+        super(prototype);
+    }
+
+    @Override
+    public D deserialize(final NormalizedNode<?, ?> normalizedNode) {
+        Preconditions.checkArgument(normalizedNode instanceof AugmentationNode);
+        return createBindingProxy((AugmentationNode)normalizedNode);
+    }
+
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingCodecContext.java
new file mode 100644 (file)
index 0000000..93067c6
--- /dev/null
@@ -0,0 +1,364 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.Callable;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTree;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeNode;
+import org.opendaylight.yangtools.binding.data.codec.impl.NodeCodecContext.CodecContextFactory;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+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.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class BindingCodecContext implements CodecContextFactory, BindingCodecTree, Immutable {
+    private static final Logger LOG = LoggerFactory.getLogger(BindingCodecContext.class);
+    static final String GETTER_PREFIX = "get";
+
+    private final Codec<YangInstanceIdentifier, InstanceIdentifier<?>> instanceIdentifierCodec;
+    private final Codec<QName, Class<?>> identityCodec;
+    private final BindingNormalizedNodeCodecRegistry registry;
+    private final BindingRuntimeContext context;
+    private final SchemaRootCodecContext<?> root;
+
+    BindingCodecContext(final BindingRuntimeContext context, final BindingNormalizedNodeCodecRegistry registry) {
+        this.context = Preconditions.checkNotNull(context, "Binding Runtime Context is required.");
+        this.root = SchemaRootCodecContext.create(this);
+        this.identityCodec = new IdentityCodec(context);
+        this.instanceIdentifierCodec = new InstanceIdentifierCodec(this);
+        this.registry = Preconditions.checkNotNull(registry);
+    }
+
+    @Override
+    public BindingRuntimeContext getRuntimeContext() {
+        return context;
+    }
+
+    Codec<YangInstanceIdentifier, InstanceIdentifier<?>> getInstanceIdentifierCodec() {
+        return instanceIdentifierCodec;
+    }
+
+    public Codec<QName, Class<?>> getIdentityCodec() {
+        return identityCodec;
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    @Override
+    public DataObjectSerializer getEventStreamSerializer(final Class<?> type) {
+        return registry.getSerializer((Class) type);
+    }
+
+    public Entry<YangInstanceIdentifier, BindingStreamEventWriter> newWriter(final InstanceIdentifier<?> path,
+            final NormalizedNodeStreamWriter domWriter) {
+        final List<YangInstanceIdentifier.PathArgument> yangArgs = new LinkedList<>();
+        final DataContainerCodecContext<?,?> codecContext = getCodecContextNode(path, yangArgs);
+        return new SimpleEntry<>(YangInstanceIdentifier.create(yangArgs), codecContext.createWriter(domWriter));
+    }
+
+    public BindingStreamEventWriter newWriterWithoutIdentifier(final InstanceIdentifier<?> path,
+            final NormalizedNodeStreamWriter domWriter) {
+        return getCodecContextNode(path, null).createWriter(domWriter);
+    }
+
+    BindingStreamEventWriter newRpcWriter(final Class<? extends DataContainer> rpcInputOrOutput,
+            final NormalizedNodeStreamWriter domWriter) {
+        return root.getRpc(rpcInputOrOutput).createWriter(domWriter);
+    }
+
+    BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification> notification,
+            final NormalizedNodeStreamWriter domWriter) {
+        return root.getNotification(notification).createWriter(domWriter);
+    }
+
+    public DataContainerCodecContext<?,?> getCodecContextNode(final InstanceIdentifier<?> binding,
+            final List<YangInstanceIdentifier.PathArgument> builder) {
+        DataContainerCodecContext<?,?> currentNode = root;
+        for (final InstanceIdentifier.PathArgument bindingArg : binding.getPathArguments()) {
+            currentNode = currentNode.bindingPathArgumentChild(bindingArg, builder);
+            Preconditions.checkArgument(currentNode != null, "Supplied Instance Identifier %s is not valid.",binding);
+        }
+        return currentNode;
+    }
+
+    /**
+     * Multi-purpose utility function. Traverse the codec tree, looking for
+     * the appropriate codec for the specified {@link YangInstanceIdentifier}.
+     * As a side-effect, gather all traversed binding {@link InstanceIdentifier.PathArgument}s
+     * into the supplied collection.
+     *
+     * @param dom {@link YangInstanceIdentifier} which is to be translated
+     * @param bindingArguments Collection for traversed path arguments
+     * @return Codec for target node, or @null if the node does not have a
+     *         binding representation (choice, case, leaf).
+     *
+     */
+    @Nullable NodeCodecContext<?> getCodecContextNode(final @Nonnull YangInstanceIdentifier dom,
+            final @Nullable Collection<InstanceIdentifier.PathArgument> bindingArguments) {
+        NodeCodecContext<?> currentNode = root;
+        ListNodeCodecContext<?> currentList = null;
+
+        for (final YangInstanceIdentifier.PathArgument domArg : dom.getPathArguments()) {
+            Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?,?>, "Unexpected child of non-container node %s", currentNode);
+            final DataContainerCodecContext<?,?> previous = (DataContainerCodecContext<?,?>) currentNode;
+            final NodeCodecContext<?> nextNode = previous.yangPathArgumentChild(domArg);
+
+            /*
+             * List representation in YANG Instance Identifier consists of two
+             * arguments: first is list as a whole, second is list as an item so
+             * if it is /list it means list as whole, if it is /list/list - it
+             * is wildcarded and if it is /list/list[key] it is concrete item,
+             * all this variations are expressed in Binding Aware Instance
+             * Identifier as Item or IdentifiableItem
+             */
+            if (currentList != null) {
+                Preconditions.checkArgument(currentList == nextNode, "List should be referenced two times in YANG Instance Identifier %s", dom);
+
+                // We entered list, so now we have all information to emit
+                // list path using second list argument.
+                if (bindingArguments != null) {
+                    bindingArguments.add(currentList.getBindingPathArgument(domArg));
+                }
+                currentList = null;
+                currentNode = nextNode;
+            } else if (nextNode instanceof ListNodeCodecContext) {
+                // We enter list, we do not update current Node yet,
+                // since we need to verify
+                currentList = (ListNodeCodecContext<?>) nextNode;
+            } else if (nextNode instanceof ChoiceNodeCodecContext) {
+                // We do not add path argument for choice, since
+                // it is not supported by binding instance identifier.
+                currentNode = nextNode;
+            } else if (nextNode instanceof DataContainerCodecContext<?,?>) {
+                if (bindingArguments != null) {
+                    bindingArguments.add(((DataContainerCodecContext<?,?>) nextNode).getBindingPathArgument(domArg));
+                }
+                currentNode = nextNode;
+            } else if (nextNode instanceof LeafNodeCodecContext) {
+                LOG.debug("Instance identifier referencing a leaf is not representable (%s)", dom);
+                return null;
+            }
+        }
+
+        // Algorithm ended in list as whole representation
+        // we sill need to emit identifier for list
+        if (currentNode instanceof ChoiceNodeCodecContext) {
+            LOG.debug("Instance identifier targeting a choice is not representable (%s)", dom);
+            return null;
+        }
+        if (currentNode instanceof CaseNodeCodecContext) {
+            LOG.debug("Instance identifier targeting a case is not representable (%s)", dom);
+            return null;
+        }
+
+        if (currentList != null) {
+            if(bindingArguments != null) {
+                bindingArguments.add(currentList.getBindingPathArgument(null));
+            }
+            return currentList;
+        }
+        return currentNode;
+    }
+
+    NotificationCodecContext<?> getNotificationContext(final SchemaPath notification) {
+        return root.getNotification(notification);
+    }
+
+    ContainerNodeCodecContext<?> getRpcDataContext(final SchemaPath path) {
+        return root.getRpc(path);
+    }
+
+    @Override
+    public ImmutableMap<String, LeafNodeCodecContext<?>> getLeafNodes(final Class<?> parentClass,
+            final DataNodeContainer childSchema) {
+        final Map<String, DataSchemaNode> getterToLeafSchema = new HashMap<>();
+        for (final DataSchemaNode leaf : childSchema.getChildNodes()) {
+            final TypeDefinition<?> typeDef;
+            if (leaf instanceof LeafSchemaNode) {
+                typeDef = ((LeafSchemaNode) leaf).getType();
+            } else if (leaf instanceof LeafListSchemaNode) {
+                typeDef = ((LeafListSchemaNode) leaf).getType();
+            } else {
+                continue;
+            }
+
+            final String getterName = getGetterName(leaf.getQName(), typeDef);
+            getterToLeafSchema.put(getterName, leaf);
+        }
+        return getLeafNodesUsingReflection(parentClass, getterToLeafSchema);
+    }
+
+    private String getGetterName(final QName qName, TypeDefinition<?> typeDef) {
+        final String suffix = BindingMapping.getClassName(qName);
+
+        while (typeDef.getBaseType() != null) {
+            typeDef = typeDef.getBaseType();
+        }
+        if (typeDef instanceof BooleanTypeDefinition || typeDef instanceof EmptyTypeDefinition) {
+            return "is" + suffix;
+        }
+        return GETTER_PREFIX + suffix;
+    }
+
+    private ImmutableMap<String, LeafNodeCodecContext<?>> getLeafNodesUsingReflection(final Class<?> parentClass,
+            final Map<String, DataSchemaNode> getterToLeafSchema) {
+        final Map<String, LeafNodeCodecContext<?>> leaves = new HashMap<>();
+        for (final Method method : parentClass.getMethods()) {
+            if (method.getParameterTypes().length == 0) {
+                final DataSchemaNode schema = getterToLeafSchema.get(method.getName());
+                final Class<?> valueType;
+                if (schema instanceof LeafSchemaNode) {
+                    valueType = method.getReturnType();
+                } else if (schema instanceof LeafListSchemaNode) {
+                    final Type genericType = ClassLoaderUtils.getFirstGenericParameter(method.getGenericReturnType());
+
+                    if (genericType instanceof Class<?>) {
+                        valueType = (Class<?>) genericType;
+                    } else if (genericType instanceof ParameterizedType) {
+                        valueType = (Class<?>) ((ParameterizedType) genericType).getRawType();
+                    } else {
+                        throw new IllegalStateException("Unexpected return type " + genericType);
+                    }
+                } else {
+                    continue; // We do not have schema for leaf, so we will ignore it (eg. getClass, getImplementedInterface).
+                }
+                final Codec<Object, Object> codec = getCodec(valueType, schema);
+                final LeafNodeCodecContext<?> leafNode = new LeafNodeCodecContext<>(schema, codec, method);
+                leaves.put(schema.getQName().getLocalName(), leafNode);
+            }
+        }
+        return ImmutableMap.copyOf(leaves);
+    }
+
+    private Codec<Object, Object> getCodec(final Class<?> valueType, final DataSchemaNode schema) {
+        final TypeDefinition<?> instantiatedType;
+        if (schema instanceof LeafSchemaNode) {
+            instantiatedType = ((LeafSchemaNode) schema).getType();
+        } else if (schema instanceof LeafListSchemaNode) {
+            instantiatedType = ((LeafListSchemaNode) schema).getType();
+        } else {
+            throw new IllegalArgumentException("Unsupported leaf node type " + schema.getClass());
+        }
+        if (Class.class.equals(valueType)) {
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            final Codec<Object, Object> casted = (Codec) identityCodec;
+            return casted;
+        } else if (InstanceIdentifier.class.equals(valueType)) {
+            @SuppressWarnings({ "unchecked", "rawtypes" })
+            final Codec<Object, Object> casted = (Codec) instanceIdentifierCodec;
+            return casted;
+        } else if (Boolean.class.equals(valueType)) {
+            if(instantiatedType instanceof EmptyTypeDefinition) {
+                return ValueTypeCodec.EMPTY_CODEC;
+            }
+        } else if (BindingReflections.isBindingClass(valueType)) {
+                            return getCodec(valueType, instantiatedType);
+        }
+        return ValueTypeCodec.NOOP_CODEC;
+    }
+
+    private Codec<Object, Object> getCodec(final Class<?> valueType, final TypeDefinition<?> instantiatedType) {
+        @SuppressWarnings("rawtypes")
+        TypeDefinition rootType = instantiatedType;
+        while (rootType.getBaseType() != null) {
+            rootType = rootType.getBaseType();
+        }
+        if (rootType instanceof IdentityrefTypeDefinition) {
+            return ValueTypeCodec.encapsulatedValueCodecFor(valueType, identityCodec);
+        } else if (rootType instanceof InstanceIdentifierTypeDefinition) {
+            return ValueTypeCodec.encapsulatedValueCodecFor(valueType, instanceIdentifierCodec);
+        } else if (rootType instanceof UnionTypeDefinition) {
+            final Callable<UnionTypeCodec> loader = UnionTypeCodec.loader(valueType, (UnionTypeDefinition) rootType);
+            try {
+                return loader.call();
+            } catch (final Exception e) {
+                throw new IllegalStateException("Unable to load codec for " + valueType, e);
+            }
+        } else if(rootType instanceof LeafrefTypeDefinition) {
+            final Entry<GeneratedType, Object> typeWithSchema = context.getTypeWithSchema(valueType);
+            final Object schema = typeWithSchema.getValue();
+            Preconditions.checkState(schema instanceof TypeDefinition<?>);
+            return getCodec(valueType, (TypeDefinition<?>) schema);
+        }
+        return ValueTypeCodec.getCodecFor(valueType, instantiatedType);
+    }
+
+    @Override
+    public Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> getPathArgumentCodec(final Class<?> listClz,
+            final ListSchemaNode schema) {
+        final Class<? extends Identifier<?>> identifier = ClassLoaderUtils.findFirstGenericArgument(listClz,
+                Identifiable.class);
+        final Map<QName, ValueContext> valueCtx = new HashMap<>();
+        for (final LeafNodeCodecContext<?> leaf : getLeafNodes(identifier, schema).values()) {
+            final QName name = leaf.getDomPathArgument().getNodeType();
+            valueCtx.put(name, new ValueContext(identifier, leaf));
+        }
+        return new IdentifiableItemCodec(schema, identifier, listClz, valueCtx);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends DataObject> BindingCodecTreeNode<T> getSubtreeCodec(final InstanceIdentifier<T> path) {
+        // TODO Do we need defensive check here?
+        return (BindingCodecTreeNode<T>) getCodecContextNode(path, null);
+    }
+
+    @Override
+    public BindingCodecTreeNode<?> getSubtreeCodec(final YangInstanceIdentifier path) {
+        return getCodecContextNode(path, null);
+    }
+
+    @Override
+    public BindingCodecTreeNode<?> getSubtreeCodec(final SchemaPath path) {
+        throw new UnsupportedOperationException("Not implemented yet.");
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingNormalizedNodeCache.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingNormalizedNodeCache.java
new file mode 100644 (file)
index 0000000..141353d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+final class BindingNormalizedNodeCache extends CacheLoader<DataObject, NormalizedNode<?, ?>> {
+
+    private final LoadingCache<DataObject, NormalizedNode<?, ?>> cache = CacheBuilder.newBuilder().weakValues()
+            .build(this);
+    final DataContainerCodecContext<?, ?> subtreeRoot;
+    final AbstractBindingNormalizedNodeCacheHolder cacheHolder;
+
+    public BindingNormalizedNodeCache(final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
+            final DataContainerCodecContext<?, ?> subtreeRoot) {
+        this.cacheHolder = Preconditions.checkNotNull(cacheHolder, "cacheHolder");
+        this.subtreeRoot = Preconditions.checkNotNull(subtreeRoot, "subtreeRoot");
+    }
+
+    @Override
+    public NormalizedNode<?, ?> load(final DataObject key) throws Exception {
+        return CachingNormalizedNodeSerializer.serializeUsingStreamWriter(cacheHolder, subtreeRoot, key);
+    }
+
+    /**
+     * Returns cached NormalizedNode representation of DataObject.
+     *
+     * If representation is not cached, serializes DataObject and updates cache with representation.
+     *
+     * @param obj Binding object to be deserialized
+     * @return NormalizedNode representation of binding object.
+     */
+    NormalizedNode<?, ?> get(final DataObject obj) {
+        return cache.getUnchecked(obj);
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingNormalizedNodeCodecRegistry.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingNormalizedNodeCodecRegistry.java
new file mode 100644 (file)
index 0000000..50af39c
--- /dev/null
@@ -0,0 +1,299 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import java.io.IOException;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map.Entry;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTree;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeFactory;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeWriterFactory;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.MapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BindingNormalizedNodeCodecRegistry implements DataObjectSerializerRegistry,
+        BindingCodecTreeFactory, BindingNormalizedNodeWriterFactory,
+        BindingNormalizedNodeSerializer {
+    private static final Logger LOG = LoggerFactory.getLogger(BindingNormalizedNodeCodecRegistry.class);
+
+    private final DataObjectSerializerGenerator generator;
+    private final LoadingCache<Class<? extends DataObject>, DataObjectSerializer> serializers;
+    private volatile BindingCodecContext codecContext;
+
+    public BindingNormalizedNodeCodecRegistry(final DataObjectSerializerGenerator generator) {
+        this.generator = Preconditions.checkNotNull(generator);
+        this.serializers = CacheBuilder.newBuilder().weakKeys().build(new GeneratorLoader());
+    }
+
+    @Override
+    public DataObjectSerializer getSerializer(final Class<? extends DataObject> type) {
+        return serializers.getUnchecked(type);
+    }
+
+    public BindingCodecTree getCodecContext() {
+        return codecContext;
+    }
+
+    public void onBindingRuntimeContextUpdated(final BindingRuntimeContext context) {
+        codecContext = create(context);
+        generator.onBindingRuntimeContextUpdated(context);
+    }
+
+
+    @Override
+    public YangInstanceIdentifier toYangInstanceIdentifier(final InstanceIdentifier<?> binding) {
+        return codecContext.getInstanceIdentifierCodec().serialize(binding);
+    }
+
+    @Override
+    public InstanceIdentifier<?> fromYangInstanceIdentifier(final YangInstanceIdentifier dom) {
+        return codecContext.getInstanceIdentifierCodec().deserialize(dom);
+    }
+
+    @Override
+    public <T extends DataObject> Entry<YangInstanceIdentifier,NormalizedNode<?,?>> toNormalizedNode(final InstanceIdentifier<T> path, final T data) {
+        final NormalizedNodeResult result = new NormalizedNodeResult();
+        // We create DOM stream writer which produces normalized nodes
+        final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+
+        // We create Binding Stream Writer which translates from Binding to Normalized Nodes
+        final Entry<YangInstanceIdentifier, BindingStreamEventWriter> writeCtx = codecContext.newWriter(path, domWriter);
+
+        // We get serializer which reads binding data and uses Binding To Normalized Node writer to write result
+        try {
+            getSerializer(path.getTargetType()).serialize(data, writeCtx.getValue());
+        } catch (final IOException e) {
+            LOG.error("Unexpected failure while serializing path {} data {}", path, data, e);
+            throw new IllegalStateException("Failed to create normalized node", e);
+        }
+        return new SimpleEntry<YangInstanceIdentifier,NormalizedNode<?,?>>(writeCtx.getKey(),result.getResult());
+    }
+
+    @Override
+    public ContainerNode toNormalizedNodeNotification(final Notification data) {
+        final NormalizedNodeResult result = new NormalizedNodeResult();
+        // We create DOM stream writer which produces normalized nodes
+        final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final Class<? extends DataObject> type = (Class) data.getImplementedInterface();
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final BindingStreamEventWriter writer = newNotificationWriter((Class) type, domWriter);
+        try {
+            // FIXME: Should be cast to DataObject necessary?
+            getSerializer(type).serialize((DataObject) data, writer);
+        } catch (final IOException e) {
+            LOG.error("Unexpected failure while serializing data {}", data, e);
+            throw new IllegalStateException("Failed to create normalized node", e);
+        }
+        return (ContainerNode) result.getResult();
+
+    }
+
+    @Override
+    public ContainerNode toNormalizedNodeRpcData(final DataContainer data) {
+        final NormalizedNodeResult result = new NormalizedNodeResult();
+        // We create DOM stream writer which produces normalized nodes
+        final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final Class<? extends DataObject> type = (Class) data.getImplementedInterface();
+        final BindingStreamEventWriter writer = newRpcWriter(type, domWriter);
+        try {
+            // FIXME: Should be cast to DataObject necessary?
+            getSerializer(type).serialize((DataObject) data, writer);
+        } catch (final IOException e) {
+            LOG.error("Unexpected failure while serializing data {}", data, e);
+            throw new IllegalStateException("Failed to create normalized node", e);
+        }
+        return (ContainerNode) result.getResult();
+    }
+
+    private static boolean isBindingRepresentable(final NormalizedNode<?, ?> data) {
+        if (data instanceof ChoiceNode) {
+            return false;
+        }
+        if (data instanceof LeafNode<?>) {
+            return false;
+        }
+        if (data instanceof LeafSetNode) {
+            return false;
+        }
+        if( data instanceof LeafSetEntryNode<?>) {
+            return false;
+        }
+        if (data instanceof MapNode) {
+            return false;
+        }
+        if (data instanceof UnkeyedListNode) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public Entry<InstanceIdentifier<?>, DataObject> fromNormalizedNode(final YangInstanceIdentifier path, final NormalizedNode<?, ?> data) {
+        if (!isBindingRepresentable(data)) {
+            return null;
+        }
+
+        final List<PathArgument> builder = new ArrayList<>();
+        final NodeCodecContext<?> codec = codecContext.getCodecContextNode(path, builder);
+        if (codec == null) {
+            if (data != null) {
+                LOG.warn("Path {} does not have a binding equivalent, should have been caught earlier ({})", path, data.getClass());
+            }
+            return null;
+        }
+
+        final DataObject lazyObj = codec.deserialize(data);
+        final InstanceIdentifier<?> bindingPath = InstanceIdentifier.create(builder);
+        return new SimpleEntry<InstanceIdentifier<?>, DataObject>(bindingPath, lazyObj);
+    }
+
+    @Override
+    public Notification fromNormalizedNodeNotification(final SchemaPath path, final ContainerNode data) {
+        final NotificationCodecContext<?> codec = codecContext.getNotificationContext(path);
+        return codec.deserialize(data);
+    }
+
+    @Override
+    public DataObject fromNormalizedNodeRpcData(final SchemaPath path, final ContainerNode data) {
+        final ContainerNodeCodecContext<?> codec = codecContext.getRpcDataContext(path);
+        return codec.deserialize(data);
+    }
+
+   @Override
+    public Entry<YangInstanceIdentifier, BindingStreamEventWriter> newWriterAndIdentifier(final InstanceIdentifier<?> path, final NormalizedNodeStreamWriter domWriter) {
+        return codecContext.newWriter(path, domWriter);
+    }
+
+    @Override
+    public BindingStreamEventWriter newWriter(final InstanceIdentifier<?> path, final NormalizedNodeStreamWriter domWriter) {
+        return codecContext.newWriterWithoutIdentifier(path, domWriter);
+    }
+
+    @Override
+    public BindingStreamEventWriter newNotificationWriter(final Class<? extends Notification> notification,
+            final NormalizedNodeStreamWriter streamWriter) {
+        return codecContext.newNotificationWriter(notification, streamWriter);
+    }
+
+    @Override
+    public BindingStreamEventWriter newRpcWriter(final Class<? extends DataContainer> rpcInputOrOutput,
+            final NormalizedNodeStreamWriter streamWriter) {
+        return codecContext.newRpcWriter(rpcInputOrOutput,streamWriter);
+    }
+
+    public <T extends DataObject> Function<Optional<NormalizedNode<?, ?>>, Optional<T>>  deserializeFunction(final InstanceIdentifier<T> path) {
+        final DataObjectCodecContext<?,?> ctx = (DataObjectCodecContext<?,?>) codecContext.getCodecContextNode(path, null);
+        return new DeserializeFunction<T>(ctx);
+    }
+
+    @Override
+    public BindingCodecContext create(final BindingRuntimeContext context) {
+        return new BindingCodecContext(context, this);
+    }
+
+    @Override
+    public BindingCodecContext create(final SchemaContext context, final Class<?>... bindingClasses) {
+        final ModuleInfoBackedContext strategy = ModuleInfoBackedContext.create();
+        for (final Class<?> bindingCls : bindingClasses) {
+            try {
+                strategy.registerModuleInfo(BindingReflections.getModuleInfo(bindingCls));
+            } catch (final Exception e) {
+                throw new IllegalStateException(
+                        "Could not create BindingRuntimeContext from class " + bindingCls.getName(),
+                        e);
+            }
+        }
+        final BindingRuntimeContext runtimeCtx = BindingRuntimeContext.create(strategy, context);
+        return create(runtimeCtx);
+    }
+
+
+    private static final class DeserializeFunction<T> implements Function<Optional<NormalizedNode<?, ?>>, Optional<T>> {
+        private final DataObjectCodecContext<?,?> ctx;
+
+        DeserializeFunction(final DataObjectCodecContext<?,?> ctx) {
+            this.ctx = ctx;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Optional<T> apply(final Optional<NormalizedNode<?, ?>> input) {
+            if (input.isPresent()) {
+                return Optional.of((T) ctx.deserialize(input.get()));
+            }
+            return Optional.absent();
+        }
+    }
+
+    private final class GeneratorLoader extends CacheLoader<Class<? extends DataContainer>, DataObjectSerializer> {
+        @Override
+        public DataObjectSerializer load(final Class<? extends DataContainer> key) throws Exception {
+            final DataObjectSerializerImplementation prototype = generator.getSerializer(key);
+            return new DataObjectSerializerProxy(prototype);
+        }
+    }
+
+    private final class DataObjectSerializerProxy implements DataObjectSerializer, Delegator<DataObjectSerializerImplementation> {
+        private final DataObjectSerializerImplementation delegate;
+
+        DataObjectSerializerProxy(final DataObjectSerializerImplementation delegate) {
+            this.delegate = delegate;
+        }
+
+        @Override
+        public DataObjectSerializerImplementation getDelegate() {
+            return delegate;
+        }
+
+        @Override
+        public void serialize(final DataObject obj, final BindingStreamEventWriter stream) throws IOException {
+            delegate.serialize(BindingNormalizedNodeCodecRegistry.this, obj, stream);
+        }
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingToNormalizedStreamWriter.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BindingToNormalizedStreamWriter.java
new file mode 100644 (file)
index 0000000..ed4bb47
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.util.AbstractMap;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.opendaylight.yangtools.concepts.Delegator;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+
+class BindingToNormalizedStreamWriter implements BindingStreamEventWriter, Delegator<NormalizedNodeStreamWriter> {
+
+    private final NormalizedNodeStreamWriter delegate;
+    private final Deque<NodeCodecContext<?>> schema = new ArrayDeque<>();
+    private final NodeCodecContext<?> rootNodeSchema;
+
+    public BindingToNormalizedStreamWriter(final NodeCodecContext<?> schema, final NormalizedNodeStreamWriter delegate) {
+        this.delegate = Preconditions.checkNotNull(delegate, "Delegate must not be null");
+        this.rootNodeSchema = Preconditions.checkNotNull(schema);
+
+    }
+
+    protected final NodeCodecContext<?> current() {
+        return schema.peek();
+    }
+
+    private NodeIdentifier duplicateSchemaEnter() {
+        final NodeCodecContext<?> next;
+        if (current() == null) {
+            // Entry of first node
+            next = rootNodeSchema;
+        } else {
+            next = current();
+        }
+        this.schema.push(next);
+        return (NodeIdentifier) current().getDomPathArgument();
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    private <T extends YangInstanceIdentifier.PathArgument> T enter(final Class<?> name, final Class<T> identifier) {
+        final NodeCodecContext<?> next;
+        if (current() == null) {
+            // Entry of first node
+            next = rootNodeSchema;
+        } else {
+            Preconditions.checkArgument((current() instanceof DataContainerCodecContext), "Could not start node %s",
+                    name);
+            next = ((DataContainerCodecContext<?,?>) current()).streamChild((Class) name);
+        }
+        this.schema.push(next);
+        T arg = (T) next.getDomPathArgument();
+        return arg;
+    }
+
+    private <T extends YangInstanceIdentifier.PathArgument> T enter(final String localName, final Class<T> identifier) {
+        NodeCodecContext<?> current = current();
+        NodeCodecContext<?> next = ((DataObjectCodecContext<?,?>) current).getLeafChild(localName);
+        this.schema.push(next);
+        @SuppressWarnings("unchecked")
+        T arg = (T) next.getDomPathArgument();
+        return arg;
+    }
+
+    @Override
+    public void endNode() throws IOException {
+        NodeCodecContext<?> left = schema.pop();
+        // NormalizedNode writer does not have entry into case, but into choice
+        // so for leaving case, we do not emit endNode.
+        if (!(left instanceof CaseNodeCodecContext)) {
+            getDelegate().endNode();
+        }
+    }
+
+    @Override
+    public NormalizedNodeStreamWriter getDelegate() {
+        return delegate;
+    }
+
+    private Map.Entry<NodeIdentifier, Object> serializeLeaf(final String localName, final Object value) {
+        Preconditions.checkArgument(current() instanceof DataObjectCodecContext);
+
+        DataObjectCodecContext<?,?> currentCasted = (DataObjectCodecContext<?,?>) current();
+        LeafNodeCodecContext<?> leafContext = currentCasted.getLeafChild(localName);
+
+        NodeIdentifier domArg = (NodeIdentifier) leafContext.getDomPathArgument();
+        Object domValue = leafContext.getValueCodec().serialize(value);
+        return new AbstractMap.SimpleEntry<>(domArg, domValue);
+    }
+
+    @Override
+    public void leafNode(final String localName, final Object value) throws IOException {
+        Entry<NodeIdentifier, Object> dom = serializeLeaf(localName, value);
+        getDelegate().leafNode(dom.getKey(), dom.getValue());
+    }
+
+    @Override
+    public void anyxmlNode(final String name, final Object value) throws IOException {
+        Entry<NodeIdentifier, Object> dom = serializeLeaf(name, value);
+        getDelegate().anyxmlNode(dom.getKey(), dom.getValue());
+    }
+
+    @Override
+    public void leafSetEntryNode(final Object value) throws IOException {
+        LeafNodeCodecContext<?> ctx = (LeafNodeCodecContext<?>) current();
+        getDelegate().leafSetEntryNode(ctx.getValueCodec().serialize(value));
+    }
+
+    @Override
+    public void startAugmentationNode(final Class<? extends Augmentation<?>> augmentationType) throws IOException {
+        getDelegate().startAugmentationNode(enter(augmentationType, AugmentationIdentifier.class));
+    }
+
+    @Override
+    public void startCase(final Class<? extends DataObject> caze, final int childSizeHint) {
+        enter(caze, NodeIdentifier.class);
+    }
+
+    @Override
+    public void startChoiceNode(final Class<? extends DataContainer> type, final int childSizeHint) throws IOException {
+        getDelegate().startChoiceNode(enter(type, NodeIdentifier.class), childSizeHint);
+    }
+
+    @Override
+    public void startContainerNode(final Class<? extends DataObject> object, final int childSizeHint)
+            throws IOException {
+        getDelegate().startContainerNode(enter(object, NodeIdentifier.class), childSizeHint);
+    }
+
+    @Override
+    public void startLeafSet(final String localName, final int childSizeHint) throws IOException {
+        getDelegate().startLeafSet(enter(localName, NodeIdentifier.class), childSizeHint);
+    }
+
+    @Override
+    public void startMapEntryNode(final Identifier<?> key, final int childSizeHint) throws IOException {
+        duplicateSchemaEnter();
+        NodeIdentifierWithPredicates identifier = ((KeyedListNodeCodecContext<?>) current()).serialize(key);
+        getDelegate().startMapEntryNode(identifier, childSizeHint);
+    }
+
+    @Override
+    public <T extends DataObject & Identifiable<?>> void startMapNode(final Class<T> mapEntryType,
+            final int childSizeHint) throws IOException {
+        getDelegate().startMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
+    }
+
+    @Override
+    public <T extends DataObject & Identifiable<?>> void startOrderedMapNode(final Class<T> mapEntryType,
+            final int childSizeHint) throws IOException {
+        getDelegate().startOrderedMapNode(enter(mapEntryType, NodeIdentifier.class), childSizeHint);
+    }
+
+    @Override
+    public void startUnkeyedList(final Class<? extends DataObject> obj, final int childSizeHint) throws IOException {
+        getDelegate().startUnkeyedList(enter(obj, NodeIdentifier.class), childSizeHint);
+    }
+
+    @Override
+    public void startUnkeyedListItem(final int childSizeHint) throws IOException {
+        getDelegate().startUnkeyedListItem(duplicateSchemaEnter(), childSizeHint);
+    }
+
+    @Override
+    public void flush() throws IOException {
+        getDelegate().flush();
+    }
+
+    @Override
+    public void close() throws IOException {
+        getDelegate().close();
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BitsCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/BitsCodec.java
new file mode 100644 (file)
index 0000000..d8b1455
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSortedMap;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.concurrent.Callable;
+import org.opendaylight.yangtools.binding.data.codec.impl.ValueTypeCodec.SchemaUnawareCodec;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
+
+class BitsCodec extends ReflectionBasedCodec implements SchemaUnawareCodec {
+
+    private final ImmutableSortedMap<String, Method> valueGetters;
+    private final Constructor<?> constructor;
+
+    private BitsCodec(final Class<?> typeClass, final SortedMap<String, Method> valueGetters,
+            final Constructor<?> constructor) {
+        super(typeClass);
+        this.valueGetters = ImmutableSortedMap.copyOf(valueGetters);
+        this.constructor = constructor;
+    }
+
+    static Callable<BitsCodec> loader(final Class<?> returnType,
+            final BitsTypeDefinition rootType) {
+        return new Callable<BitsCodec>() {
+
+            @Override
+            public BitsCodec call() throws Exception {
+                try {
+                    SortedMap<String, Method> valueGetters = new TreeMap<>();
+                    for (Bit bit : rootType.getBits()) {
+                        String bindingName = BindingMapping.getClassName(bit.getName());
+                        Method valueGetter = returnType.getMethod("is" + bindingName);
+                        valueGetters.put(bit.getName(), valueGetter);
+
+                    }
+                    Constructor<?> constructor = null;
+                    for (Constructor<?> cst : returnType.getConstructors()) {
+                        if (cst.getParameterTypes()[0].equals(returnType)) {
+                            continue;
+                        }
+                        constructor = cst;
+                    }
+
+                    return new BitsCodec(returnType, valueGetters, constructor);
+                } catch (IllegalArgumentException | NoSuchMethodException | SecurityException e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+        };
+    }
+
+    @Override
+    public Object deserialize(final Object input) {
+        Preconditions.checkArgument(input instanceof Set);
+        @SuppressWarnings("unchecked")
+        Set<String> casted = (Set<String>) input;
+
+        Object args[] = new Object[valueGetters.size()];
+        int currentArg = 0;
+        /*
+         * We can do this walk based on field set
+         * sorted by name, since constructor arguments in
+         * Java Binding are sorted by name.
+         *
+         * This means we will construct correct array
+         * for construction of bits object.
+         */
+        for (String value : valueGetters.keySet()) {
+            args[currentArg++] = casted.contains(value);
+        }
+
+        try {
+            return constructor.newInstance(args);
+        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public Object serialize(final Object input) {
+        Set<String> result = new HashSet<>();
+        for (Entry<String, Method> valueGet : valueGetters.entrySet()) {
+            try {
+                Boolean value = (Boolean) valueGet.getValue().invoke(input);
+                if (value) {
+                    result.add(valueGet.getKey());
+                }
+            } catch (IllegalAccessException | InvocationTargetException e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeCodec.java
new file mode 100644 (file)
index 0000000..d1f22fb
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Set;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+class CachingNormalizedNodeCodec<D extends DataObject> extends AbstractBindingNormalizedNodeCacheHolder implements
+        BindingNormalizedNodeCachingCodec<D> {
+
+    private final DataContainerCodecContext<D, ?> context;
+
+
+    CachingNormalizedNodeCodec(final DataContainerCodecContext<D, ?> subtreeRoot,
+            final Set<Class<? extends DataObject>> cacheSpec) {
+        super(cacheSpec);
+        this.context = Preconditions.checkNotNull(subtreeRoot);
+    }
+
+    @Override
+    public D deserialize(final NormalizedNode<?, ?> data) {
+        return context.deserialize(data);
+    }
+
+    @Override
+    public NormalizedNode<?, ?> serialize(final D data) {
+        return CachingNormalizedNodeSerializer.serialize(this, context, data);
+    }
+
+    @Override
+    public void close() {
+        // NOOP as of now.
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeSerializer.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CachingNormalizedNodeSerializer.java
new file mode 100644 (file)
index 0000000..87c8c44
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Throwables;
+import java.io.IOException;
+import org.opendaylight.yangtools.yang.binding.BindingSerializer;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+
+/**
+ * Serializer of Binding objects to Normalized Node which uses {@link BindingNormalizedNodeCache} to
+ * cache already serialized values.
+ *
+ * This serializer implements {@link BindingStreamEventWriter} along with {@link BindingSerializer}.
+ *
+ * {@link BindingSerializer} interface is used by generated implementations of
+ * {@link org.opendaylight.yangtools.yang.binding.DataObjectSerializer} to provide Binding object
+ * for inspection and to prevent streaming of already serialized object.
+ *
+ */
+final class CachingNormalizedNodeSerializer extends ForwardingBindingStreamEventWriter implements
+        BindingSerializer<Object, DataObject> {
+
+    private final NormalizedNodeResult domResult;
+    private final NormalizedNodeWriterWithAddChild domWriter;
+    private final BindingToNormalizedStreamWriter delegate;
+    private final AbstractBindingNormalizedNodeCacheHolder cacheHolder;
+
+    CachingNormalizedNodeSerializer(final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
+            final DataContainerCodecContext<?, ?> subtreeRoot) {
+        this.cacheHolder = cacheHolder;
+        this.domResult = new NormalizedNodeResult();
+        this.domWriter = new NormalizedNodeWriterWithAddChild(domResult);
+        this.delegate = new BindingToNormalizedStreamWriter(subtreeRoot, domWriter);
+    }
+
+    @Override
+    protected BindingStreamEventWriter delegate() {
+        return delegate;
+    }
+
+    NormalizedNode<?, ?> build() {
+        return domResult.getResult();
+    }
+
+    /**
+     * Serializes input if it is cached, returns null otherwise.
+     *
+     * If input is cached it uses {@link NormalizedNodeWriterWithAddChild#addChild(NormalizedNode)}
+     * to provide already serialized value to underlying NormalizedNodeWriter in order to reuse
+     * value instead of creating new one using Normalized Node stream APIs.
+     *
+     * Note that this optional is serialization of child node invoked from
+     * {@link org.opendaylight.yangtools.yang.binding.DataObjectSerializer}, which may opt-out from
+     * streaming of data when non-null result is returned.
+     */
+    @Override
+    public NormalizedNode<?, ?> serialize(final DataObject input) {
+        final BindingNormalizedNodeCache cachingSerializer = getCacheSerializer(input.getImplementedInterface());
+        if (cachingSerializer != null) {
+            final NormalizedNode<?, ?> domData = cachingSerializer.get(input);
+            domWriter.addChild(domData);
+            return domData;
+        }
+        return null;
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private BindingNormalizedNodeCache getCacheSerializer(final Class type) {
+        if (cacheHolder.isCached(type)) {
+            final DataContainerCodecContext<?, ?> currentCtx = (DataContainerCodecContext<?, ?>) delegate.current();
+            if (type.equals(currentCtx.getBindingClass())) {
+                return cacheHolder.getCachingSerializer(currentCtx);
+            }
+            final DataContainerCodecContext<?, ?> childCtx =
+                    (DataContainerCodecContext<?, ?>) currentCtx.streamChild(type);
+            return cacheHolder.getCachingSerializer(childCtx);
+        }
+        return null;
+    }
+
+    /**
+     * Serializes supplied data using stream writer with child cache enabled or using cache directly
+     * if cache is avalaible also for supplied Codec node.
+     *
+     * @param cacheHolder Binding to Normalized Node Cache holder
+     * @param subtreeRoot Codec Node for provided data object
+     * @param data Data to be serialized
+     * @return Normalized Node representation of data.
+     */
+    static NormalizedNode<?, ?> serialize(final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
+            final DataContainerCodecContext<?, ?> subtreeRoot, final DataObject data) {
+        final BindingNormalizedNodeCache cache = cacheHolder.getCachingSerializer(subtreeRoot);
+        if (cache != null) {
+            return cache.get(data);
+        }
+        return serializeUsingStreamWriter(cacheHolder, subtreeRoot, data);
+    }
+
+    /**
+     * Serializes supplied data using stream writer with child cache enabled.
+     *
+     * @param cacheHolder Binding to Normalized Node Cache holder
+     * @param subtreeRoot Codec Node for provided data object
+     * @param data Data to be serialized
+     * @return Normalized Node representation of data.
+     */
+    static NormalizedNode<?, ?> serializeUsingStreamWriter(final AbstractBindingNormalizedNodeCacheHolder cacheHolder,
+            final DataContainerCodecContext<?, ?> subtreeRoot, final DataObject data) {
+        final CachingNormalizedNodeSerializer writer = new CachingNormalizedNodeSerializer(cacheHolder, subtreeRoot);
+        try {
+            subtreeRoot.eventStreamSerializer().serialize(data, writer);
+            return writer.build();
+        } catch (final IOException e) {
+            throw Throwables.propagate(e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CaseNodeCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CaseNodeCodecContext.java
new file mode 100644 (file)
index 0000000..d392285
--- /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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.List;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+
+final class CaseNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D,ChoiceCaseNode> {
+    public CaseNodeCodecContext(final DataContainerCodecPrototype<ChoiceCaseNode> prototype) {
+        super(prototype);
+    }
+
+    @Override
+    protected void addYangPathArgument(final PathArgument arg,
+            final List<org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument> builder) {
+        // NOOP
+    }
+
+    @Override
+    public D deserialize(final NormalizedNode<?, ?> normalizedNode) {
+        Preconditions.checkState(normalizedNode instanceof ChoiceNode);
+        return createBindingProxy((ChoiceNode) normalizedNode);
+    }
+
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
+
+    @Override
+    public org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument serializePathArgument(
+            PathArgument arg) {
+        Preconditions.checkArgument(arg == null);
+        return null;
+    }
+
+    @Override
+    public PathArgument deserializePathArgument(
+            org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument arg) {
+        Preconditions.checkArgument(arg == null);
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ChoiceNodeCodecContext.java
new file mode 100644 (file)
index 0000000..b9c44c8
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+final class ChoiceNodeCodecContext<D extends DataObject> extends DataContainerCodecContext<D,ChoiceSchemaNode> {
+    private static final Logger LOG = LoggerFactory.getLogger(ChoiceNodeCodecContext.class);
+    private final ImmutableMap<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChild;
+    private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byClass;
+    private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClass;
+
+    public ChoiceNodeCodecContext(final DataContainerCodecPrototype<ChoiceSchemaNode> prototype) {
+        super(prototype);
+        final Map<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangCaseChildBuilder = new HashMap<>();
+        final Map<Class<?>, DataContainerCodecPrototype<?>> byClassBuilder = new HashMap<>();
+        final Map<Class<?>, DataContainerCodecPrototype<?>> byCaseChildClassBuilder = new HashMap<>();
+        final Set<Class<?>> potentialSubstitutions = new HashSet<>();
+        // Walks all cases for supplied choice in current runtime context
+        for (final Class<?> caze : factory().getRuntimeContext().getCases(getBindingClass())) {
+            // We try to load case using exact match thus name
+            // and original schema must equals
+            final DataContainerCodecPrototype<ChoiceCaseNode> cazeDef = loadCase(caze);
+            // If we have case definition, this case is instantiated
+            // at current location and thus is valid in context of parent choice
+            if (cazeDef != null) {
+                byClassBuilder.put(cazeDef.getBindingClass(), cazeDef);
+                // Updates collection of case children
+                @SuppressWarnings("unchecked")
+                final Class<? extends DataObject> cazeCls = (Class<? extends DataObject>) caze;
+                for (final Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses(cazeCls)) {
+                    byCaseChildClassBuilder.put(cazeChild, cazeDef);
+                }
+                // Updates collection of YANG instance identifier to case
+                for (final DataSchemaNode cazeChild : cazeDef.getSchema().getChildNodes()) {
+                    if (cazeChild.isAugmenting()) {
+                        final AugmentationSchema augment = SchemaUtils.findCorrespondingAugment(cazeDef.getSchema(), cazeChild);
+                        if (augment != null) {
+                            byYangCaseChildBuilder.put(SchemaUtils.getNodeIdentifierForAugmentation(augment), cazeDef);
+                            continue;
+                        }
+                    }
+                    byYangCaseChildBuilder.put(new NodeIdentifier(cazeChild.getQName()), cazeDef);
+                }
+            } else {
+                /*
+                 * If case definition is not available, we store it for
+                 * later check if it could be used as substitution of existing one.
+                 */
+                potentialSubstitutions.add(caze);
+            }
+        }
+
+        final Map<Class<?>, DataContainerCodecPrototype<?>> bySubstitutionBuilder = new HashMap<>();
+        /*
+         * Walks all cases which are not directly instantiated and
+         * tries to match them to instantiated cases - represent same data as instantiated case,
+         * only case name or schema path is different. This is required due property of
+         * binding specification, that if choice is in grouping schema path location is lost,
+         * and users may use incorrect case class using copy builders.
+         */
+        for(final Class<?> substitution : potentialSubstitutions) {
+            search: for(final Entry<Class<?>, DataContainerCodecPrototype<?>> real : byClassBuilder.entrySet()) {
+                if(BindingReflections.isSubstitutionFor(substitution, real.getKey())) {
+                    bySubstitutionBuilder.put(substitution, real.getValue());
+                    break search;
+                }
+            }
+        }
+        byClassBuilder.putAll(bySubstitutionBuilder);
+        byYangCaseChild = ImmutableMap.copyOf(byYangCaseChildBuilder);
+        byClass = ImmutableMap.copyOf(byClassBuilder);
+        byCaseChildClass = ImmutableMap.copyOf(byCaseChildClassBuilder);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(final Class<DV> childClass) {
+        final DataContainerCodecPrototype<?> child = byClass.get(childClass);
+        return (DataContainerCodecContext<DV, ?>) childNonNull(child, childClass, "Supplied class %s is not valid case", childClass).get();
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <DV extends DataObject> Optional<DataContainerCodecContext<DV, ?>> possibleStreamChild(
+            final Class<DV> childClass) {
+        final DataContainerCodecPrototype<?> child = byClass.get(childClass);
+        if(child != null) {
+            return Optional.<DataContainerCodecContext<DV,?>>of((DataContainerCodecContext<DV, ?>) child.get());
+        }
+        return Optional.absent();
+    }
+
+    Iterable<Class<?>> getCaseChildrenClasses() {
+        return byCaseChildClass.keySet();
+    }
+
+    protected DataContainerCodecPrototype<ChoiceCaseNode> loadCase(final Class<?> childClass) {
+        final Optional<ChoiceCaseNode> childSchema = factory().getRuntimeContext().getCaseSchemaDefinition(schema(), childClass);
+        if (childSchema.isPresent()) {
+            return DataContainerCodecPrototype.from(childClass, childSchema.get(), factory());
+        }
+
+        LOG.debug("Supplied class %s is not valid case in schema %s", childClass, schema());
+        return null;
+    }
+
+    @Override
+    public NodeCodecContext<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg) {
+        final DataContainerCodecPrototype<?> cazeProto = byYangCaseChild.get(arg);
+        childNonNull(cazeProto != null, arg,"Argument %s is not valid child of %s", arg, schema());
+        return cazeProto.get().yangPathArgumentChild(arg);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    @Nullable
+    public D deserialize(final NormalizedNode<?, ?> data) {
+        Preconditions.checkArgument(data instanceof ChoiceNode);
+        final NormalizedNodeContainer<?, ?, NormalizedNode<?,?>> casted = (NormalizedNodeContainer<?, ?, NormalizedNode<?,?>>) data;
+        final NormalizedNode<?, ?> first = Iterables.getFirst(casted.getValue(), null);
+
+        if (first == null) {
+            return null;
+        }
+        final DataContainerCodecPrototype<?> caze = byYangCaseChild.get(first.getIdentifier());
+        return (D) caze.get().deserialize(data);
+    }
+
+    DataContainerCodecContext<?, ?> getCazeByChildClass(final @Nonnull Class<? extends DataObject> type) {
+        final DataContainerCodecPrototype<?> protoCtx =
+                childNonNull(byCaseChildClass.get(type), type, "Class %s is not child of any cases for %s", type,
+                        bindingArg());
+        return protoCtx.get();
+    }
+
+    @Override
+    protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
+
+    @Override
+    public PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
+        Preconditions.checkArgument(getDomPathArgument().equals(arg));
+        return null;
+    }
+
+    @Override
+    public YangInstanceIdentifier.PathArgument serializePathArgument(
+            final PathArgument arg) {
+        // FIXME: check for null, since binding container is null.
+        return getDomPathArgument();
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CompositeValueCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/CompositeValueCodec.java
new file mode 100644 (file)
index 0000000..d81e394
--- /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.binding.data.codec.impl;
+
+import org.opendaylight.yangtools.concepts.Codec;
+
+final class CompositeValueCodec extends ValueTypeCodec {
+
+    private final SchemaUnawareCodec bindingToSimpleType;
+    @SuppressWarnings("rawtypes")
+    private final Codec bindingToDom;
+
+    CompositeValueCodec(final SchemaUnawareCodec extractor,
+            @SuppressWarnings("rawtypes") final Codec delegate) {
+        this.bindingToSimpleType = extractor;
+        this.bindingToDom = delegate;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object deserialize(final Object input) {
+        return bindingToSimpleType.deserialize(bindingToDom.deserialize(input));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object serialize(final Object input) {
+        return bindingToDom.serialize(bindingToSimpleType.serialize(input));
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ContainerNodeCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ContainerNodeCodecContext.java
new file mode 100644 (file)
index 0000000..a179d9a
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+
+final class ContainerNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D,ContainerSchemaNode> {
+
+    ContainerNodeCodecContext(final DataContainerCodecPrototype<ContainerSchemaNode> prototype) {
+        super(prototype);
+    }
+
+    @Override
+    public D deserialize(final NormalizedNode<?, ?> data) {
+        Preconditions.checkState(data instanceof ContainerNode);
+        return createBindingProxy((ContainerNode) data);
+    }
+
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataContainerCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataContainerCodecContext.java
new file mode 100644 (file)
index 0000000..3d2adfb
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+
+abstract class DataContainerCodecContext<D extends DataObject,T> extends NodeCodecContext<D>  {
+
+    private final DataContainerCodecPrototype<T> prototype;
+    private volatile DataObjectSerializer eventStreamSerializer;
+
+    protected DataContainerCodecContext(final DataContainerCodecPrototype<T> prototype) {
+        this.prototype = prototype;
+    }
+
+    protected final T schema() {
+        return prototype.getSchema();
+    }
+
+    protected final QNameModule namespace() {
+        return prototype.getNamespace();
+    }
+
+    protected final CodecContextFactory factory() {
+        return prototype.getFactory();
+    }
+
+    @Override
+    protected YangInstanceIdentifier.PathArgument getDomPathArgument() {
+        return prototype.getYangArg();
+    }
+
+    /**
+     * Returns nested node context using supplied YANG Instance Identifier
+     *
+     * @param arg Yang Instance Identifier Argument
+     * @return Context of child
+     * @throws IllegalArgumentException If supplied argument does not represent valid child.
+     */
+    @Override
+    public abstract NodeCodecContext<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg);
+
+    /**
+     * Returns nested node context using supplied Binding Instance Identifier
+     * and adds YANG instance identifiers to supplied list.
+     *
+     * @param arg Binding Instance Identifier Argument
+     * @return Context of child or null if supplied {@code arg} does not represent valid child.
+     * @throws IllegalArgumentException If supplied argument does not represent valid child.
+     */
+    @Override
+    public @Nullable DataContainerCodecContext<?,?> bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg,
+            final List<YangInstanceIdentifier.PathArgument> builder) {
+        final DataContainerCodecContext<?,?> child = streamChild(arg.getType());
+        if(child != null) {
+            if (builder != null) {
+                child.addYangPathArgument(arg,builder);
+            }
+            return child;
+        }
+        throw new IllegalArgumentException("SUpplied argument is not valid child");
+    }
+
+    /**
+     * Returns deserialized Binding Path Argument from YANG instance identifier.
+     *
+     * @param domArg
+     * @return
+     */
+    protected PathArgument getBindingPathArgument(final YangInstanceIdentifier.PathArgument domArg) {
+        return bindingArg();
+    }
+
+    protected final PathArgument bindingArg() {
+        return prototype.getBindingArg();
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public final Class<D> getBindingClass() {
+        return Class.class.cast(prototype.getBindingClass());
+    }
+
+    /**
+     *
+     * Returns child context as if it was walked by
+     * {@link BindingStreamEventWriter}. This means that to enter case, one
+     * must issue getChild(ChoiceClass).getChild(CaseClass).
+     *
+     * @param childClass
+     * @return Context of child node or null, if supplied class is not subtree child
+     * @throws IllegalArgumentException If supplied child class is not valid in specified context.
+     */
+    @Override
+    public abstract @Nullable <DV extends DataObject> DataContainerCodecContext<DV,?> streamChild(final Class<DV> childClass) throws IllegalArgumentException;
+
+    /**
+     *
+     * Returns child context as if it was walked by
+     * {@link BindingStreamEventWriter}. This means that to enter case, one
+     * must issue getChild(ChoiceClass).getChild(CaseClass).
+     *
+     * @param childClass
+     * @return Context of child or Optional absent is supplied class is not applicable in context.
+     */
+    @Override
+    public abstract <DV extends DataObject> Optional<DataContainerCodecContext<DV,?>> possibleStreamChild(final Class<DV> childClass);
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + " [" + prototype.getBindingClass() + "]";
+    }
+
+    @Override
+    public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
+            final ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
+        if(cacheSpecifier.isEmpty()) {
+            return new NonCachingCodec<>(this);
+        }
+        return new CachingNormalizedNodeCodec<D>(this,ImmutableSet.copyOf(cacheSpecifier));
+    }
+
+    BindingStreamEventWriter createWriter(final NormalizedNodeStreamWriter domWriter) {
+        return  new BindingToNormalizedStreamWriter(this, domWriter);
+    }
+
+    @Nonnull
+    protected final <V> V childNonNull(@Nullable final V nullable, final YangInstanceIdentifier.PathArgument child,
+            final String message, final Object... args) {
+        if (nullable != null) {
+            return nullable;
+        }
+        MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
+        throw IncorrectNestingException.create(message, args);
+    }
+
+    @Nonnull
+    protected final <V> V childNonNull(@Nullable final V nullable, final QName child, final String message,
+            final Object... args) {
+        if (nullable != null) {
+            return nullable;
+        }
+        MissingSchemaException.checkModulePresent(factory().getRuntimeContext().getSchemaContext(), child);
+        throw IncorrectNestingException.create(message, args);
+    }
+
+    @Nonnull
+    protected final <V> V childNonNull(@Nullable final V nullable, final Class<?> childClass, final String message,
+            final Object... args) {
+        if (nullable != null) {
+            return nullable;
+        }
+        MissingSchemaForClassException.check(factory().getRuntimeContext(), childClass);
+        MissingClassInLoadingStrategyException.check(factory().getRuntimeContext().getStrategy(), childClass);
+        throw IncorrectNestingException.create(message, args);
+    }
+
+    DataObjectSerializer eventStreamSerializer() {
+        if(eventStreamSerializer == null) {
+            eventStreamSerializer = factory().getEventStreamSerializer(getBindingClass());
+        }
+        return eventStreamSerializer;
+    }
+
+    @Override
+    public NormalizedNode<?, ?> serialize(final D data) {
+        final NormalizedNodeResult result = new NormalizedNodeResult();
+        // We create DOM stream writer which produces normalized nodes
+        final NormalizedNodeStreamWriter domWriter = ImmutableNormalizedNodeStreamWriter.from(result);
+        writeAsNormalizedNode(data, domWriter);
+        return result.getResult();
+    }
+
+    @Override
+    public void writeAsNormalizedNode(final D data, final NormalizedNodeStreamWriter writer) {
+        try {
+            eventStreamSerializer().serialize(data, createWriter(writer));
+        } catch (final IOException e) {
+            throw new IllegalStateException("Failed to serialize Binding DTO",e);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataContainerCodecPrototype.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataContainerCodecPrototype.java
new file mode 100644 (file)
index 0000000..8398763
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.collect.Iterables;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.yangtools.binding.data.codec.impl.NodeCodecContext.CodecContextFactory;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+final class DataContainerCodecPrototype<T> implements NodeContextSupplier {
+
+    private final T schema;
+    private final QNameModule namespace;
+    private final CodecContextFactory factory;
+    private final Class<?> bindingClass;
+    private final InstanceIdentifier.Item<?> bindingArg;
+    private final YangInstanceIdentifier.PathArgument yangArg;
+    private volatile DataContainerCodecContext<?,T> instance = null;
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private DataContainerCodecPrototype(final Class<?> cls, final YangInstanceIdentifier.PathArgument arg, final T nodeSchema,
+            final CodecContextFactory factory) {
+        super();
+        this.bindingClass = cls;
+        this.yangArg = arg;
+        this.schema = nodeSchema;
+        this.factory = factory;
+        this.bindingArg = new InstanceIdentifier.Item(bindingClass);
+
+        if (arg instanceof AugmentationIdentifier) {
+            this.namespace = Iterables.getFirst(((AugmentationIdentifier) arg).getPossibleChildNames(), null).getModule();
+        } else {
+            this.namespace = arg.getNodeType().getModule();
+        }
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    static <T extends DataSchemaNode> DataContainerCodecPrototype<T> from(final Class<?> cls, final T schema,
+            final CodecContextFactory factory) {
+        final NodeIdentifier arg = new NodeIdentifier(schema.getQName());
+        return new DataContainerCodecPrototype(cls, arg, schema, factory);
+    }
+
+    static DataContainerCodecPrototype<SchemaContext> rootPrototype(final CodecContextFactory factory) {
+        final SchemaContext schema = factory.getRuntimeContext().getSchemaContext();
+        final NodeIdentifier arg = new NodeIdentifier(schema.getQName());
+        return new DataContainerCodecPrototype<SchemaContext>(DataRoot.class, arg, schema, factory);
+    }
+
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    static DataContainerCodecPrototype<?> from(final Class<?> augClass, final AugmentationIdentifier arg,
+            final AugmentationSchema schema, final CodecContextFactory factory) {
+        return new DataContainerCodecPrototype(augClass, arg, schema, factory);
+    }
+
+    static DataContainerCodecPrototype<NotificationDefinition> from(final Class<?> augClass, final NotificationDefinition schema, final CodecContextFactory factory) {
+        final PathArgument arg = new NodeIdentifier(schema.getQName());
+        return new DataContainerCodecPrototype<NotificationDefinition>(augClass,arg, schema, factory);
+    }
+
+    protected T getSchema() {
+        return schema;
+    }
+
+    protected QNameModule getNamespace() {
+        return namespace;
+    }
+
+    protected CodecContextFactory getFactory() {
+        return factory;
+    }
+
+    protected Class<?> getBindingClass() {
+        return bindingClass;
+    }
+
+    protected InstanceIdentifier.Item<?> getBindingArg() {
+        return bindingArg;
+    }
+
+    protected YangInstanceIdentifier.PathArgument getYangArg() {
+        return yangArg;
+    }
+
+    @Override
+    public DataContainerCodecContext<?,T> get() {
+        DataContainerCodecContext<?,T> tmp = instance;
+        if (tmp == null) {
+            synchronized (this) {
+                tmp = instance;
+                if (tmp == null) {
+                    tmp = createInstance();
+                    instance = tmp;
+                }
+            }
+        }
+
+        return tmp;
+    }
+
+    @GuardedBy("this")
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private DataContainerCodecContext<?,T> createInstance() {
+        // FIXME: make protected abstract
+        if (schema instanceof ContainerSchemaNode) {
+            return new ContainerNodeCodecContext(this);
+        } else if (schema instanceof ListSchemaNode) {
+            if (Identifiable.class.isAssignableFrom(getBindingClass())) {
+                return new KeyedListNodeCodecContext(this);
+            } else {
+                return new ListNodeCodecContext(this);
+            }
+        } else if (schema instanceof ChoiceSchemaNode) {
+            return new ChoiceNodeCodecContext(this);
+        } else if (schema instanceof AugmentationSchema) {
+            return new AugmentationNodeContext(this);
+        } else if (schema instanceof ChoiceCaseNode) {
+            return new CaseNodeCodecContext(this);
+        }
+        throw new IllegalArgumentException("Unsupported type " + bindingClass + " " + schema);
+    }
+
+    boolean isChoice() {
+        return schema instanceof ChoiceSchemaNode;
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataObjectCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/DataObjectCodecContext.java
new file mode 100644 (file)
index 0000000..f01ecbd
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSortedMap;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class DataObjectCodecContext<D extends DataObject,T extends DataNodeContainer> extends DataContainerCodecContext<D,T> {
+    private static final Logger LOG = LoggerFactory.getLogger(DataObjectCodecContext.class);
+    private static final Lookup LOOKUP = MethodHandles.publicLookup();
+    private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class, InvocationHandler.class);
+    private static final MethodType DATAOBJECT_TYPE = MethodType.methodType(DataObject.class, InvocationHandler.class);
+    private static final Comparator<Method> METHOD_BY_ALPHABET = new Comparator<Method>() {
+        @Override
+        public int compare(final Method o1, final Method o2) {
+            return o1.getName().compareTo(o2.getName());
+        }
+    };
+
+    private final ImmutableMap<String, LeafNodeCodecContext<?>> leafChild;
+    private final ImmutableMap<YangInstanceIdentifier.PathArgument, NodeContextSupplier> byYang;
+    private final ImmutableSortedMap<Method, NodeContextSupplier> byMethod;
+    private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byStreamClass;
+    private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byBindingArgClass;
+    private final ImmutableMap<AugmentationIdentifier, Type> possibleAugmentations;
+    private final MethodHandle proxyConstructor;
+
+    private final ConcurrentMap<YangInstanceIdentifier.PathArgument, DataContainerCodecPrototype<?>> byYangAugmented =
+            new ConcurrentHashMap<>();
+    private final ConcurrentMap<Class<?>, DataContainerCodecPrototype<?>> byStreamAugmented = new ConcurrentHashMap<>();
+
+
+    protected DataObjectCodecContext(final DataContainerCodecPrototype<T> prototype) {
+        super(prototype);
+
+        this.leafChild = factory().getLeafNodes(getBindingClass(), schema());
+
+        final Map<Class<?>, Method> clsToMethod = BindingReflections.getChildrenClassToMethod(getBindingClass());
+
+        final Map<YangInstanceIdentifier.PathArgument, NodeContextSupplier> byYangBuilder = new HashMap<>();
+        final SortedMap<Method, NodeContextSupplier> byMethodBuilder = new TreeMap<>(METHOD_BY_ALPHABET);
+        final Map<Class<?>, DataContainerCodecPrototype<?>> byStreamClassBuilder = new HashMap<>();
+        final Map<Class<?>, DataContainerCodecPrototype<?>> byBindingArgClassBuilder = new HashMap<>();
+
+        // Adds leaves to mapping
+        for (final LeafNodeCodecContext<?> leaf : leafChild.values()) {
+            byMethodBuilder.put(leaf.getGetter(), leaf);
+            byYangBuilder.put(leaf.getDomPathArgument(), leaf);
+        }
+
+        for (final Entry<Class<?>, Method> childDataObj : clsToMethod.entrySet()) {
+            final DataContainerCodecPrototype<?> childProto = loadChildPrototype(childDataObj.getKey());
+            byMethodBuilder.put(childDataObj.getValue(), childProto);
+            byStreamClassBuilder.put(childProto.getBindingClass(), childProto);
+            byYangBuilder.put(childProto.getYangArg(), childProto);
+            if (childProto.isChoice()) {
+                final ChoiceNodeCodecContext<?> choice = (ChoiceNodeCodecContext<?>) childProto.get();
+                for(final Class<?> cazeChild : choice.getCaseChildrenClasses()) {
+                    byBindingArgClassBuilder.put(cazeChild, childProto);
+                }
+            }
+        }
+        this.byMethod = ImmutableSortedMap.copyOfSorted(byMethodBuilder);
+        this.byYang = ImmutableMap.copyOf(byYangBuilder);
+        this.byStreamClass = ImmutableMap.copyOf(byStreamClassBuilder);
+        byBindingArgClassBuilder.putAll(byStreamClass);
+        this.byBindingArgClass = ImmutableMap.copyOf(byBindingArgClassBuilder);
+
+
+        if (Augmentable.class.isAssignableFrom(getBindingClass())) {
+            this.possibleAugmentations = factory().getRuntimeContext().getAvailableAugmentationTypes(schema());
+        } else {
+            this.possibleAugmentations = ImmutableMap.of();
+        }
+        reloadAllAugmentations();
+
+        final Class<?> proxyClass = Proxy.getProxyClass(getBindingClass().getClassLoader(),  new Class[] { getBindingClass(), AugmentationHolder.class });
+        try {
+            proxyConstructor = LOOKUP.findConstructor(proxyClass, CONSTRUCTOR_TYPE).asType(DATAOBJECT_TYPE);
+        } catch (NoSuchMethodException | IllegalAccessException e) {
+            throw new IllegalStateException("Failed to find contructor for class " + proxyClass);
+        }
+    }
+
+    private void reloadAllAugmentations() {
+        for (final Entry<AugmentationIdentifier, Type> augment : possibleAugmentations.entrySet()) {
+            final DataContainerCodecPrototype<?> augProto = getAugmentationPrototype(augment.getValue());
+            if (augProto != null) {
+                byYangAugmented.putIfAbsent(augProto.getYangArg(), augProto);
+                byStreamAugmented.putIfAbsent(augProto.getBindingClass(), augProto);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(final Class<DV> childClass) {
+        final DataContainerCodecPrototype<?> childProto = streamChildPrototype(childClass);
+        return (DataContainerCodecContext<DV, ?>) childNonNull(childProto, childClass, " Child %s is not valid child.",
+                childClass).get();
+    }
+
+    private final DataContainerCodecPrototype<?> streamChildPrototype(final Class<?> childClass) {
+        final DataContainerCodecPrototype<?> childProto = byStreamClass.get(childClass);
+        if (childProto != null) {
+            return childProto;
+        }
+        if (Augmentation.class.isAssignableFrom(childClass)) {
+            return augmentationByClass(childClass);
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <DV extends DataObject> Optional<DataContainerCodecContext<DV, ?>> possibleStreamChild(
+            final Class<DV> childClass) {
+        final DataContainerCodecPrototype<?> childProto = streamChildPrototype(childClass);
+        if(childProto != null) {
+            return Optional.<DataContainerCodecContext<DV,?>>of((DataContainerCodecContext<DV,?>) childProto.get());
+        }
+        return Optional.absent();
+    }
+
+    @Override
+    public DataContainerCodecContext<?,?> bindingPathArgumentChild(final InstanceIdentifier.PathArgument arg,
+            final List<YangInstanceIdentifier.PathArgument> builder) {
+
+        final Class<? extends DataObject> argType = arg.getType();
+        DataContainerCodecPrototype<?> ctxProto = byBindingArgClass.get(argType);
+        if (ctxProto == null && Augmentation.class.isAssignableFrom(argType)) {
+            ctxProto = augmentationByClass(argType);
+        }
+        final DataContainerCodecContext<?, ?> context =
+                childNonNull(ctxProto, argType, "Class %s is not valid child of %s", argType, getBindingClass()).get();
+        if (context instanceof ChoiceNodeCodecContext) {
+            final ChoiceNodeCodecContext<?> choice = (ChoiceNodeCodecContext<?>) context;
+            final DataContainerCodecContext<?, ?> caze = choice.getCazeByChildClass(arg.getType());
+            choice.addYangPathArgument(arg, builder);
+            caze.addYangPathArgument(arg, builder);
+            return caze.bindingPathArgumentChild(arg, builder);
+        }
+        context.addYangPathArgument(arg, builder);
+        return context;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public NodeCodecContext<D> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument arg) {
+        final NodeContextSupplier childSupplier;
+        if(arg instanceof NodeIdentifierWithPredicates) {
+            childSupplier = byYang.get(new NodeIdentifier(arg.getNodeType()));
+        } else if (arg instanceof AugmentationIdentifier) {
+            childSupplier = yangAugmentationChild((AugmentationIdentifier) arg);
+        } else {
+            childSupplier = byYang.get(arg);
+        }
+        childNonNull(childSupplier != null, arg, "Argument %s is not valid child of %s", arg, schema());
+        return (NodeCodecContext<D>) childSupplier.get();
+    }
+
+    protected final LeafNodeCodecContext<?> getLeafChild(final String name) {
+        final LeafNodeCodecContext<?> value = leafChild.get(name);
+        return IncorrectNestingException.checkNonNull(value, "Leaf %s is not valid for %s", name, getBindingClass());
+    }
+
+    private DataContainerCodecPrototype<?> loadChildPrototype(final Class<?> childClass) {
+        final DataSchemaNode origDef = factory().getRuntimeContext().getSchemaDefinition(childClass);
+        // Direct instantiation or use in same module in which grouping
+        // was defined.
+        DataSchemaNode sameName;
+        try {
+            sameName = schema().getDataChildByName(origDef.getQName());
+        } catch (final IllegalArgumentException e) {
+            sameName = null;
+        }
+        final DataSchemaNode childSchema;
+        if (sameName != null) {
+            // Exactly same schema node
+            if (origDef.equals(sameName)) {
+                childSchema = sameName;
+                // We check if instantiated node was added via uses
+                // statement and is instantiation of same grouping
+            } else if (origDef.equals(SchemaNodeUtils.getRootOriginalIfPossible(sameName))) {
+                childSchema = sameName;
+            } else {
+                // Node has same name, but clearly is different
+                childSchema = null;
+            }
+        } else {
+            // We are looking for instantiation via uses in other module
+            final QName instantiedName = QName.create(namespace(), origDef.getQName().getLocalName());
+            final DataSchemaNode potential = schema().getDataChildByName(instantiedName);
+            // We check if it is really instantiated from same
+            // definition as class was derived
+            if (potential != null && origDef.equals(SchemaNodeUtils.getRootOriginalIfPossible(potential))) {
+                childSchema = potential;
+            } else {
+                childSchema = null;
+            }
+        }
+        final DataSchemaNode nonNullChild =
+                childNonNull(childSchema, childClass, "Node %s does not have child named %s", schema(), childClass);
+        return DataContainerCodecPrototype.from(childClass, nonNullChild, factory());
+    }
+
+    private DataContainerCodecPrototype<?> yangAugmentationChild(final AugmentationIdentifier arg) {
+        final DataContainerCodecPrototype<?> firstTry = byYangAugmented.get(arg);
+        if (firstTry != null) {
+            return firstTry;
+        }
+        if (possibleAugmentations.containsKey(arg)) {
+            reloadAllAugmentations();
+            return byYangAugmented.get(arg);
+        }
+        return null;
+    }
+
+    @Nullable
+    private DataContainerCodecPrototype<?> augmentationByClass(@Nonnull final Class<?> childClass) {
+        final DataContainerCodecPrototype<?> firstTry = augmentationByClassOrEquivalentClass(childClass);
+        if (firstTry != null) {
+            return firstTry;
+        }
+        reloadAllAugmentations();
+        return augmentationByClassOrEquivalentClass(childClass);
+    }
+
+    @Nullable
+    private final DataContainerCodecPrototype<?> augmentationByClassOrEquivalentClass(@Nonnull final Class<?> childClass) {
+        final DataContainerCodecPrototype<?> childProto = byStreamAugmented.get(childClass);
+        if (childProto != null) {
+            return childProto;
+        }
+
+        /*
+         * It is potentially mismatched valid augmentation - we look up equivalent augmentation
+         * using reflection and walk all stream child and compare augmenations classes if they are
+         * equivalent.
+         *
+         * FIXME: Cache mapping of mismatched augmentation to real one, to speed up lookup.
+         */
+        @SuppressWarnings("rawtypes")
+        final Class<?> augTarget = BindingReflections.findAugmentationTarget((Class) childClass);
+        if ((getBindingClass().equals(augTarget))) {
+            for (final DataContainerCodecPrototype<?> realChild : byStreamAugmented.values()) {
+                if (Augmentation.class.isAssignableFrom(realChild.getBindingClass())
+                        && BindingReflections.isSubstitutionFor(childClass, realChild.getBindingClass())) {
+                    return realChild;
+                }
+            }
+        }
+        return null;
+    }
+
+    private DataContainerCodecPrototype<?> getAugmentationPrototype(final Type value) {
+        final ClassLoadingStrategy loader = factory().getRuntimeContext().getStrategy();
+        @SuppressWarnings("rawtypes")
+        final Class augClass;
+        try {
+            augClass = loader.loadClass(value);
+        } catch (final ClassNotFoundException e) {
+            LOG.debug("Failed to load augmentation prototype for {}. Will be retried when needed.", value, e);
+            return null;
+        }
+
+        @SuppressWarnings("unchecked")
+        final Entry<AugmentationIdentifier, AugmentationSchema> augSchema = factory().getRuntimeContext()
+                .getResolvedAugmentationSchema(schema(), augClass);
+        return DataContainerCodecPrototype.from(augClass, augSchema.getKey(), augSchema.getValue(), factory());
+    }
+
+    @SuppressWarnings("rawtypes")
+    Object getBindingChildValue(final Method method, final NormalizedNodeContainer domData) {
+        final NodeCodecContext<?> childContext = byMethod.get(method).get();
+        @SuppressWarnings("unchecked")
+        final Optional<NormalizedNode<?, ?>> domChild = domData.getChild(childContext.getDomPathArgument());
+        if (domChild.isPresent()) {
+            return childContext.deserializeObject(domChild.get());
+        }
+        return null;
+    }
+
+    protected final D createBindingProxy(final NormalizedNodeContainer<?, ?, ?> node) {
+        try {
+            return (D) proxyConstructor.invokeExact((InvocationHandler)new LazyDataObject<>(this, node));
+        } catch (final Throwable e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAllAugmentationsFrom(
+            final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> data) {
+
+        @SuppressWarnings("rawtypes")
+        final Map map = new HashMap<>();
+
+        for (final NormalizedNode<?, ?> childValue : data.getValue()) {
+            if (childValue instanceof AugmentationNode) {
+                final AugmentationNode augDomNode = (AugmentationNode) childValue;
+                final DataContainerCodecPrototype<?> codecProto = yangAugmentationChild(augDomNode.getIdentifier());
+                if(codecProto != null) {
+                    final DataContainerCodecContext<?, ?> codec = codecProto.get();
+                    map.put(codec.getBindingClass(), codec.deserializeObject(augDomNode));
+                }
+            }
+        }
+        for (final DataContainerCodecPrototype<?> value : byStreamAugmented.values()) {
+            final Optional<NormalizedNode<?, ?>> augData = data.getChild(value.getYangArg());
+            if (augData.isPresent()) {
+                map.put(value.getBindingClass(), value.get().deserializeObject(augData.get()));
+            }
+        }
+        return map;
+    }
+
+    public Collection<Method> getHashCodeAndEqualsMethods() {
+        return byMethod.keySet();
+    }
+
+    @Override
+    public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
+        Preconditions.checkArgument(getDomPathArgument().equals(arg));
+        return bindingArg();
+    }
+
+    @Override
+    public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
+        Preconditions.checkArgument(bindingArg().equals(arg));
+        return getDomPathArgument();
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/EncapsulatedValueCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/EncapsulatedValueCodec.java
new file mode 100644 (file)
index 0000000..3de5085
--- /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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+import org.opendaylight.yangtools.binding.data.codec.impl.ValueTypeCodec.SchemaUnawareCodec;
+
+/**
+ *
+ * Derived YANG types are just immutable value holders for simple value
+ * types, which are same as in NormalizedNode model.
+ *
+ */
+final class EncapsulatedValueCodec extends ReflectionBasedCodec implements SchemaUnawareCodec {
+    private static final Lookup LOOKUP = MethodHandles.publicLookup();
+    private static final MethodType OBJ_METHOD = MethodType.methodType(Object.class, Object.class);
+    private final MethodHandle constructor;
+    private final MethodHandle getter;
+
+    private EncapsulatedValueCodec(final Class<?> typeClz, final MethodHandle constructor, final MethodHandle getter) {
+        super(typeClz);
+        this.constructor = Preconditions.checkNotNull(constructor);
+        this.getter = Preconditions.checkNotNull(getter);
+    }
+
+    static Callable<EncapsulatedValueCodec> loader(final Class<?> typeClz) {
+        return new Callable<EncapsulatedValueCodec>() {
+            @Override
+            public EncapsulatedValueCodec call() throws Exception {
+                final Method m = typeClz.getMethod("getValue");
+                final MethodHandle getter = LOOKUP.unreflect(m).asType(OBJ_METHOD);
+                final MethodHandle constructor = LOOKUP.findConstructor(typeClz, MethodType.methodType(void.class, m.getReturnType())).asType(OBJ_METHOD);
+                return new EncapsulatedValueCodec(typeClz, constructor, getter);
+            }
+        };
+    }
+
+    @Override
+    public Object deserialize(final Object input) {
+        try {
+            return constructor.invokeExact(input);
+        } catch (Throwable e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    @Override
+    public Object serialize(final Object input) {
+        try {
+            return getter.invokeExact(input);
+        } catch (Throwable e) {
+            throw Throwables.propagate(e);
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/EnumerationCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/EnumerationCodec.java
new file mode 100644 (file)
index 0000000..a35a562
--- /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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableBiMap;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import org.opendaylight.yangtools.binding.data.codec.impl.ValueTypeCodec.SchemaUnawareCodec;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
+
+final class EnumerationCodec extends ReflectionBasedCodec implements SchemaUnawareCodec {
+
+    private final ImmutableBiMap<String, Enum<?>> yangValueToBinding;
+
+    public EnumerationCodec(final Class<? extends Enum<?>> enumeration, final Map<String, Enum<?>> schema) {
+        super(enumeration);
+        yangValueToBinding = ImmutableBiMap.copyOf(schema);
+    }
+
+    static Callable<EnumerationCodec> loader(final Class<?> returnType,
+            final EnumTypeDefinition enumSchema) {
+        Preconditions.checkArgument(Enum.class.isAssignableFrom(returnType));
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        final Class<? extends Enum<?>> enumType = (Class) returnType;
+        return new Callable<EnumerationCodec>() {
+            @Override
+            public EnumerationCodec call() throws Exception {
+
+                Map<String, Enum<?>> nameToValue = new HashMap<>();
+                for (Enum<?> enumValue : enumType.getEnumConstants()) {
+                    nameToValue.put(enumValue.toString(), enumValue);
+                }
+                Map<String, Enum<?>> yangNameToBinding = new HashMap<>();
+                for (EnumPair yangValue : enumSchema.getValues()) {
+                    final String bindingName = BindingMapping.getClassName(yangValue.getName());
+                    final Enum<?> bindingVal = nameToValue.get(bindingName);
+                    yangNameToBinding.put(yangValue.getName(), bindingVal);
+                }
+                return new EnumerationCodec(enumType, yangNameToBinding);
+            }
+        };
+    }
+
+    @Override
+    public Object deserialize(final Object input) {
+        Enum<?> value = yangValueToBinding.get(input);
+        Preconditions.checkArgument(value != null, "Invalid enumeration value %s. Valid values are %s", input,
+                yangValueToBinding.keySet());
+        return value;
+    }
+
+    @Override
+    public Object serialize(final Object input) {
+        Preconditions.checkArgument(typeClass.isInstance(input), "Input must be instance of %s", typeClass);
+        return yangValueToBinding.inverse().get(input);
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ForwardingBindingStreamEventWriter.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ForwardingBindingStreamEventWriter.java
new file mode 100644 (file)
index 0000000..d6323df
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import java.io.IOException;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+//FIXME: Consider moving this to yang.binding.util.* in Be
+abstract class ForwardingBindingStreamEventWriter implements BindingStreamEventWriter {
+
+    protected abstract BindingStreamEventWriter delegate();
+
+    @Override
+    public void leafNode(final String localName, final Object value) throws IOException, IllegalArgumentException {
+        delegate().leafNode(localName, value);
+    }
+
+
+    @Override
+    public void startLeafSet(final String localName, final int childSizeHint) throws IOException, IllegalArgumentException {
+        delegate().startLeafSet(localName, childSizeHint);
+    }
+
+
+    @Override
+    public void leafSetEntryNode(final Object value) throws IOException, IllegalArgumentException {
+        delegate().leafSetEntryNode(value);
+    }
+
+
+    @Override
+    public void startContainerNode(final Class<? extends DataObject> container, final int childSizeHint) throws IOException,
+            IllegalArgumentException {
+        delegate().startContainerNode(container, childSizeHint);
+    }
+
+
+    @Override
+    public void startUnkeyedList(final Class<? extends DataObject> localName, final int childSizeHint) throws IOException,
+            IllegalArgumentException {
+        delegate().startUnkeyedList(localName, childSizeHint);
+    }
+
+
+    @Override
+    public void startUnkeyedListItem(final int childSizeHint) throws IOException, IllegalStateException {
+        delegate().startUnkeyedListItem(childSizeHint);
+    }
+
+
+    @Override
+    public <T extends DataObject & Identifiable<?>> void startMapNode(final Class<T> mapEntryType, final int childSizeHint)
+            throws IOException, IllegalArgumentException {
+        delegate().startMapNode(mapEntryType, childSizeHint);
+    }
+
+
+    @Override
+    public <T extends DataObject & Identifiable<?>> void startOrderedMapNode(final Class<T> mapEntryType, final int childSizeHint)
+            throws IOException, IllegalArgumentException {
+        delegate().startOrderedMapNode(mapEntryType, childSizeHint);
+    }
+
+
+    @Override
+    public void startMapEntryNode(final Identifier<?> keyValues, final int childSizeHint) throws IOException,
+            IllegalArgumentException {
+        delegate().startMapEntryNode(keyValues, childSizeHint);
+    }
+
+
+    @Override
+    public void startChoiceNode(final Class<? extends DataContainer> choice, final int childSizeHint) throws IOException,
+            IllegalArgumentException {
+        delegate().startChoiceNode(choice, childSizeHint);
+    }
+
+
+    @Override
+    public void startCase(final Class<? extends DataObject> caze, final int childSizeHint) throws IOException,
+            IllegalArgumentException {
+        delegate().startCase(caze, childSizeHint);
+    }
+
+
+    @Override
+    public void startAugmentationNode(final Class<? extends Augmentation<?>> augmentationType) throws IOException,
+            IllegalArgumentException {
+        delegate().startAugmentationNode(augmentationType);
+    }
+
+
+    @Override
+    public void anyxmlNode(final String name, final Object value) throws IOException, IllegalArgumentException {
+        delegate().anyxmlNode(name, value);
+    }
+
+
+    @Override
+    public void endNode() throws IOException, IllegalStateException {
+        delegate().endNode();
+    }
+
+
+    @Override
+    public void flush() throws IOException {
+        delegate().flush();
+    }
+
+
+    @Override
+    public void close() throws IOException {
+        delegate().close();
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IdentifiableItemCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IdentifiableItemCodec.java
new file mode 100644 (file)
index 0000000..0923117
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class IdentifiableItemCodec implements Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> {
+    private static final Comparator<QName> KEYARG_COMPARATOR = new Comparator<QName>() {
+        @Override
+        public int compare(final QName q1, final QName q2) {
+            return q1.getLocalName().compareToIgnoreCase(q2.getLocalName());
+        }
+    };
+    private static final Lookup LOOKUP = MethodHandles.publicLookup();
+    private final Map<QName, ValueContext> keyValueContexts;
+    private final List<QName> keysInBindingOrder;
+    private final ListSchemaNode schema;
+    private final Class<?> identifiable;
+    private final MethodHandle ctorInvoker;
+    private final MethodHandle ctor;
+
+    public IdentifiableItemCodec(final ListSchemaNode schema, final Class<? extends Identifier<?>> keyClass,
+            final Class<?> identifiable, final Map<QName, ValueContext> keyValueContexts) {
+        this.schema = schema;
+        this.identifiable = identifiable;
+
+        try {
+            ctor = LOOKUP.unreflectConstructor(getConstructor(keyClass));
+        } catch (IllegalAccessException e) {
+            throw new IllegalArgumentException("Missing construct in class " + keyClass);
+        }
+        final MethodHandle inv = MethodHandles.spreadInvoker(ctor.type(), 0);
+        this.ctorInvoker = inv.asType(inv.type().changeReturnType(Identifier.class));
+
+        /*
+         * We need to re-index to make sure we instantiate nodes in the order in which
+         * they are defined.
+         */
+        final Map<QName, ValueContext> keys = new LinkedHashMap<>();
+        for (final QName qname : schema.getKeyDefinition()) {
+            keys.put(qname, keyValueContexts.get(qname));
+        }
+        this.keyValueContexts = ImmutableMap.copyOf(keys);
+
+        /*
+         * When instantiating binding objects we need to specify constructor arguments
+         * in alphabetic order. We play a couple of tricks here to optimize CPU/memory
+         * trade-offs.
+         *
+         * We do not have to perform a sort if the source collection has less than two
+         * elements.
+
+         * We always perform an ImmutableList.copyOf(), as that will turn into a no-op
+         * if the source is already immutable. It will also produce optimized implementations
+         * for empty and singleton collections.
+         *
+         * BUG-2755: remove this if order is made declaration-order-dependent
+         */
+        final List<QName> unsortedKeys = schema.getKeyDefinition();
+        final List<QName> sortedKeys;
+        if (unsortedKeys.size() > 1) {
+            final List<QName> tmp = new ArrayList<>(unsortedKeys);
+            Collections.sort(tmp, KEYARG_COMPARATOR);
+            sortedKeys = tmp;
+        } else {
+            sortedKeys = unsortedKeys;
+        }
+
+        this.keysInBindingOrder = ImmutableList.copyOf(sortedKeys);
+    }
+
+    @Override
+    public IdentifiableItem<?, ?> deserialize(final NodeIdentifierWithPredicates input) {
+        final Object[] bindingValues = new Object[keysInBindingOrder.size()];
+        int offset = 0;
+
+        for (final QName key : keysInBindingOrder) {
+            final Object yangValue = input.getKeyValues().get(key);
+            bindingValues[offset++] = keyValueContexts.get(key).deserialize(yangValue);
+        }
+
+        final Identifier<?> identifier;
+        try {
+            identifier = (Identifier<?>) ctorInvoker.invokeExact(ctor, bindingValues);
+        } catch (Throwable e) {
+            throw Throwables.propagate(e);
+        }
+
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        final IdentifiableItem identifiableItem = new IdentifiableItem(identifiable, identifier);
+        return identifiableItem;
+    }
+
+    @Override
+    public NodeIdentifierWithPredicates serialize(final IdentifiableItem<?, ?> input) {
+        final Object value = input.getKey();
+
+        final Map<QName, Object> values = new LinkedHashMap<>();
+        for (final Entry<QName, ValueContext> valueCtx : keyValueContexts.entrySet()) {
+            values.put(valueCtx.getKey(), valueCtx.getValue().getAndSerialize(value));
+        }
+        return new NodeIdentifierWithPredicates(schema.getQName(), values);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    private static Constructor<? extends Identifier<?>> getConstructor(final Class<? extends Identifier<?>> clazz) {
+        for (@SuppressWarnings("rawtypes") final Constructor constr : clazz.getConstructors()) {
+            final Class<?>[] parameters = constr.getParameterTypes();
+            if (!clazz.equals(parameters[0])) {
+                // It is not copy constructor;
+                return constr;
+            }
+        }
+        throw new IllegalArgumentException("Supplied class " + clazz + "does not have required constructor.");
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IdentityCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IdentityCodec.java
new file mode 100644 (file)
index 0000000..6dd631a
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+
+final class IdentityCodec implements Codec<QName, Class<?>> {
+    private final BindingRuntimeContext context;
+
+    IdentityCodec(final BindingRuntimeContext context) {
+        this.context = Preconditions.checkNotNull(context);
+    }
+
+    @Override
+    public Class<?> deserialize(final QName input) {
+        Preconditions.checkArgument(input != null, "Input must not be null.");
+        return context.getIdentityClass(input);
+    }
+
+    @Override
+    public QName serialize(final Class<?> input) {
+        Preconditions.checkArgument(BaseIdentity.class.isAssignableFrom(input));
+        return BindingReflections.findQName(input);
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IncorrectNestingException.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/IncorrectNestingException.java
new file mode 100644 (file)
index 0000000..5e7ec6a
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+/**
+ *
+ * Thrown where incorrect nesting of data structures was detected
+ * and was caused by user.
+ *
+ */
+public class IncorrectNestingException extends IllegalArgumentException {
+
+    private static final long serialVersionUID = 1L;
+
+    protected IncorrectNestingException(final String message) {
+        super(message);
+    }
+
+    public static IncorrectNestingException create(final String message, final Object... args) {
+        return new IncorrectNestingException(String.format(message, args));
+    }
+
+    public static void check(final boolean check, final String message, final Object... args) {
+        if(!check) {
+            throw IncorrectNestingException.create(message, args);
+        }
+    }
+
+    @Nonnull
+    public static <V> V checkNonNull(@Nullable final V nullable, final String message, final Object... args) {
+        if(nullable != null) {
+            return nullable;
+        }
+        throw IncorrectNestingException.create(message, args);
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/InstanceIdentifierCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/InstanceIdentifierCodec.java
new file mode 100644 (file)
index 0000000..377f374
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Iterables;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+
+final class InstanceIdentifierCodec implements Codec<YangInstanceIdentifier, InstanceIdentifier<?>> {
+    private final BindingCodecContext context;
+
+    InstanceIdentifierCodec(final BindingCodecContext context) {
+        this.context = Preconditions.checkNotNull(context);
+    }
+
+    @Override
+    public YangInstanceIdentifier serialize(final InstanceIdentifier<?> input) {
+        final List<PathArgument> domArgs = new ArrayList<>();
+        context.getCodecContextNode(input, domArgs);
+        return YangInstanceIdentifier.create(domArgs);
+    }
+
+    @Override
+    public InstanceIdentifier<?> deserialize(final YangInstanceIdentifier input) {
+        final List<InstanceIdentifier.PathArgument> builder = new ArrayList<>();
+        final NodeCodecContext<?> codec = context.getCodecContextNode(input, builder);
+        if (codec == null) {
+            return null;
+        }
+        if (codec instanceof ListNodeCodecContext && Iterables.getLast(builder) instanceof InstanceIdentifier.Item) {
+            // We ended up in list, but without key, which means it represent list as a whole,
+            // which is not binding representable.
+            return null;
+        }
+        return InstanceIdentifier.create(builder);
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/KeyedListNodeCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/KeyedListNodeCodecContext.java
new file mode 100644 (file)
index 0000000..865a4ed
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+final class KeyedListNodeCodecContext<D extends DataObject & Identifiable<?>> extends ListNodeCodecContext<D> {
+    private final Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> codec;
+    private final Method keyGetter;
+
+    KeyedListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
+        super(prototype);
+
+        this.codec = factory().getPathArgumentCodec(getBindingClass(), schema());
+        try {
+            this.keyGetter = getBindingClass().getMethod("getKey");
+        } catch (NoSuchMethodException e) {
+            throw new IllegalStateException("Required method not available", e);
+        }
+    }
+
+    @Override
+    protected void addYangPathArgument(final InstanceIdentifier.PathArgument arg, final List<YangInstanceIdentifier.PathArgument> builder) {
+        /*
+         * DOM Instance Identifier for list is always represent by two
+         * entries one for map and one for children. This is also true for
+         * wildcarded instance identifiers
+         */
+        if (builder == null) {
+            return;
+        }
+
+        super.addYangPathArgument(arg, builder);
+        if (arg instanceof IdentifiableItem<?, ?>) {
+            builder.add(codec.serialize((IdentifiableItem<?, ?>) arg));
+        } else {
+            // Adding wildcarded
+            super.addYangPathArgument(arg, builder);
+        }
+    }
+
+    @Override
+    @SuppressWarnings("rawtypes")
+    Object getBindingChildValue(final Method method, final NormalizedNodeContainer dom) {
+        if (dom instanceof MapEntryNode && keyGetter.equals(method)) {
+            NodeIdentifierWithPredicates identifier = ((MapEntryNode) dom).getIdentifier();
+            return codec.deserialize(identifier).getKey();
+        } else {
+            return super.getBindingChildValue(method, dom);
+        }
+    }
+
+    @Override
+    protected InstanceIdentifier.PathArgument getBindingPathArgument(final org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument domArg) {
+        if (domArg instanceof NodeIdentifierWithPredicates) {
+            return codec.deserialize((NodeIdentifierWithPredicates) domArg);
+        }
+        return super.getBindingPathArgument(domArg);
+    }
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    NodeIdentifierWithPredicates serialize(final Identifier<?> key) {
+        return codec.serialize(new IdentifiableItem(getBindingClass(), key));
+    }
+
+    @Override
+    public YangInstanceIdentifier.PathArgument serializePathArgument(InstanceIdentifier.PathArgument arg) {
+        if(arg instanceof IdentifiableItem) {
+            return codec.serialize((IdentifiableItem<?,?>) arg);
+        }
+        return super.serializePathArgument(arg);
+    }
+
+    @Override
+    public InstanceIdentifier.PathArgument deserializePathArgument(YangInstanceIdentifier.PathArgument arg) {
+        if(arg instanceof NodeIdentifierWithPredicates) {
+            return codec.deserialize((NodeIdentifierWithPredicates) arg);
+        }
+        return super.deserializePathArgument(arg);
+    }
+
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/LazyDataObject.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/LazyDataObject.java
new file mode 100644 (file)
index 0000000..eb7e126
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import org.opendaylight.yangtools.binding.data.codec.util.AugmentationReader;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class LazyDataObject<D extends DataObject> implements InvocationHandler, AugmentationReader {
+
+    private static final Logger LOG = LoggerFactory.getLogger(LazyDataObject.class);
+    private static final String GET_IMPLEMENTED_INTERFACE = "getImplementedInterface";
+    private static final String TO_STRING = "toString";
+    private static final String EQUALS = "equals";
+    private static final String GET_AUGMENTATION = "getAugmentation";
+    private static final String HASHCODE = "hashCode";
+    private static final String AUGMENTATIONS = "augmentations";
+    private static final Object NULL_VALUE = new Object();
+
+    private final ConcurrentHashMap<Method, Object> cachedData = new ConcurrentHashMap<>();
+    private final NormalizedNodeContainer<?, PathArgument, NormalizedNode<?, ?>> data;
+    private final DataObjectCodecContext<D,?> context;
+
+    private volatile ImmutableMap<Class<? extends Augmentation<?>>, Augmentation<?>> cachedAugmentations = null;
+    private volatile Integer cachedHashcode = null;
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    LazyDataObject(final DataObjectCodecContext<D,?> ctx, final NormalizedNodeContainer data) {
+        this.context = Preconditions.checkNotNull(ctx, "Context must not be null");
+        this.data = Preconditions.checkNotNull(data, "Data must not be null");
+    }
+
+    @Override
+    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+        if (method.getParameterTypes().length == 0) {
+            final String name = method.getName();
+            if (GET_IMPLEMENTED_INTERFACE.equals(name)) {
+                return context.getBindingClass();
+            } else if (TO_STRING.equals(name)) {
+                return bindingToString();
+            } else if (HASHCODE.equals(name)) {
+                return bindingHashCode();
+            } else if (AUGMENTATIONS.equals(name)) {
+                return getAugmentationsImpl();
+            }
+            return getBindingData(method);
+        } else if (GET_AUGMENTATION.equals(method.getName())) {
+            return getAugmentationImpl((Class<?>) args[0]);
+        } else if (EQUALS.equals(method.getName())) {
+            return bindingEquals(args[0]);
+        }
+        throw new UnsupportedOperationException("Unsupported method " + method);
+    }
+
+    private boolean bindingEquals(final Object other) {
+        if (other == null) {
+            return false;
+        }
+        if (!context.getBindingClass().isAssignableFrom(other.getClass())) {
+            return false;
+        }
+        try {
+            for (final Method m : context.getHashCodeAndEqualsMethods()) {
+                final Object thisValue = getBindingData(m);
+                final Object otherValue = m.invoke(other);
+                if(!Objects.equals(thisValue, otherValue)) {
+                    return false;
+                }
+            }
+        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+            LOG.warn("Can not determine equality of {} and {}", this, other, e);
+            return false;
+        }
+        return true;
+    }
+
+    private Integer bindingHashCode() {
+        final Integer ret = cachedHashcode;
+        if (ret != null) {
+            return ret;
+        }
+
+        final int prime = 31;
+        int result = 1;
+        for (final Method m : context.getHashCodeAndEqualsMethods()) {
+            final Object value = getBindingData(m);
+            result = prime * result + ((value == null) ? 0 : value.hashCode());
+        }
+        if (Augmentable.class.isAssignableFrom(context.getBindingClass())) {
+            result = prime * result + (getAugmentationsImpl().hashCode());
+        }
+        cachedHashcode = result;
+        return result;
+    }
+
+    private Object getBindingData(final Method method) {
+        Object cached = cachedData.get(method);
+        if (cached == null) {
+            final Object readedValue = context.getBindingChildValue(method, data);
+            if (readedValue == null) {
+                cached = NULL_VALUE;
+            } else {
+                cached = readedValue;
+            }
+            cachedData.putIfAbsent(method, cached);
+        }
+
+        return cached == NULL_VALUE ? null : cached;
+    }
+
+    private Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentationsImpl() {
+        ImmutableMap<Class<? extends Augmentation<?>>, Augmentation<?>> ret = cachedAugmentations;
+        if (ret == null) {
+            synchronized (this) {
+                ret = cachedAugmentations;
+                if (ret == null) {
+                    ret = ImmutableMap.copyOf(context.getAllAugmentationsFrom(data));
+                    cachedAugmentations = ret;
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    @Override
+    public Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object obj) {
+        Preconditions.checkArgument(this == Proxy.getInvocationHandler(obj),
+                "Supplied object is not associated with this proxy handler");
+
+        return getAugmentationsImpl();
+    }
+
+    private Object getAugmentationImpl(final Class<?> cls) {
+        final ImmutableMap<Class<? extends Augmentation<?>>, Augmentation<?>> aug = cachedAugmentations;
+        if (aug != null) {
+            return aug.get(cls);
+        }
+        Preconditions.checkNotNull(cls,"Supplied augmentation must not be null.");
+
+        @SuppressWarnings({"unchecked","rawtypes"})
+        final Optional<DataContainerCodecContext<?,?>> augCtx= context.possibleStreamChild((Class) cls);
+        if(augCtx.isPresent()) {
+            final Optional<NormalizedNode<?, ?>> augData = data.getChild(augCtx.get().getDomPathArgument());
+            if (augData.isPresent()) {
+                return augCtx.get().deserialize(augData.get());
+            }
+        }
+        return null;
+    }
+
+    public String bindingToString() {
+        final ToStringHelper helper = MoreObjects.toStringHelper(context.getBindingClass()).omitNullValues();
+
+        for (final Method m :context.getHashCodeAndEqualsMethods()) {
+            helper.add(m.getName(), getBindingData(m));
+        }
+        if (Augmentable.class.isAssignableFrom(context.getBindingClass())) {
+            helper.add("augmentations", getAugmentationsImpl());
+        }
+        return helper.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + context.hashCode();
+        result = prime * result + data.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final LazyDataObject<?> other = (LazyDataObject<?>) obj;
+        if (context == null) {
+            if (other.context != null) {
+                return false;
+            }
+        } else if (!context.equals(other.context)) {
+            return false;
+        }
+        if (data == null) {
+            if (other.data != null) {
+                return false;
+            }
+        } else if (!data.equals(other.data)) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/LeafNodeCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/LeafNodeCodecContext.java
new file mode 100644 (file)
index 0000000..81d9f3a
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeNode;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+final class LeafNodeCodecContext<D extends DataObject> extends NodeCodecContext<D> implements NodeContextSupplier {
+
+    private final YangInstanceIdentifier.PathArgument yangIdentifier;
+    private final Codec<Object, Object> valueCodec;
+    private final Method getter;
+
+    public LeafNodeCodecContext(final DataSchemaNode schema, final Codec<Object, Object> codec, final Method getter) {
+        this.yangIdentifier = new YangInstanceIdentifier.NodeIdentifier(schema.getQName());
+        this.valueCodec = codec;
+        this.getter = getter;
+    }
+
+    @Override
+    protected YangInstanceIdentifier.PathArgument getDomPathArgument() {
+        return (yangIdentifier);
+    }
+
+    protected Codec<Object, Object> getValueCodec() {
+        return valueCodec;
+    }
+
+    @Override
+    public D deserialize(final NormalizedNode<?, ?> normalizedNode) {
+        throw new UnsupportedOperationException("Leaf can not be deserialized to DataObject");
+    }
+
+    @Override
+    public NodeCodecContext<?> get() {
+        return this;
+    }
+
+    final Method getGetter() {
+        return getter;
+    }
+
+    @Override
+    public BindingCodecTreeNode<?> bindingPathArgumentChild(final PathArgument arg,
+            final List<YangInstanceIdentifier.PathArgument> builder) {
+        throw new IllegalArgumentException("Leaf does not have children");
+    }
+
+    @Override
+    public BindingNormalizedNodeCachingCodec<D> createCachingCodec(
+            final ImmutableCollection<Class<? extends DataObject>> cacheSpecifier) {
+        throw new UnsupportedOperationException("Leaves does not support caching codec.");
+    }
+
+    @Override
+    public Class<D> getBindingClass() {
+        throw new UnsupportedOperationException("Leaf does not have DataObject representation");
+    }
+
+    @Override
+    public NormalizedNode<?, ?> serialize(final D data) {
+        throw new UnsupportedOperationException("Separete serialization of leaf node is not supported.");
+    }
+
+    @Override
+    public void writeAsNormalizedNode(final D data, final NormalizedNodeStreamWriter writer) {
+        throw new UnsupportedOperationException("Separete serialization of leaf node is not supported.");
+    }
+
+    @Override
+    public <E extends DataObject> BindingCodecTreeNode<E> streamChild(final Class<E> childClass) {
+        throw new IllegalArgumentException("Leaf does not have children");
+    }
+
+    @Override
+    public <E extends DataObject> Optional<? extends BindingCodecTreeNode<E>> possibleStreamChild(
+            final Class<E> childClass) {
+        throw new IllegalArgumentException("Leaf does not have children");
+    }
+
+    @Override
+    public BindingCodecTreeNode<?> yangPathArgumentChild(final YangInstanceIdentifier.PathArgument child) {
+        throw new IllegalArgumentException("Leaf does not have children");
+    }
+
+    @Override
+    protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
+        if (normalizedNode instanceof LeafNode<?>) {
+            return valueCodec.deserialize(normalizedNode.getValue());
+        } else if(normalizedNode instanceof LeafSetNode<?>) {
+            @SuppressWarnings("unchecked")
+            final Collection<LeafSetEntryNode<Object>> domValues = ((LeafSetNode<Object>) normalizedNode).getValue();
+            final List<Object> result = new ArrayList<>(domValues.size());
+            for (final LeafSetEntryNode<Object> valueNode : domValues) {
+                result.add(valueCodec.deserialize(valueNode.getValue()));
+            }
+            return result;
+        }
+        return null;
+    }
+
+    @Override
+    public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
+        Preconditions.checkArgument(getDomPathArgument().equals(arg));
+        return null;
+    }
+
+    @Override
+    public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
+        return getDomPathArgument();
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ListNodeCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ListNodeCodecContext.java
new file mode 100644 (file)
index 0000000..919df10
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+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.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+class ListNodeCodecContext<D extends DataObject> extends DataObjectCodecContext<D,ListSchemaNode> {
+    protected ListNodeCodecContext(final DataContainerCodecPrototype<ListSchemaNode> prototype) {
+        super(prototype);
+    }
+
+    @Override
+    public D deserialize(final NormalizedNode<?, ?> node) {
+        if (node instanceof MapEntryNode) {
+            return fromMapEntry((MapEntryNode) node);
+        } else if (node instanceof UnkeyedListEntryNode) {
+            return fromUnkeyedListEntry((UnkeyedListEntryNode) node);
+        } else {
+            throw new IllegalStateException("Unsupported data type " + node.getClass());
+        }
+    }
+
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> node) {
+        if (node instanceof MapNode) {
+            return fromMap((MapNode) node);
+        } else if (node instanceof MapEntryNode) {
+            return fromMapEntry((MapEntryNode) node);
+        } else if (node instanceof UnkeyedListNode) {
+            return fromUnkeyedList((UnkeyedListNode) node);
+        } else if (node instanceof UnkeyedListEntryNode) {
+            return fromUnkeyedListEntry((UnkeyedListEntryNode) node);
+        } else {
+            throw new IllegalStateException("Unsupported data type " + node.getClass());
+        }
+    }
+
+    private List<D> fromMap(final MapNode nodes) {
+        List<D> ret = new ArrayList<>(nodes.getValue().size());
+        for (MapEntryNode node : nodes.getValue()) {
+            ret.add(fromMapEntry(node));
+        }
+        return ret;
+    }
+
+    private D fromMapEntry(final MapEntryNode node) {
+        return createBindingProxy(node);
+    }
+
+    private D fromUnkeyedListEntry(final UnkeyedListEntryNode node) {
+        return createBindingProxy(node);
+    }
+
+    private List<D> fromUnkeyedList(final UnkeyedListNode nodes) {
+        // FIXME: Could be this lazy transformed list?
+        List<D> ret = new ArrayList<>(nodes.getValue().size());
+        for (UnkeyedListEntryNode node : nodes.getValue()) {
+            ret.add(fromUnkeyedListEntry(node));
+        }
+        return ret;
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingClassInLoadingStrategyException.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingClassInLoadingStrategyException.java
new file mode 100644 (file)
index 0000000..aca197e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
+
+/**
+ *
+ * Thrown when user schema for supplied binding class is available in present schema context, but
+ * binding class itself is not known to codecs because backing class loading strategy did not
+ * provided it.
+ *
+ */
+public class MissingClassInLoadingStrategyException extends MissingSchemaException {
+
+    private static final long serialVersionUID = 1L;
+
+    protected MissingClassInLoadingStrategyException(final String msg, final Throwable cause) {
+        super(msg, cause);
+    }
+
+    public static void check(final ClassLoadingStrategy strategy, final Class<?> childClass) {
+        try {
+            strategy.loadClass(childClass.getName());
+        } catch (final ClassNotFoundException e) {
+            final String message =
+                    String.format("User supplied class %s is not available in %s.", childClass.getName(), strategy);
+            throw new MissingClassInLoadingStrategyException(message, e);
+        }
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaException.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaException.java
new file mode 100644 (file)
index 0000000..cab233a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Thrown when codec was used with data which are not modeled
+ * and available in schema used by codec.
+ *
+ */
+public class MissingSchemaException extends IllegalArgumentException {
+
+    private static final long serialVersionUID = 1L;
+
+    protected MissingSchemaException(final String msg) {
+        super(msg);
+    }
+
+    protected MissingSchemaException(final String msg, final Throwable cause) {
+        super(msg, cause);
+    }
+
+    private static MissingSchemaException create(final String format, final Object... args) {
+        return new MissingSchemaException(String.format(format, args));
+    }
+
+    static void checkModulePresent(final SchemaContext schemaContext, final QName name) {
+        if(schemaContext.findModuleByNamespaceAndRevision(name.getNamespace(), name.getRevision()) == null) {
+            throw MissingSchemaException.create("Module %s is not present in current schema context.",name.getModule());
+        }
+    }
+
+    static void checkModulePresent(final SchemaContext schemaContext, final YangInstanceIdentifier.PathArgument child) {
+        checkModulePresent(schemaContext, extractName(child));
+    }
+
+    private static QName extractName(final PathArgument child) {
+        if(child instanceof YangInstanceIdentifier.AugmentationIdentifier) {
+            final Set<QName> children = ((YangInstanceIdentifier.AugmentationIdentifier) child).getPossibleChildNames();
+            Preconditions.checkArgument(!children.isEmpty(),"Augmentation without childs must not be used in data");
+            return children.iterator().next();
+        }
+        return child.getNodeType();
+    }
+
+
+
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaForClassException.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/MissingSchemaForClassException.java
new file mode 100644 (file)
index 0000000..6f9778f
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+/**
+ *
+ * Thrown when Java Binding class was used in data for which codec does not
+ * have schema.
+ *
+ * By serialization /  deserialization of this exception {@link #getBindingClass()}
+ * will return null.
+ *
+ */
+public class MissingSchemaForClassException extends MissingSchemaException {
+
+    private static final long serialVersionUID = 1L;
+
+    private final transient Class<?> bindingClass;
+
+    private MissingSchemaForClassException(final Class<?> clz) {
+        super(String.format("Schema is not available for %s", clz));
+        this.bindingClass = Preconditions.checkNotNull(clz);
+    }
+
+    static MissingSchemaForClassException forClass(final Class<?> clz) {
+        return new MissingSchemaForClassException(clz);
+    }
+
+    public Class<?> getBindingClass() {
+        return bindingClass;
+    }
+
+    public static void check(final BindingRuntimeContext runtimeContext, final Class<?> bindingClass) {
+        final Object schema;
+        if (Augmentation.class.isAssignableFrom(bindingClass)) {
+            schema = runtimeContext.getAugmentationDefinition(bindingClass);
+        } else {
+            schema = runtimeContext.getSchemaDefinition(bindingClass);
+        }
+        if(schema == null) {
+            throw MissingSchemaForClassException.forClass(bindingClass);
+        }
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NodeCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NodeCodecContext.java
new file mode 100644 (file)
index 0000000..028801b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.List;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeNode;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+
+/**
+ *
+ * Location specific context for schema nodes, which contains codec specific
+ * information to properly serialize / deserialize from Java YANG Binding data
+ * to NormalizedNode data.
+ *
+ * Two core subtypes of codec context are available:
+ * <ul>
+ * <li>{@link LeafNodeCodecContext} - Context for nodes, which does not contain
+ * any nested YANG modeled substructures.</li>
+ * <li>{@link DataObjectCodecContext} - Context for nodes, which does contain
+ * nested YANG modeled substructures. This context nodes contains context
+ * for children nodes.</li>
+ * </ul>
+ *
+ */
+abstract class NodeCodecContext<D extends DataObject> implements BindingCodecTreeNode<D> {
+
+    /**
+     * Returns Yang Instance Identifier Path Argument of current node
+     *
+     * @return DOM Path Argument of node
+     */
+    protected abstract YangInstanceIdentifier.PathArgument getDomPathArgument();
+
+    /**
+     *
+     * Immutable factory, which provides access to runtime context,
+     * create leaf nodes and provides path argument codecs.
+     * <p>
+     * During lifetime of factory all calls for same arguments to method must return
+     * equal result (not necessary same instance of result).
+     *
+     */
+    protected interface CodecContextFactory {
+        /**
+         * Returns immutable runtime context associated with this factory.
+         * @return runtime context
+         */
+        BindingRuntimeContext getRuntimeContext();
+
+        /**
+         * Returns leaf nodes for supplied data container and parent class.
+         *
+         * @param type Binding type for which leaves should be loaded.
+         * @param schema  Instantiated schema of binding type.
+         * @return Map of local name to leaf node context.
+         */
+        ImmutableMap<String, LeafNodeCodecContext<?>> getLeafNodes(Class<?> type, DataNodeContainer schema);
+
+        /**
+         * Returns Path argument codec for list item
+         *
+         * @param type Type of list item
+         * @param schema Schema of list item
+         * @return Path argument codec for supplied list item.
+         */
+        Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> getPathArgumentCodec(Class<?> type,
+                ListSchemaNode schema);
+
+        DataObjectSerializer getEventStreamSerializer(Class<?> type);
+    }
+
+    /**
+     *
+     * Serializes supplied Binding Path Argument
+     * and adds all necessary YANG instance identifiers to supplied list.
+     *
+     * @param arg Binding Path Argument
+     * @param builder DOM Path argument.
+     */
+    protected void addYangPathArgument(final InstanceIdentifier.PathArgument arg,
+            final List<YangInstanceIdentifier.PathArgument> builder) {
+        if (builder != null) {
+            builder.add(getDomPathArgument());
+        }
+    }
+
+    protected abstract Object deserializeObject(NormalizedNode<?, ?> normalizedNode);
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NodeContextSupplier.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NodeContextSupplier.java
new file mode 100644 (file)
index 0000000..c659990
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Supplier;
+import javax.annotation.Nonnull;
+
+/**
+ * Type capture of an entity producing NodeCodecContexts.
+ */
+interface NodeContextSupplier extends Supplier<NodeCodecContext<?>> {
+    @Override
+    @Nonnull NodeCodecContext<?> get();
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NonCachingCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NonCachingCodec.java
new file mode 100644 (file)
index 0000000..4216f58
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCodec;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+class NonCachingCodec<D extends DataObject> implements BindingNormalizedNodeCachingCodec<D> {
+
+    private final BindingNormalizedNodeCodec<D> delegate;
+
+    protected NonCachingCodec(final BindingNormalizedNodeCodec<D> delegate) {
+        this.delegate = delegate;
+    }
+
+    @Override
+    public D deserialize(final NormalizedNode<?, ?> data) {
+        return delegate.deserialize(data);
+    }
+
+    @Override
+    public NormalizedNode<?, ?> serialize(final D data) {
+        return delegate.serialize(data);
+    }
+
+    @Override
+    public void close() {
+        // NOOP
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NormalizedNodeWriterWithAddChild.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NormalizedNodeWriterWithAddChild.java
new file mode 100644 (file)
index 0000000..57f9bcf
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+
+final class NormalizedNodeWriterWithAddChild extends ImmutableNormalizedNodeStreamWriter {
+
+    NormalizedNodeWriterWithAddChild(final NormalizedNodeResult result) {
+        super(result);
+    }
+
+    void addChild(final NormalizedNode<?, ?> child) {
+        this.writeChild(child);
+    }
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NotificationCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/NotificationCodecContext.java
new file mode 100644 (file)
index 0000000..25433b8
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+
+final class NotificationCodecContext<D extends DataObject & Notification> extends DataObjectCodecContext<D,NotificationDefinition> {
+
+    public NotificationCodecContext(final Class<?> key, final NotificationDefinition schema, final CodecContextFactory factory) {
+        super(DataContainerCodecPrototype.from(key, schema, factory));
+    }
+
+    @Override
+    public D deserialize(final NormalizedNode<?, ?> data) {
+        Preconditions.checkState(data instanceof ContainerNode);
+        return createBindingProxy((NormalizedNodeContainer<?, ?, ?>) data);
+    }
+
+    @Override
+    protected Object deserializeObject(NormalizedNode<?, ?> normalizedNode) {
+        return deserialize(normalizedNode);
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ReflectionBasedCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ReflectionBasedCodec.java
new file mode 100644 (file)
index 0000000..fa3aa50
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.binding.data.codec.impl;
+
+abstract class ReflectionBasedCodec extends ValueTypeCodec {
+
+    protected final Class<?> typeClass;
+
+    public ReflectionBasedCodec(final Class<?> typeClass) {
+        super();
+        this.typeClass = typeClass;
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/SchemaRootCodecContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/SchemaRootCodecContext.java
new file mode 100644 (file)
index 0000000..16533f0
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.util.concurrent.UncheckedExecutionException;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+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.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
+
+final class SchemaRootCodecContext<D extends DataObject> extends DataContainerCodecContext<D,SchemaContext> {
+
+    private final LoadingCache<Class<?>, DataContainerCodecContext<?,?>> childrenByClass = CacheBuilder.newBuilder()
+            .build(new CacheLoader<Class<?>, DataContainerCodecContext<?,?>>() {
+                @Override
+                public DataContainerCodecContext<?,?> load(final Class<?> key) {
+                    return createDataTreeChildContext(key);
+                }
+
+            });
+
+    private final LoadingCache<Class<?>, ContainerNodeCodecContext<?>> rpcDataByClass = CacheBuilder.newBuilder().build(
+            new CacheLoader<Class<?>, ContainerNodeCodecContext<?>>() {
+                @Override
+                public ContainerNodeCodecContext<?> load(final Class<?> key) {
+                    return createRpcDataContext(key);
+                }
+            });
+
+    private final LoadingCache<Class<?>, NotificationCodecContext<?>> notificationsByClass = CacheBuilder.newBuilder()
+            .build(new CacheLoader<Class<?>, NotificationCodecContext<?>>() {
+                @Override
+                public NotificationCodecContext<?> load(final Class<?> key) {
+                    return createNotificationDataContext(key);
+                }
+            });
+
+    private final LoadingCache<QName, DataContainerCodecContext<?,?>> childrenByQName = CacheBuilder.newBuilder().build(
+            new CacheLoader<QName, DataContainerCodecContext<?,?>>() {
+                @SuppressWarnings("unchecked")
+                @Override
+                public DataContainerCodecContext<?,?> load(final QName qname) {
+                    final DataSchemaNode childSchema = schema().getDataChildByName(qname);
+                    childNonNull(childSchema, qname,"Argument %s is not valid child of %s", qname,schema());
+                    if (childSchema instanceof DataNodeContainer || childSchema instanceof ChoiceSchemaNode) {
+                        @SuppressWarnings("rawtypes")
+                        final Class childCls = factory().getRuntimeContext().getClassForSchema(childSchema);
+                        return streamChild(childCls);
+                    } else {
+                        throw new UnsupportedOperationException("Unsupported child type " + childSchema.getClass());
+                    }
+                }
+            });
+
+    private final LoadingCache<SchemaPath, ContainerNodeCodecContext<?>> rpcDataByPath = CacheBuilder.newBuilder().build(
+            new CacheLoader<SchemaPath, ContainerNodeCodecContext<?>>() {
+
+                @SuppressWarnings({ "rawtypes", "unchecked" })
+                @Override
+                public ContainerNodeCodecContext load(final SchemaPath key) {
+                    final ContainerSchemaNode schema = SchemaContextUtil.getRpcDataSchema(schema(), key);
+                    final Class cls = factory().getRuntimeContext().getClassForSchema(schema);
+                    return getRpc(cls);
+                }
+            });
+
+    private final LoadingCache<SchemaPath, NotificationCodecContext<?>> notificationsByPath = CacheBuilder.newBuilder()
+            .build(new CacheLoader<SchemaPath, NotificationCodecContext<?>>() {
+
+                @SuppressWarnings({ "rawtypes", "unchecked" })
+                @Override
+                public NotificationCodecContext load(final SchemaPath key) throws Exception {
+                    final NotificationDefinition schema = SchemaContextUtil.getNotificationSchema(schema(), key);
+                    final Class clz = factory().getRuntimeContext().getClassForSchema(schema);
+                    return getNotification(clz);
+                }
+            });
+
+    private SchemaRootCodecContext(final DataContainerCodecPrototype<SchemaContext> dataPrototype) {
+        super(dataPrototype);
+    }
+
+    /**
+     * Creates RootNode from supplied CodecContextFactory.
+     *
+     * @param factory
+     *            CodecContextFactory
+     * @return
+     */
+    static SchemaRootCodecContext<?> create(final CodecContextFactory factory) {
+        final DataContainerCodecPrototype<SchemaContext> prototype = DataContainerCodecPrototype.rootPrototype(factory);
+        return new SchemaRootCodecContext<>(prototype);
+    }
+
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <DV extends DataObject> DataContainerCodecContext<DV, ?> streamChild(final Class<DV> childClass)
+            throws IllegalArgumentException {
+        /* FIXME: This is still not solved for RPCs
+         * TODO: Probably performance wise RPC, Data and Notification loading cache
+         *       should be merge for performance resons. Needs microbenchmark to
+         *       determine which is faster (keeping them separate or in same cache).
+         */
+        if (Notification.class.isAssignableFrom(childClass)) {
+            return (DataContainerCodecContext<DV, ?>) getNotification((Class<? extends Notification>)childClass);
+        }
+        return (DataContainerCodecContext<DV, ?>) getOrRethrow(childrenByClass,childClass);
+    }
+
+    @Override
+    public <E extends DataObject> Optional<DataContainerCodecContext<E,?>> possibleStreamChild(final Class<E> childClass) {
+        throw new UnsupportedOperationException("Not supported");
+    }
+
+    @Override
+    public DataContainerCodecContext<?,?> yangPathArgumentChild(final PathArgument arg) {
+        return getOrRethrow(childrenByQName,arg.getNodeType());
+    }
+
+    @Override
+    public D deserialize(final NormalizedNode<?, ?> normalizedNode) {
+        throw new UnsupportedOperationException(
+                "Could not create Binding data representation for root");
+    }
+
+
+    ContainerNodeCodecContext<?> getRpc(final Class<? extends DataContainer> rpcInputOrOutput) {
+        return getOrRethrow(rpcDataByClass, rpcInputOrOutput);
+    }
+
+    NotificationCodecContext<?> getNotification(final Class<? extends Notification> notification) {
+        return getOrRethrow(notificationsByClass, notification);
+    }
+
+    NotificationCodecContext<?> getNotification(final SchemaPath notification) {
+        return getOrRethrow(notificationsByPath, notification);
+    }
+
+    ContainerNodeCodecContext<?> getRpc(final SchemaPath notification) {
+        return getOrRethrow(rpcDataByPath, notification);
+    }
+
+    private DataContainerCodecContext<?,?> createDataTreeChildContext(final Class<?> key) {
+        final Class<Object> parent = ClassLoaderUtils.findFirstGenericArgument(key, ChildOf.class);
+        IncorrectNestingException.check(DataRoot.class.isAssignableFrom(parent), "Class %s is not top level item.", key);
+        final QName qname = BindingReflections.findQName(key);
+        final DataSchemaNode childSchema = childNonNull(schema().getDataChildByName(qname),key,"%s is not top-level item.",key);
+        return DataContainerCodecPrototype.from(key, childSchema, factory()).get();
+    }
+
+    private ContainerNodeCodecContext<?> createRpcDataContext(final Class<?> key) {
+        Preconditions.checkArgument(DataContainer.class.isAssignableFrom(key));
+        final QName qname = BindingReflections.findQName(key);
+        final QNameModule module = qname.getModule();
+        RpcDefinition rpc = null;
+        for (final RpcDefinition potential : schema().getOperations()) {
+            final QName potentialQName = potential.getQName();
+            /*
+             *
+             * Check if rpc and class represents data from same module and then
+             * checks if rpc local name produces same class name as class name
+             * appended with Input/Output based on QName associated with bidning
+             * class.
+             *
+             * FIXME: Rework this to have more precise logic regarding Binding
+             * Specification.
+             */
+            if (module.equals(potentialQName.getModule())
+                    && key.getSimpleName().equals(
+                            BindingMapping.getClassName(potentialQName) + BindingMapping.getClassName(qname))) {
+                rpc = potential;
+                break;
+            }
+        }
+        Preconditions.checkArgument(rpc != null, "Supplied class %s is not valid RPC class.", key);
+        final ContainerSchemaNode schema = SchemaNodeUtils.getRpcDataSchema(rpc, qname);
+        Preconditions.checkArgument(schema != null, "Schema for %s does not define input / output.", rpc.getQName());
+        return (ContainerNodeCodecContext<?>) DataContainerCodecPrototype.from(key, schema, factory()).get();
+    }
+
+    private NotificationCodecContext<?> createNotificationDataContext(final Class<?> notificationType) {
+        Preconditions.checkArgument(Notification.class.isAssignableFrom(notificationType));
+        Preconditions.checkArgument(notificationType.isInterface(), "Supplied class must be interface.");
+        final QName qname = BindingReflections.findQName(notificationType);
+        /**
+         *  FIXME: After Lithium cleanup of yang-model-api, use direct call on schema context
+         *  to retrieve notification via index.
+         */
+        final NotificationDefinition schema = SchemaContextUtil.getNotificationSchema(schema(),
+                SchemaPath.create(true, qname));
+        Preconditions.checkArgument(schema != null, "Supplied %s is not valid notification", notificationType);
+
+        return new NotificationCodecContext<>(notificationType, schema, factory());
+    }
+
+    @Override
+    protected Object deserializeObject(final NormalizedNode<?, ?> normalizedNode) {
+        throw new UnsupportedOperationException("Unable to deserialize root");
+    }
+
+    @Override
+    public InstanceIdentifier.PathArgument deserializePathArgument(final YangInstanceIdentifier.PathArgument arg) {
+        Preconditions.checkArgument(arg == null);
+        return null;
+    }
+
+    @Override
+    public YangInstanceIdentifier.PathArgument serializePathArgument(final InstanceIdentifier.PathArgument arg) {
+        Preconditions.checkArgument(arg == null);
+        return null;
+    }
+
+    private static <K,V> V getOrRethrow(final LoadingCache<K, V> cache, final K key) {
+        try {
+            return cache.getUnchecked(key);
+        } catch (final UncheckedExecutionException e) {
+            final Throwable cause = e.getCause();
+            if(cause != null) {
+                Throwables.propagateIfPossible(cause);
+            }
+            throw e;
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/UnionTypeCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/UnionTypeCodec.java
new file mode 100644 (file)
index 0000000..00702f0
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.collect.ImmutableSet;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.UnionType;
+
+final class UnionTypeCodec extends ReflectionBasedCodec {
+
+    private final ImmutableSet<UnionValueOptionContext> typeCodecs;
+    private final Constructor<?> charConstructor;
+
+    private UnionTypeCodec(final Class<?> unionCls,final Set<UnionValueOptionContext> codecs) {
+        super(unionCls);
+        try {
+            charConstructor = unionCls.getConstructor(char[].class);
+            typeCodecs = ImmutableSet.copyOf(codecs);
+        } catch (NoSuchMethodException | SecurityException e) {
+           throw new IllegalStateException("Required constructor is not available.",e);
+        }
+    }
+
+    static Callable<UnionTypeCodec> loader(final Class<?> unionCls, final UnionTypeDefinition unionType) {
+        return new Callable<UnionTypeCodec>() {
+            @Override
+            public UnionTypeCodec call() throws NoSuchMethodException, SecurityException {
+                Set<UnionValueOptionContext> values = new HashSet<>();
+                for(TypeDefinition<?> subtype : unionType.getTypes()) {
+                    String methodName = "get" + BindingMapping.getClassName(subtype.getQName());
+                    Method valueGetter = unionCls.getMethod(methodName);
+                    Class<?> valueType = valueGetter.getReturnType();
+                    Codec<Object, Object> valueCodec = UnionTypeCodec.getCodecForType(valueType, subtype);
+                    values.add(new UnionValueOptionContext(valueType,valueGetter, valueCodec));
+                }
+                return new UnionTypeCodec(unionCls, values);
+            }
+        };
+    }
+
+    private static Codec<Object, Object> getCodecForType(final Class<?> valueType, final TypeDefinition<?> subtype) {
+        if (subtype.getBaseType() instanceof UnionType) {
+            try {
+                return UnionTypeCodec.loader(valueType, (UnionType) subtype.getBaseType()).call();
+            } catch (final Exception e) {
+                throw new IllegalStateException("Could not construct Union Type Codec");
+            }
+        } else {
+            return ValueTypeCodec.getCodecFor(valueType, subtype);
+        }
+    }
+
+    @Override
+    public Object deserialize(final Object input) {
+        try {
+            return charConstructor.newInstance((input.toString().toCharArray()));
+        } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+            throw new IllegalStateException("Could not construct instance",e);
+        }
+    }
+
+    @Override
+    public Object serialize(final Object input) {
+        if (input != null) {
+            for (UnionValueOptionContext valCtx : typeCodecs) {
+                Object domValue = valCtx.serialize(input);
+                if (domValue != null) {
+                    return domValue;
+                }
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/UnionValueOptionContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/UnionValueOptionContext.java
new file mode 100644 (file)
index 0000000..7c4c144
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+import org.opendaylight.yangtools.concepts.Codec;
+
+final class UnionValueOptionContext {
+    private static final Lookup LOOKUP = MethodHandles.publicLookup();
+    private static final MethodType OBJECT_TYPE = MethodType.methodType(Object.class, Object.class);
+    private final Class<?> bindingType;
+    // FIXME: migrate to invocation
+    private final MethodHandle getter;
+    private final Codec<Object,Object> codec;
+
+    UnionValueOptionContext(final Class<?> valueType, final Method getter, final Codec<Object, Object> codec) {
+        this.bindingType = Preconditions.checkNotNull(valueType);
+        this.codec = Preconditions.checkNotNull(codec);
+
+        try {
+            this.getter = LOOKUP.unreflect(getter).asType(OBJECT_TYPE);
+        } catch (IllegalAccessException e) {
+            throw new IllegalStateException("Failed to access method " + getter, e);
+        }
+    }
+
+    Object serialize(final Object input) {
+        final Object baValue = getValueFrom(input);
+        if (baValue == null) {
+            return null;
+        }
+
+        return codec.serialize(baValue);
+    }
+
+    Object getValueFrom(final Object input) {
+        try {
+            return getter.invokeExact(input);
+        } catch (Throwable e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        return bindingType.hashCode();
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof UnionValueOptionContext)) {
+            return false;
+        }
+
+        final UnionValueOptionContext other = (UnionValueOptionContext) obj;
+        return bindingType.equals(other.bindingType);
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ValueContext.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ValueContext.java
new file mode 100644 (file)
index 0000000..e44ae31
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+
+final class ValueContext {
+    private static final Lookup LOOKUP = MethodHandles.publicLookup();
+    private static final MethodType OBJECT_METHOD = MethodType.methodType(Object.class, Object.class);
+    private final Codec<Object, Object> codec;
+    private final MethodHandle getter;
+    private final Class<?> identifier;
+    private final String getterName;
+
+    ValueContext(final Class<?> identifier, final LeafNodeCodecContext <?>leaf) {
+        getterName = BindingCodecContext.GETTER_PREFIX + BindingMapping.getClassName(leaf.getDomPathArgument().getNodeType());
+        try {
+            getter = LOOKUP.unreflect(identifier.getMethod(getterName)).asType(OBJECT_METHOD);
+        } catch (IllegalAccessException | NoSuchMethodException | SecurityException e) {
+            throw new IllegalStateException(String.format("Cannot find method %s in class %s", getterName, identifier), e);
+        }
+        this.identifier = identifier;
+        codec = leaf.getValueCodec();
+    }
+
+    Object getAndSerialize(final Object obj) {
+        final Object value;
+        try {
+            value = getter.invokeExact(obj);
+        } catch (Throwable e) {
+            throw Throwables.propagate(e);
+        }
+
+        Preconditions.checkArgument(value != null,
+                "All keys must be specified for %s. Missing key is %s. Supplied key is %s",
+                identifier, getterName, obj);
+        return codec.serialize(value);
+    }
+
+    Object deserialize(final Object obj) {
+        return codec.deserialize(obj);
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ValueTypeCodec.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ValueTypeCodec.java
new file mode 100644 (file)
index 0000000..d69970b
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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.binding.data.codec.impl;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import org.opendaylight.yangtools.concepts.Codec;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+
+/**
+ * Value codec, which serializes / deserializes values from DOM simple values.
+ *
+ */
+abstract class ValueTypeCodec implements Codec<Object, Object> {
+
+    private static final Cache<Class<?>, SchemaUnawareCodec> staticCodecs = CacheBuilder.newBuilder().weakKeys()
+            .build();
+
+
+    /**
+     * Marker interface for codecs, which functionality will not be
+     * affected by schema change (introduction of new YANG modules)
+     * they may have one static instance generated when
+     * first time needed.
+     *
+     */
+    interface SchemaUnawareCodec extends Codec<Object,Object> {
+
+    }
+
+
+    /**
+     *
+     * No-op Codec, Java YANG Binding uses same types as NormalizedNode model
+     * for base YANG types, representing numbers, binary and strings.
+     *
+     *
+     */
+    public static final SchemaUnawareCodec NOOP_CODEC = new SchemaUnawareCodec() {
+
+        @Override
+        public Object serialize(final Object input) {
+            return input;
+        }
+
+        @Override
+        public Object deserialize(final Object input) {
+            return input;
+        }
+    };
+
+    public static final SchemaUnawareCodec EMPTY_CODEC = new SchemaUnawareCodec() {
+
+        @Override
+        public Object serialize(final Object arg0) {
+            // Empty type has null value in NormalizedNode and Composite Node
+            // representation
+            return null;
+        }
+
+        @Override
+        public Object deserialize(final Object arg0) {
+            /* Empty type has boolean.TRUE representation in Binding-aware world
+            *  otherwise it is null / false.
+            *  So when codec is triggered, empty leaf is present, that means we
+            *  are safe to return true.
+            */
+            return Boolean.TRUE;
+        }
+    };
+
+    private static final Callable<? extends SchemaUnawareCodec> EMPTY_LOADER = new Callable<SchemaUnawareCodec>() {
+
+        @Override
+        public SchemaUnawareCodec call() {
+            return EMPTY_CODEC;
+        }
+    };
+
+
+    public static SchemaUnawareCodec getCodecFor(final Class<?> typeClz, final TypeDefinition<?> def) {
+        if (BindingReflections.isBindingClass(typeClz)) {
+            return getCachedSchemaUnawareCodec(typeClz, getCodecLoader(typeClz, def));
+        }
+        TypeDefinition<?> rootType = def;
+        while (rootType.getBaseType() != null) {
+            rootType = rootType.getBaseType();
+        }
+        if (rootType instanceof EmptyTypeDefinition) {
+            return EMPTY_CODEC;
+        }
+        return NOOP_CODEC;
+    }
+
+    private static SchemaUnawareCodec getCachedSchemaUnawareCodec(final Class<?> typeClz, final Callable<? extends SchemaUnawareCodec> loader) {
+        try {
+            return staticCodecs.get(typeClz, loader);
+        } catch (ExecutionException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    private static Callable<? extends SchemaUnawareCodec> getCodecLoader(final Class<?> typeClz, final TypeDefinition<?> def) {
+
+        TypeDefinition<?> rootType = def;
+        while (rootType.getBaseType() != null) {
+            rootType = rootType.getBaseType();
+        }
+        if (rootType instanceof EnumTypeDefinition) {
+            return EnumerationCodec.loader(typeClz, (EnumTypeDefinition) rootType);
+        } else if (rootType instanceof BitsTypeDefinition) {
+            return BitsCodec.loader(typeClz, (BitsTypeDefinition) rootType);
+        } else if (rootType instanceof EmptyTypeDefinition) {
+            return EMPTY_LOADER;
+        }
+        return EncapsulatedValueCodec.loader(typeClz);
+    }
+
+    @SuppressWarnings("rawtypes")
+    static ValueTypeCodec encapsulatedValueCodecFor(final Class<?> typeClz, final Codec delegate) {
+        SchemaUnawareCodec extractor = getCachedSchemaUnawareCodec(typeClz, EncapsulatedValueCodec.loader(typeClz));
+        return new CompositeValueCodec(extractor, delegate);
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/util/AugmentableDispatchSerializer.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/util/AugmentableDispatchSerializer.java
new file mode 100644 (file)
index 0000000..b0860eb
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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.binding.data.codec.util;
+
+import com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ *
+ * Dispatch serializer, which emits {@link BindingStreamEventWriter#startAugmentationNode(Class)}
+ * events for supplied augmentation node.
+ *
+ */
+public class AugmentableDispatchSerializer implements DataObjectSerializerImplementation {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AugmentableDispatchSerializer.class);
+
+    @Override
+    public void serialize(final DataObjectSerializerRegistry reg, final DataObject obj,
+            final BindingStreamEventWriter stream) throws IOException {
+        if (obj instanceof Augmentable<?>) {
+            final Map<Class<? extends Augmentation<?>>, Augmentation<?>> augmentations;
+            if (reg instanceof AugmentationReader) {
+                augmentations = ((AugmentationReader) reg).getAugmentations(obj);
+            } else if (Proxy.isProxyClass(obj.getClass())) {
+                augmentations = getFromProxy(obj);
+            } else {
+                augmentations = BindingReflections.getAugmentations((Augmentable<?>) obj);
+            }
+            for (final Entry<Class<? extends Augmentation<?>>, Augmentation<?>> aug : augmentations.entrySet()) {
+                emitAugmentation(aug.getKey(), aug.getValue(), stream, reg);
+            }
+        }
+    }
+
+    private Map<Class<? extends Augmentation<?>>, Augmentation<?>> getFromProxy(final DataObject obj) {
+        final InvocationHandler proxy = Proxy.getInvocationHandler(obj);
+        if (proxy instanceof AugmentationReader) {
+            return ((AugmentationReader) proxy).getAugmentations(obj);
+        }
+        return Collections.emptyMap();
+    }
+
+    @SuppressWarnings("rawtypes")
+    private void emitAugmentation(final Class type, final Augmentation<?> value, final BindingStreamEventWriter stream,
+            final DataObjectSerializerRegistry registry) throws IOException {
+        /*
+         * Binding Specification allowed to insert augmentation with null for
+         * value, which effectively could be used to remove augmentation
+         * from builder / DTO.
+         */
+        if(value == null) {
+            return;
+        }
+        Preconditions.checkArgument(value instanceof DataObject);
+        @SuppressWarnings("unchecked")
+        final DataObjectSerializer serializer = registry.getSerializer(type);
+        if (serializer != null) {
+            serializer.serialize((DataObject) value, stream);
+        } else {
+            LOG.warn("DataObjectSerializer is not present for {} in registry {}", type, registry);
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/util/AugmentationReader.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/util/AugmentationReader.java
new file mode 100644 (file)
index 0000000..e79e86e
--- /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.binding.data.codec.util;
+
+import java.util.Map;
+
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+/**
+ * Interface which sould be implemented by proxy {@link java.lang.reflect.InvocationHandler}
+ * to obtain augmentations from proxy implementations of {@link org.opendaylight.yangtools.yang.binding.Augmentable}
+ * object.
+ *
+ * If implemented proxy does not implement this interface, its augmentations are not
+ * properly serialized / deserialized.
+ */
+public interface AugmentationReader {
+
+    Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(Object obj);
+}
diff --git a/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/util/ChoiceDispatchSerializer.java b/code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/util/ChoiceDispatchSerializer.java
new file mode 100644 (file)
index 0000000..5671ed5
--- /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.binding.data.codec.util;
+
+import com.google.common.base.Preconditions;
+
+import java.io.IOException;
+
+import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializer;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
+import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ChoiceDispatchSerializer implements DataObjectSerializerImplementation {
+
+    private static final Logger LOG = LoggerFactory.getLogger(ChoiceDispatchSerializer.class);
+
+    @SuppressWarnings("rawtypes")
+    private final Class choiceClass;
+
+    @SuppressWarnings("rawtypes")
+    private ChoiceDispatchSerializer(final Class choiceClass) {
+        this.choiceClass = Preconditions.checkNotNull(choiceClass);
+    }
+
+    public static final ChoiceDispatchSerializer from(final Class<? extends DataContainer> choiceClass) {
+        return new ChoiceDispatchSerializer(choiceClass);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void serialize(final DataObjectSerializerRegistry reg, final DataObject obj, final BindingStreamEventWriter stream) throws IOException {
+        @SuppressWarnings("rawtypes")
+        Class cazeClass = obj.getImplementedInterface();
+        stream.startChoiceNode(choiceClass, BindingStreamEventWriter.UNKNOWN_SIZE);
+        DataObjectSerializer caseSerializer = reg.getSerializer(cazeClass);
+        if (caseSerializer != null) {
+            caseSerializer.serialize(obj, stream);
+        } else {
+            LOG.warn("No serializer for case {} is available in registry {}", cazeClass, reg);
+        }
+        stream.endNode();
+    }
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AbstractBindingRuntimeTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AbstractBindingRuntimeTest.java
new file mode 100644 (file)
index 0000000..a56364c
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.binding.data.codec.test;
+
+import org.junit.Before;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public abstract class AbstractBindingRuntimeTest {
+
+    private SchemaContext schemaContext;
+    private BindingRuntimeContext runtimeContext;
+
+    @Before
+    public void setup() {
+        ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create();
+        ctx.addModuleInfos(BindingReflections.loadModuleInfos());
+        schemaContext = ctx.tryToCreateSchemaContext().get();
+        runtimeContext = BindingRuntimeContext.create(ctx, schemaContext);
+
+    }
+
+    public SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
+
+    public BindingRuntimeContext getRuntimeContext() {
+        return runtimeContext;
+    }
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AugmentationClassDiscoveredAfterCodecTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AugmentationClassDiscoveredAfterCodecTest.java
new file mode 100644 (file)
index 0000000..f75be68
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.test;
+import static org.junit.Assert.assertNotNull;
+
+import com.google.common.base.Preconditions;
+import java.util.HashSet;
+import java.util.Map.Entry;
+import java.util.Set;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.binding.data.codec.impl.MissingClassInLoadingStrategyException;
+import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * This sets of tests are designed in way, that schema context contains models for all
+ * augmentations, but backing class loading strategy is not aware of some of the classes, and
+ * becames aware of them after codec was used.
+ *
+ * Idea of this suite is to test that codecs will work even if situation like this happens.
+ *
+ */
+public class AugmentationClassDiscoveredAfterCodecTest {
+
+    private SchemaContext schemaContext;
+    private BindingRuntimeContext runtimeContext;
+    private ClassExcludingClassLoadingStrategy mockedContext;
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Before
+    public void setup() {
+        final ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create();
+        ctx.addModuleInfos(BindingReflections.loadModuleInfos());
+        mockedContext = new ClassExcludingClassLoadingStrategy(ctx);
+        schemaContext = ctx.tryToCreateSchemaContext().get();
+        runtimeContext = BindingRuntimeContext.create(mockedContext, schemaContext);
+        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(runtimeContext);
+    }
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+            .augmentation(TreeLeafOnlyAugment.class);
+
+
+
+    @Test(expected = MissingClassInLoadingStrategyException.class)
+    public void testCorrectExceptionThrown() {
+        materializeWithExclusions(TreeLeafOnlyAugment.class, TreeComplexUsesAugment.class);
+        registry.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
+    }
+
+
+    @Test
+    public void testUsingBindingInstanceIdentifier() {
+        materializeWithExclusions(TreeLeafOnlyAugment.class, TreeComplexUsesAugment.class);
+        mockedContext.includeClass(TreeLeafOnlyAugment.class);
+        final YangInstanceIdentifier domYY = registry.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
+        assertNotNull(domYY);
+    }
+
+    @Test
+    public void testUsingBindingData() {
+        materializeWithExclusions(TreeLeafOnlyAugment.class, TreeComplexUsesAugment.class);
+        mockedContext.includeClass(TreeLeafOnlyAugment.class);
+        final TopLevelList data =
+                new TopLevelListBuilder()
+                        .setKey(TOP_FOO_KEY)
+                        .addAugmentation(TreeLeafOnlyAugment.class,
+                                new TreeLeafOnlyAugmentBuilder().setSimpleValue("foo").build()).build();
+        final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> domData =
+                registry.toNormalizedNode(BA_TOP_LEVEL_LIST, data);
+        assertNotNull(domData);
+    }
+
+
+    private void materializeWithExclusions(final Class<?>... clzToExclude) {
+        for (final Class<?> clz : clzToExclude) {
+            mockedContext.excludeClass(clz);
+        }
+        registry.toYangInstanceIdentifier(BA_TOP_LEVEL_LIST);
+    }
+
+    private static class ClassExcludingClassLoadingStrategy extends GeneratedClassLoadingStrategy {
+
+        private final Set<String> exclusions = new HashSet<>();
+        private final GeneratedClassLoadingStrategy delegate;
+
+        void excludeClass(final Class<?> clz) {
+            exclusions.add(clz.getName());
+        }
+
+        void includeClass(final Class<?> clz) {
+            exclusions.remove(clz.getName());
+        }
+
+        protected ClassExcludingClassLoadingStrategy(final GeneratedClassLoadingStrategy delegate) {
+            this.delegate = Preconditions.checkNotNull(delegate);
+        }
+
+        @Override
+        public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
+            if (exclusions.contains(fullyQualifiedName)) {
+                throw new ClassNotFoundException(String.format("Class %s is not available for test reasons.",
+                        fullyQualifiedName));
+            }
+            return delegate.loadClass(fullyQualifiedName);
+        }
+    };
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AugmentationSubstitutionTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/AugmentationSubstitutionTest.java
new file mode 100644 (file)
index 0000000..3200682
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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.binding.data.codec.test;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.base.Optional;
+import java.util.Collections;
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+
+public class AugmentationSubstitutionTest extends AbstractBindingRuntimeTest {
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+            .augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+            .augmentation(TreeComplexUsesAugment.class);
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void augmentationInGroupingSubstituted() {
+        final TopLevelList baRpc = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .addAugmentation(RpcComplexUsesAugment.class, new RpcComplexUsesAugmentBuilder(createComplexData()).build())
+            .build();
+        final TopLevelList baTree = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .addAugmentation(TreeComplexUsesAugment.class, new TreeComplexUsesAugmentBuilder(createComplexData()).build())
+            .build();
+        final NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baTree).getValue();
+        final NormalizedNode<?, ?> domRpcEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baRpc).getValue();
+        assertEquals(domTreeEntry, domRpcEntry);
+    }
+
+    @Test
+    public void copyBuilderWithAugmenationsTest() {
+        final TopLevelList manuallyConstructed = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .addAugmentation(TreeComplexUsesAugment.class, new TreeComplexUsesAugmentBuilder(createComplexData()).build())
+            .build();
+        final NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, manuallyConstructed).getValue();
+        final TopLevelList deserialized = registry.deserializeFunction(BA_TOP_LEVEL_LIST).apply(Optional.<NormalizedNode<?, ?>>of(domTreeEntry)).get();
+        assertEquals(manuallyConstructed, deserialized);
+        final TopLevelList copiedFromDeserialized = new TopLevelListBuilder(deserialized).build();
+        assertEquals(manuallyConstructed, copiedFromDeserialized);
+    }
+
+    private RpcComplexUsesAugment createComplexData() {
+        return new RpcComplexUsesAugmentBuilder()
+        .setContainerWithUses(new ContainerWithUsesBuilder()
+            .setLeafFromGrouping("foo")
+        .build())
+        .setListViaUses(Collections.<ListViaUses>emptyList())
+        .build();
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/CachingCodecTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/CachingCodecTest.java
new file mode 100644 (file)
index 0000000..735679a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import java.util.Collection;
+import java.util.List;
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingCodecTreeNode;
+import org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeCachingCodec;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
+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;
+
+public class CachingCodecTest extends AbstractBindingRuntimeTest {
+
+    private static final NodeIdentifier TOP_LEVEL_LIST_ARG = new NodeIdentifier(TopLevelList.QNAME);
+    private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
+    private static final List<TopLevelList> TWO_LIST = createList(2);
+    private static final List<TopLevelList> THREE_LIST = createList(3);
+
+    private static final Top TOP_TWO_LIST_DATA = new TopBuilder().setTopLevelList(TWO_LIST).build();
+    private static final Top TOP_THREE_LIST_DATA = new TopBuilder().setTopLevelList(THREE_LIST).build();
+
+    private BindingNormalizedNodeCodecRegistry registry;
+    private BindingCodecTreeNode<Top> topNode;
+
+    @Override
+    public void setup() {
+        super.setup();
+        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+        topNode = registry.getCodecContext().getSubtreeCodec(TOP_PATH);
+
+    }
+
+
+    private static List<TopLevelList> createList(final int num) {
+
+        final ImmutableList.Builder<TopLevelList> builder = ImmutableList.builder();
+        for (int i = 0; i < num; i++) {
+            final TopLevelListKey key = new TopLevelListKey("test-" + i);
+            builder.add(new TopLevelListBuilder().setKey(key).build());
+        }
+        return builder.build();
+    }
+
+    @Test
+    public void testListCache() {
+        final BindingNormalizedNodeCachingCodec<Top> cachingCodec = createCachingCodec(TopLevelList.class);
+        final NormalizedNode<?, ?> first = cachingCodec.serialize(TOP_TWO_LIST_DATA);
+        final NormalizedNode<?, ?> second = cachingCodec.serialize(TOP_TWO_LIST_DATA);
+
+        assertNotSame(first, second);
+        assertEquals(first, second);
+        verifyListItemSame(first, second);
+
+        final NormalizedNode<?, ?> third = cachingCodec.serialize(TOP_THREE_LIST_DATA);
+        verifyListItemSame(first, third);
+        verifyListItemSame(second, third);
+    }
+
+
+    @Test
+    public void testTopAndListCache() {
+        final BindingNormalizedNodeCachingCodec<Top> cachingCodec = createCachingCodec(Top.class, TopLevelList.class);
+        final NormalizedNode<?, ?> first = cachingCodec.serialize(TOP_TWO_LIST_DATA);
+        final NormalizedNode<?, ?> second = cachingCodec.serialize(TOP_TWO_LIST_DATA);
+
+        assertEquals(first, second);
+        assertSame(first, second);
+
+        final NormalizedNode<?, ?> third = cachingCodec.serialize(TOP_THREE_LIST_DATA);
+        verifyListItemSame(first, third);
+    }
+
+    @SafeVarargs
+    private final BindingNormalizedNodeCachingCodec<Top> createCachingCodec(
+            final Class<? extends DataObject>... classes) {
+        return topNode.createCachingCodec(ImmutableSet.<Class<? extends DataObject>>copyOf(classes));
+    }
+
+    private static void verifyListItemSame(final NormalizedNode<?, ?> firstTop, final NormalizedNode<?, ?> secondTop) {
+        final Collection<MapEntryNode> initialNodes = getListItems(firstTop).getValue();
+        final MapNode secondMap = getListItems(secondTop);
+
+        for (final MapEntryNode initial : initialNodes) {
+            final MapEntryNode second = secondMap.getChild(initial.getIdentifier()).get();
+            assertEquals(initial, second);
+            assertSame(initial, second);
+        }
+    }
+
+
+    private static MapNode getListItems(final NormalizedNode<?, ?> top) {
+        return ((MapNode) ((DataContainerNode<?>) top).getChild(TOP_LEVEL_LIST_ARG).get());
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/CaseSubstitutionTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/CaseSubstitutionTest.java
new file mode 100644 (file)
index 0000000..c90a5a8
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.put.top.input.top.level.list.choice.in.list.ComplexViaUsesWithDifferentNameBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.top.level.list.choice.in.list.ComplexViaUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class CaseSubstitutionTest extends AbstractBindingRuntimeTest {
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+            .augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+            .augmentation(TreeComplexUsesAugment.class);
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void choiceInGroupingSubstituted() {
+        TopLevelList baRpc = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .setChoiceInList(new ComplexViaUsesWithDifferentNameBuilder(createComplexData()).build())
+            .build();
+        TopLevelList baTree = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .setChoiceInList(new ComplexViaUsesBuilder(createComplexData()).build())
+            .build();
+        NormalizedNode<?, ?> domTreeEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baTree).getValue();
+        NormalizedNode<?, ?> domRpcEntry = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, baRpc).getValue();
+        assertEquals(domTreeEntry, domRpcEntry);
+    }
+
+    private RpcComplexUsesAugment createComplexData() {
+        return new RpcComplexUsesAugmentBuilder()
+        .setContainerWithUses(new ContainerWithUsesBuilder()
+            .setLeafFromGrouping("foo")
+        .build())
+        .setListViaUses(Collections.<ListViaUses>emptyList())
+        .build();
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/EmptyLeafTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/EmptyLeafTest.java
new file mode 100644 (file)
index 0000000..26d9bbb
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.binding.data.codec.test;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.RpcComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ContainerWithUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.top.level.list.choice.in.list.EmptyLeaf;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.top.level.list.choice.in.list.EmptyLeafBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.ChoiceInList;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+
+public class EmptyLeafTest extends AbstractBindingRuntimeTest {
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+            .augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+            .augmentation(TreeComplexUsesAugment.class);
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void testCaseWithEmptyLeafType() {
+        TopLevelList withEmptyCase = new TopLevelListBuilder()
+            .setKey(TOP_FOO_KEY)
+            .setChoiceInList(new EmptyLeafBuilder().setEmptyType(true).build())
+            .build();
+        Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> dom = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, withEmptyCase);
+        Entry<InstanceIdentifier<?>, DataObject> readed = registry.fromNormalizedNode(dom.getKey(),dom.getValue());
+        ChoiceInList list = ((TopLevelList) readed.getValue()).getChoiceInList();
+        assertTrue(list instanceof EmptyLeaf);
+        assertTrue(((EmptyLeaf) list).isEmptyType());
+    }
+
+    private RpcComplexUsesAugment createComplexData() {
+        return new RpcComplexUsesAugmentBuilder()
+        .setContainerWithUses(new ContainerWithUsesBuilder()
+            .setLeafFromGrouping("foo")
+        .build())
+        .setListViaUses(Collections.<ListViaUses>emptyList())
+        .build();
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/ExceptionReportingTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/ExceptionReportingTest.java
new file mode 100644 (file)
index 0000000..4a565ed
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.binding.data.codec.impl.IncorrectNestingException;
+import org.opendaylight.yangtools.binding.data.codec.impl.MissingSchemaException;
+import org.opendaylight.yangtools.binding.data.codec.impl.MissingSchemaForClassException;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+
+public class ExceptionReportingTest {
+
+
+    private static final BindingNormalizedNodeCodecRegistry EMPTY_SCHEMA_CODEC = codec();
+    private static final BindingNormalizedNodeCodecRegistry ONLY_TOP_CODEC = codec(Top.class);
+    private static final BindingNormalizedNodeCodecRegistry FULL_CODEC = codec(TreeComplexUsesAugment.class);
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+            .builder(Top.class).child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY =
+            BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+
+    private static final QName TOP_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "top");
+    private static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.builder().node(TOP_QNAME).build();
+    private static final YangInstanceIdentifier BI_TREE_LEAF_ONLY = FULL_CODEC.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
+
+
+    @Test(expected=MissingSchemaException.class)
+    public void testDOMTop() {
+        EMPTY_SCHEMA_CODEC.fromYangInstanceIdentifier(BI_TOP_PATH);
+    }
+
+    @Test(expected=MissingSchemaException.class)
+    public void testDOMAugment() {
+        EMPTY_SCHEMA_CODEC.fromYangInstanceIdentifier(BI_TREE_LEAF_ONLY);
+    }
+
+    @Test(expected=MissingSchemaForClassException.class)
+    public void testBindingTop() {
+        EMPTY_SCHEMA_CODEC.toYangInstanceIdentifier(BA_TOP_LEVEL_LIST);
+    }
+
+    @Test(expected=MissingSchemaForClassException.class)
+    public void testBindingAugment() {
+        ONLY_TOP_CODEC.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
+    }
+
+    @Test(expected=IncorrectNestingException.class)
+    public void testBindingSkippedRoot() {
+        FULL_CODEC.toYangInstanceIdentifier(InstanceIdentifier.create(TopLevelList.class));
+    }
+
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    @Test(expected=IncorrectNestingException.class)
+    public void testBindingIncorrectAugment() {
+        FULL_CODEC.toYangInstanceIdentifier(InstanceIdentifier.create(Top.class).augmentation((Class) TreeComplexUsesAugment.class));
+    }
+
+
+    private static BindingNormalizedNodeCodecRegistry codec(final Class<?>... classes ) {
+        final ModuleInfoBackedContext ctx = ModuleInfoBackedContext.create();
+        for(final Class<?> clazz : classes) {
+            YangModuleInfo modInfo;
+            try {
+                modInfo = BindingReflections.getModuleInfo(clazz);
+                ctx.registerModuleInfo(modInfo);
+            } catch (final Exception e) {
+                throw new IllegalStateException(e);
+            }
+        }
+        final SchemaContext schema = ctx.tryToCreateSchemaContext().get();
+        final BindingRuntimeContext runtimeCtx = BindingRuntimeContext.create(ctx, schema);
+        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        final BindingNormalizedNodeCodecRegistry registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(runtimeCtx);
+        return registry;
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierSerializeDeserializeTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierSerializeDeserializeTest.java
new file mode 100644 (file)
index 0000000..dd0e316
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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.binding.data.codec.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import com.google.common.collect.Iterables;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+public class InstanceIdentifierSerializeDeserializeTest extends AbstractBindingRuntimeTest{
+    public static final String TOP_LEVEL_LIST_KEY_VALUE = "foo";
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+            .builder(Top.class).child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY =
+            BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES =
+            BA_TOP_LEVEL_LIST.augmentation(TreeComplexUsesAugment.class);
+
+    public static final QName TOP_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "top");
+    public static final QName TOP_LEVEL_LIST_QNAME = QName.create(TOP_QNAME, "top-level-list");
+    public static final QName TOP_LEVEL_LIST_KEY = QName.create(TOP_QNAME, "name");
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    public static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.builder().node(TOP_QNAME).build();
+    public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_PATH = BI_TOP_PATH.node(TOP_LEVEL_LIST_QNAME);
+    public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_1_PATH = BI_TOP_LEVEL_LIST_PATH
+            .node(new YangInstanceIdentifier.NodeIdentifierWithPredicates(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY, TOP_LEVEL_LIST_KEY_VALUE));
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    @Before
+    public void setup() {
+        super.setup();
+        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void testYangIIToBindingAwareII() {
+        final InstanceIdentifier<?> instanceIdentifier = registry.fromYangInstanceIdentifier(BI_TOP_PATH);
+        assertEquals(Top.class, instanceIdentifier.getTargetType());
+    }
+
+    @Test
+    public void testYangIIToBindingAwareIIListWildcarded() {
+        final InstanceIdentifier<?> instanceIdentifier = registry.fromYangInstanceIdentifier(BI_TOP_LEVEL_LIST_PATH);
+        assertNull(instanceIdentifier);
+    }
+
+    @Test
+    public void testYangIIToBindingAwareIIListWithKey() {
+        final InstanceIdentifier<?> instanceIdentifier = registry.fromYangInstanceIdentifier(BI_TOP_LEVEL_LIST_1_PATH);
+        final InstanceIdentifier.PathArgument last = Iterables.getLast(instanceIdentifier.getPathArguments());
+        assertEquals(TopLevelList.class, instanceIdentifier.getTargetType());
+        assertFalse(instanceIdentifier.isWildcarded());
+        assertTrue(last instanceof InstanceIdentifier.IdentifiableItem);
+        final Identifier<?> key = ((InstanceIdentifier.IdentifiableItem<?, ?>) last).getKey();
+        assertEquals(TopLevelListKey.class, key.getClass());
+        assertEquals(TOP_LEVEL_LIST_KEY_VALUE, ((TopLevelListKey)key).getName());
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIContainer() {
+        final YangInstanceIdentifier yangInstanceIdentifier = registry.toYangInstanceIdentifier(
+                InstanceIdentifier.create(Top.class).child(TopLevelList.class));
+        final YangInstanceIdentifier.PathArgument lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
+        assertTrue(lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifier);
+        assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIIWildcard() {
+        final YangInstanceIdentifier yangInstanceIdentifier = registry.toYangInstanceIdentifier(
+                InstanceIdentifier.create(Top.class).child(TopLevelList.class));
+        final YangInstanceIdentifier.PathArgument lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
+        assertTrue(lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifier);
+        assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIIListWithKey() {
+        final YangInstanceIdentifier yangInstanceIdentifier = registry.toYangInstanceIdentifier(
+                InstanceIdentifier.create(Top.class).child(TopLevelList.class, TOP_FOO_KEY));
+        final YangInstanceIdentifier.PathArgument lastPathArgument = yangInstanceIdentifier.getLastPathArgument();
+        assertTrue(lastPathArgument instanceof YangInstanceIdentifier.NodeIdentifierWithPredicates);
+        assertTrue(((YangInstanceIdentifier.NodeIdentifierWithPredicates) lastPathArgument).getKeyValues().containsValue(TOP_LEVEL_LIST_KEY_VALUE));
+        assertEquals(TopLevelList.QNAME, lastPathArgument.getNodeType());
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIIAugmentation() {
+        final YangInstanceIdentifier.PathArgument lastArg = registry.toYangInstanceIdentifier(BA_TREE_COMPLEX_USES).getLastPathArgument();
+        assertTrue(lastArg instanceof YangInstanceIdentifier.AugmentationIdentifier);
+    }
+
+    @Test
+    public void testBindingAwareIIToYangIILeafOnlyAugmentation() {
+        final YangInstanceIdentifier.PathArgument leafOnlyLastArg = registry.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY).getLastPathArgument();
+        assertTrue(leafOnlyLastArg instanceof YangInstanceIdentifier.AugmentationIdentifier);
+        assertTrue(((YangInstanceIdentifier.AugmentationIdentifier) leafOnlyLastArg).getPossibleChildNames().contains(SIMPLE_VALUE_QNAME));
+    }
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/InstanceIdentifierTest.java
new file mode 100644 (file)
index 0000000..fa8b48a
--- /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.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+
+public class InstanceIdentifierTest extends AbstractBindingRuntimeTest {
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
+            .augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST
+            .augmentation(TreeComplexUsesAugment.class);
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void testComplexAugmentationSerialization() {
+        YangInstanceIdentifier yangII = registry.toYangInstanceIdentifier(BA_TREE_COMPLEX_USES);
+        PathArgument lastArg = yangII.getLastPathArgument();
+        assertTrue("Last argument should be AugmentationIdentifier", lastArg instanceof AugmentationIdentifier);
+        InstanceIdentifier<?> bindingII = registry.fromYangInstanceIdentifier(yangII);
+        assertEquals(BA_TREE_COMPLEX_USES, bindingII);
+    }
+
+    @Test
+    public void testLeafOnlyAugmentationSerialization() {
+        PathArgument leafOnlyLastArg = registry.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY).getLastPathArgument();
+        assertTrue("Last argument should be AugmentationIdentifier", leafOnlyLastArg instanceof AugmentationIdentifier);
+        assertTrue(((AugmentationIdentifier) leafOnlyLastArg).getPossibleChildNames().contains(SIMPLE_VALUE_QNAME));
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/LeafReferenceTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/LeafReferenceTest.java
new file mode 100644 (file)
index 0000000..10dce65
--- /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.binding.data.codec.test;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Map.Entry;
+import javassist.ClassPool;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.ThirdParty;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexLeaves;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexLeavesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Int32StringUnion;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+
+
+public class LeafReferenceTest extends AbstractBindingRuntimeTest {
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TreeComplexLeaves> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
+            .child(TopLevelList.class, TOP_FOO_KEY).augmentation(TreeComplexLeaves.class).build();
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void testCaseWithLeafReferencesType() {
+        TreeComplexLeaves binding = new TreeComplexLeavesBuilder()
+            .setIdentity(ThirdParty.class)
+            .setIdentityRef(ThirdParty.class)
+            .setSimpleType(10)
+            .setSimpleTypeRef(10)
+            .setSchemaUnawareUnion(new Int32StringUnion("foo"))
+            .setSchemaUnawareUnionRef(new Int32StringUnion(10))
+        .build();
+        Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> dom = registry.toNormalizedNode(BA_TOP_LEVEL_LIST, binding);
+        Entry<InstanceIdentifier<?>, DataObject> readed = registry.fromNormalizedNode(dom.getKey(),dom.getValue());
+        TreeComplexLeaves readedAugment = ((TreeComplexLeaves) readed.getValue());
+
+        assertEquals(binding,readedAugment);
+
+    }
+
+
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NormalizedNodeSerializeDeserializeTest.java
new file mode 100644 (file)
index 0000000..e7af4ca
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * 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.binding.data.codec.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.top;
+import static org.opendaylight.controller.md.sal.test.model.util.ListsBindingUtils.topLevelList;
+import static org.opendaylight.yangtools.yang.data.impl.schema.Builders.*;
+import static org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes.leafNode;
+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 com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TopChoiceAugment1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TopChoiceAugment1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TopChoiceAugment2;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TopChoiceAugment2Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.augment.choice1.Case1Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.augment.choice1.case1.augment.choice2.Case11Builder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.top.augment.choice1.case1.augment.choice2.case11.Case11ChoiceCaseContainerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.ChoiceContainer;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.ChoiceContainerBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.choice.identifier.ExtendedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.choice.identifier.extended.ExtendedIdBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+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.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.Builders;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
+
+public class NormalizedNodeSerializeDeserializeTest extends AbstractBindingRuntimeTest{
+
+    public static final String TOP_LEVEL_LIST_FOO_KEY_VALUE = "foo";
+    public static final TopLevelListKey TOP_LEVEL_LIST_FOO_KEY = new TopLevelListKey(TOP_LEVEL_LIST_FOO_KEY_VALUE);
+
+    public static final QName TOP_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "top");
+    public static final QName TOP_LEVEL_LIST_QNAME = QName.create(TOP_QNAME, "top-level-list");
+    public static final QName TOP_LEVEL_LIST_KEY_QNAME = QName.create(TOP_QNAME, "name");
+    public static final QName TOP_LEVEL_LEAF_LIST_QNAME = QName.create(TOP_QNAME, "top-level-leaf-list");
+    public static final QName NESTED_LIST_QNAME = QName.create(TOP_QNAME, "nested-list");
+    public static final QName NESTED_LIST_KEY_QNAME = QName.create(TOP_QNAME, "name");
+    public static final QName CHOICE_CONTAINER_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:binding", "2014-07-01", "choice-container");
+    public static final QName CHOICE_IDENTIFIER_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "identifier");
+    public static final QName CHOICE_IDENTIFIER_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "id");
+    public static final QName SIMPLE_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "simple-id");
+    public static final QName EXTENDED_ID_QNAME = QName.create(CHOICE_CONTAINER_QNAME, "extended-id");
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+            .builder(Top.class).child(TopLevelList.class, TOP_LEVEL_LIST_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY =
+            BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES =
+            BA_TOP_LEVEL_LIST.augmentation(TreeComplexUsesAugment.class);
+
+    public static final YangInstanceIdentifier BI_TOP_PATH = YangInstanceIdentifier.of(TOP_QNAME);
+    public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_PATH = BI_TOP_PATH.node(TOP_LEVEL_LIST_QNAME);
+    public static final YangInstanceIdentifier BI_TOP_LEVEL_LIST_FOO_PATH = BI_TOP_LEVEL_LIST_PATH
+            .node(new YangInstanceIdentifier.NodeIdentifierWithPredicates(TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE));
+    public static final YangInstanceIdentifier BI_CHOICE_CONTAINER_PATH = YangInstanceIdentifier.of(CHOICE_CONTAINER_QNAME);
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Before
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void containerToNormalized() {
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(InstanceIdentifier.create(Top.class), top());
+        ContainerNode topNormalized = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+                .withChild(mapNodeBuilder(TOP_LEVEL_LIST_QNAME).build()).build();
+        assertEquals(topNormalized, entry.getValue());
+    }
+
+    @Test
+    public void containerFromNormalized() {
+        ContainerNode topNormalized = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+                .withChild(mapNodeBuilder(TOP_LEVEL_LIST_QNAME).build()).build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_PATH, topNormalized);
+        assertEquals(top(), entry.getValue());
+    }
+
+    @Test
+    public void listWithKeysToNormalized() {
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(BA_TOP_LEVEL_LIST, topLevelList(TOP_LEVEL_LIST_FOO_KEY));
+        MapEntryNode topLevelListNormalized = ImmutableMapEntryNodeBuilder.create()
+                .withNodeIdentifier(
+                        new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                                TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .build();
+        assertEquals(topLevelListNormalized, entry.getValue());
+    }
+
+    @Test
+    public void listWithKeysFromNormalized() {
+        MapEntryNode topLevelListNormalized = ImmutableMapEntryNodeBuilder.create()
+                .withNodeIdentifier(
+                        new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                                TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry =
+                registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH, topLevelListNormalized);
+        assertEquals(topLevelList(TOP_LEVEL_LIST_FOO_KEY), entry.getValue());
+    }
+
+    @Test
+    public void leafOnlyAugmentationToNormalized() {
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(BA_TREE_LEAF_ONLY, new TreeLeafOnlyAugmentBuilder().setSimpleValue("simpleValue").build());
+        Set<QName> augmentationChildren = new HashSet<>();
+        augmentationChildren.add(SIMPLE_VALUE_QNAME);
+        AugmentationNode augmentationNode = ImmutableAugmentationNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren))
+                .withChild(leafNode(SIMPLE_VALUE_QNAME, "simpleValue"))
+                .build();
+        assertEquals(augmentationNode, entry.getValue());
+    }
+
+    @Test
+    public void leafOnlyAugmentationFromNormalized() {
+        Set<QName> augmentationChildren = new HashSet<>();
+        augmentationChildren.add(SIMPLE_VALUE_QNAME);
+        AugmentationNode augmentationNode = ImmutableAugmentationNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren))
+                .withChild(leafNode(SIMPLE_VALUE_QNAME, "simpleValue"))
+                .build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH.node(
+                new YangInstanceIdentifier.AugmentationIdentifier(augmentationChildren)), augmentationNode);
+        assertEquals(new TreeLeafOnlyAugmentBuilder().setSimpleValue("simpleValue").build(), entry.getValue());
+    }
+
+    @Test
+    public void leafListToNormalized() {
+        List<String> topLevelLeafList = new ArrayList<>();
+        topLevelLeafList.add("foo");
+        Top top = new TopBuilder().setTopLevelLeafList(topLevelLeafList).build();
+
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(InstanceIdentifier.create(Top.class), top);
+        ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+                .withChild(ImmutableLeafSetNodeBuilder.create()
+                        .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_LEVEL_LEAF_LIST_QNAME))
+                        .withChild(
+                                ImmutableLeafSetEntryNodeBuilder.create()
+                                        .withNodeIdentifier(new YangInstanceIdentifier.NodeWithValue(TOP_LEVEL_LEAF_LIST_QNAME, "foo"))
+                                        .withValue("foo")
+                                        .build())
+                        .build())
+                .build();
+        assertEquals(containerNode, entry.getValue());
+    }
+
+    @Test
+    public void leafListFromNormalized() {
+        ContainerNode topWithLeafList = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+                .withChild(ImmutableLeafSetNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_LEVEL_LEAF_LIST_QNAME))
+                        .withChild(ImmutableLeafSetEntryNodeBuilder.create().withNodeIdentifier(
+                                new YangInstanceIdentifier.NodeWithValue(TOP_LEVEL_LEAF_LIST_QNAME, "foo")).withValue("foo").build()).build())
+                .build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_PATH, topWithLeafList);
+        List<String> topLevelLeafList = new ArrayList<>();
+        topLevelLeafList.add("foo");
+        Top top = new TopBuilder().setTopLevelLeafList(topLevelLeafList).build();
+        assertEquals(top, entry.getValue());
+    }
+
+    @Test
+    public void choiceToNormalized() {
+        ChoiceContainer choiceContainerBA = new ChoiceContainerBuilder().setIdentifier(new ExtendedBuilder().setExtendedId(
+                new ExtendedIdBuilder().setId("identifier_value").build()).build()).build();
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry =
+                registry.toNormalizedNode(InstanceIdentifier.create(ChoiceContainer.class), choiceContainerBA);
+        ContainerNode choiceContainer = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_CONTAINER_QNAME))
+                .withChild(ImmutableChoiceNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_IDENTIFIER_QNAME))
+                        .withChild(ImmutableContainerNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(EXTENDED_ID_QNAME))
+                                .withChild(leafNode(CHOICE_IDENTIFIER_ID_QNAME, "identifier_value")).build()).build())
+                .build();
+        assertEquals(choiceContainer, entry.getValue());
+    }
+
+    @Test
+    public void choiceFromNormalized() {
+        ContainerNode choiceContainerBI = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_CONTAINER_QNAME))
+                .withChild(ImmutableChoiceNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(CHOICE_IDENTIFIER_QNAME))
+                        .withChild(ImmutableContainerNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(EXTENDED_ID_QNAME))
+                                .withChild(leafNode(CHOICE_IDENTIFIER_ID_QNAME, "identifier_value")).build()).build())
+                .build();
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_CHOICE_CONTAINER_PATH, choiceContainerBI);
+        ChoiceContainer choiceContainerBA = new ChoiceContainerBuilder().setIdentifier(new ExtendedBuilder().setExtendedId(
+                new ExtendedIdBuilder().setId("identifier_value").build()).build()).build();
+        assertEquals(choiceContainerBA, entry.getValue());
+    }
+
+    @Test
+    public void orderedLisToNormalized() {
+        InstanceIdentifier<TopLevelList> ii = BA_TOP_LEVEL_LIST;
+        List<NestedList> nestedLists = new ArrayList<>();
+        nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("foo")).build());
+        nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("bar")).build());
+        TopLevelList topLevelList = new TopLevelListBuilder().setKey(TOP_LEVEL_LIST_FOO_KEY).setNestedList(nestedLists).build();
+        Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> entry = registry.toNormalizedNode(ii, topLevelList);
+        MapEntryNode foo = mapEntryBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(
+                        ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME))
+                                .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "foo"))
+                                .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "bar")).build()).build();
+        assertEquals(foo, entry.getValue());
+    }
+
+    @Test
+    public void orderedLisFromNormalized() {
+        MapEntryNode foo = mapEntryBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifierWithPredicates(
+                TOP_LEVEL_LIST_QNAME, TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(leafNode(TOP_LEVEL_LIST_KEY_QNAME, TOP_LEVEL_LIST_FOO_KEY_VALUE))
+                .withChild(
+                        ImmutableOrderedMapNodeBuilder.create().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(NESTED_LIST_QNAME))
+                                .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "foo"))
+                                .withChild(mapEntry(NESTED_LIST_QNAME, NESTED_LIST_KEY_QNAME, "bar")).build()).build();
+        InstanceIdentifier<TopLevelList> ii = BA_TOP_LEVEL_LIST;
+
+        Map.Entry<InstanceIdentifier<?>, DataObject> entry = registry.fromNormalizedNode(BI_TOP_LEVEL_LIST_FOO_PATH, foo);
+        List<NestedList> nestedLists = new ArrayList<>();
+        nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("foo")).build());
+        nestedLists.add(new NestedListBuilder().setKey(new NestedListKey("bar")).build());
+        TopLevelList topLevelList = new TopLevelListBuilder().setKey(TOP_LEVEL_LIST_FOO_KEY).setNestedList(nestedLists).build();
+        assertEquals(topLevelList, entry.getValue());
+    }
+
+    @Test
+    public void augmentMultipleChoices() {
+        QName augmentChoice1QName = QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:augment",
+                "2014-07-09", "augment-choice1");
+        QName augmentChoice2QName = QName.create(augmentChoice1QName, "augment-choice2");
+        final QName containerQName = QName.create(augmentChoice1QName, "case11-choice-case-container");
+        final QName leafQName = QName.create(augmentChoice1QName, "case11-choice-case-leaf");
+
+        final YangInstanceIdentifier.AugmentationIdentifier aug1Id =
+                new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice1QName));
+        final YangInstanceIdentifier.AugmentationIdentifier aug2Id =
+                new YangInstanceIdentifier.AugmentationIdentifier(Sets.newHashSet(augmentChoice2QName));
+        final YangInstanceIdentifier.NodeIdentifier augmentChoice1Id =
+                new YangInstanceIdentifier.NodeIdentifier(augmentChoice1QName);
+        final YangInstanceIdentifier.NodeIdentifier augmentChoice2Id =
+                new YangInstanceIdentifier.NodeIdentifier(augmentChoice2QName);
+        final YangInstanceIdentifier.NodeIdentifier containerId =
+                new YangInstanceIdentifier.NodeIdentifier(containerQName);
+
+        TopBuilder tBuilder = new TopBuilder();
+        TopChoiceAugment1Builder tca1Builder = new TopChoiceAugment1Builder();
+        Case1Builder c1Builder = new Case1Builder();
+        TopChoiceAugment2Builder tca2Builder = new TopChoiceAugment2Builder();
+        Case11Builder c11Builder = new Case11Builder();
+        Case11ChoiceCaseContainerBuilder cccc1Builder = new Case11ChoiceCaseContainerBuilder();
+        cccc1Builder.setCase11ChoiceCaseLeaf("leaf-value");
+        c11Builder.setCase11ChoiceCaseContainer(cccc1Builder.build());
+        tca2Builder.setAugmentChoice2(c11Builder.build());
+        c1Builder.addAugmentation(TopChoiceAugment2.class, tca2Builder.build());
+        tca1Builder.setAugmentChoice1(c1Builder.build());
+        tBuilder.addAugmentation(TopChoiceAugment1.class, tca1Builder.build());
+        final Top top = tBuilder.build();
+
+        final Map.Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> biResult =
+                registry.toNormalizedNode(InstanceIdentifier.create(Top.class), top);
+
+        final NormalizedNode<?, ?> topNormalized =
+                containerBuilder().withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(TOP_QNAME))
+                .withChild(augmentationBuilder().withNodeIdentifier(aug1Id)
+                        .withChild(choiceBuilder().withNodeIdentifier(augmentChoice1Id)
+                                .withChild(augmentationBuilder().withNodeIdentifier(aug2Id)
+                                        .withChild(choiceBuilder().withNodeIdentifier(augmentChoice2Id)
+                                                .withChild(containerBuilder().withNodeIdentifier(containerId)
+                                                        .withChild(leafNode(leafQName, "leaf-value"))
+                                                        .build())
+                                                .build())
+                                        .build())
+                                .build())
+                        .build()).build();
+
+        assertEquals(BI_TOP_PATH, biResult.getKey());
+        assertEquals(topNormalized, biResult.getValue());
+
+        final Map.Entry<InstanceIdentifier<?>, DataObject> baResult = registry.fromNormalizedNode(BI_TOP_PATH, topNormalized);
+
+        assertEquals(InstanceIdentifier.create(Top.class), baResult.getKey());
+        assertEquals(top, baResult.getValue());
+    }
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NotificationProcessingTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/NotificationProcessingTest.java
new file mode 100644 (file)
index 0000000..cb61d01
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.ImmutableList;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TwoLevelListChanged;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TwoLevelListChangedBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class NotificationProcessingTest extends AbstractBindingRuntimeTest {
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    @Before
+    public void setup() {
+        super.setup();
+        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    private TwoLevelListChanged createTestData() {
+        final TwoLevelListChangedBuilder tb = new TwoLevelListChangedBuilder();
+        tb.setTopLevelList(ImmutableList.of(new TopLevelListBuilder().setKey(new TopLevelListKey("test")).build()));
+        return tb.build();
+    }
+
+    @Test
+    public void testNotificationToNormalized() {
+        final TwoLevelListChanged bindingOriginal = createTestData();
+        final ContainerNode dom = registry.toNormalizedNodeNotification(bindingOriginal);
+        assertNotNull("Serialization must not return null obejct.",dom);
+        assertEquals(TwoLevelListChanged.QNAME,dom.getIdentifier().getNodeType());
+
+        final Notification bindingDeserialized = registry.fromNormalizedNodeNotification(SchemaPath.create(true, TwoLevelListChanged.QNAME),dom);
+        assertNotNull(bindingDeserialized);
+        assertTrue(bindingDeserialized instanceof TwoLevelListChanged);
+        assertEquals(bindingOriginal,bindingDeserialized);
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/RpcDataSerializationTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/RpcDataSerializationTest.java
new file mode 100644 (file)
index 0000000..3d3dda8
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import com.google.common.collect.ImmutableList;
+import javassist.ClassPool;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.GetTopOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.GetTopOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.PutTopInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.PutTopInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class RpcDataSerializationTest extends AbstractBindingRuntimeTest {
+
+    private BindingNormalizedNodeCodecRegistry registry;
+    private static final QName PUT_TOP = QName.create(PutTopInput.QNAME, "put-top");
+    private static final QName GET_TOP = QName.create(GetTopOutput.QNAME, "get-top");
+
+    private static final SchemaPath PUT_TOP_INPUT = SchemaPath.create(true, PUT_TOP, PutTopInput.QNAME);
+    private static final SchemaPath GET_TOP_OUTPUT = SchemaPath.create(true, GET_TOP, GetTopOutput.QNAME);
+
+    @Override
+    @Before
+    public void setup() {
+        super.setup();
+        final JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void testRpcInputToNormalized() {
+        final PutTopInputBuilder tb = new PutTopInputBuilder();
+        tb.setTopLevelList(ImmutableList.of(new TopLevelListBuilder().setKey(new TopLevelListKey("test")).build()));
+        final PutTopInput bindingOriginal = tb.build();
+        final ContainerNode dom = registry.toNormalizedNodeRpcData(bindingOriginal);
+        assertNotNull(dom);
+        assertEquals(PutTopInput.QNAME, dom.getIdentifier().getNodeType());
+
+        final DataObject bindingDeserialized = registry.fromNormalizedNodeRpcData(PUT_TOP_INPUT, dom);
+        assertEquals(bindingOriginal, bindingDeserialized);
+    }
+
+    @Test
+    public void testRpcOutputToNormalized() {
+        final GetTopOutputBuilder tb = new GetTopOutputBuilder();
+        tb.setTopLevelList(ImmutableList.of(new TopLevelListBuilder().setKey(new TopLevelListKey("test")).build()));
+        final GetTopOutput bindingOriginal = tb.build();
+        final ContainerNode dom = registry.toNormalizedNodeRpcData(bindingOriginal);
+        assertNotNull(dom);
+        assertEquals(GetTopOutput.QNAME, dom.getIdentifier().getNodeType());
+
+        final DataObject bindingDeserialized = registry.fromNormalizedNodeRpcData(GET_TOP_OUTPUT, dom);
+        assertEquals(bindingOriginal, bindingDeserialized);
+
+    }
+
+}
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/UnionTypeTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/UnionTypeTest.java
new file mode 100644 (file)
index 0000000..e519892
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 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.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.TopLevel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.TopLevelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.Wrapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.WrapperBuilder;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+
+public class UnionTypeTest extends AbstractBindingRuntimeTest {
+
+    private static final String testString = "testtesttest";
+
+    public static final QName WRAPPER_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:union", "2015-01-21", "wrapper");
+    public static final QName WRAP_LEAF_QNAME = QName.create(WRAPPER_QNAME, "wrap");
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void unionTest() {
+        TopLevel topLevel = TopLevelBuilder.getDefaultInstance(testString);
+        Wrapper wrapper = new WrapperBuilder().setWrap(topLevel).build();
+        NormalizedNode<?, ?> topLevelEntry = registry.toNormalizedNode(InstanceIdentifier.builder(Wrapper.class).build(), wrapper).getValue();
+
+        ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(WRAPPER_QNAME))
+                .withChild(ImmutableNodes.leafNode(WRAP_LEAF_QNAME, testString))
+                .build();
+        Assert.assertEquals(topLevelEntry, containerNode);
+    }
+}
diff --git a/code-generator/binding-generator-api/pom.xml b/code-generator/binding-generator-api/pom.xml
new file mode 100644 (file)
index 0000000..b475ad3
--- /dev/null
@@ -0,0 +1,54 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>binding-generator-api</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/BindingGenerator.java b/code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/BindingGenerator.java
new file mode 100644 (file)
index 0000000..6190008
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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.sal.binding.generator.api;
+
+import java.util.List;
+import java.util.Set;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Transform Schema Context to Generated types.
+ * 
+ */
+public interface BindingGenerator {
+
+    /**
+     * Generate Types from whole Schema Context. <br>
+     * The method will return List of All Generated Types that could be
+     * Generated from Schema Context.
+     * 
+     * 
+     * @param context
+     *            Schema Context
+     * @return List of Generated Types
+     * 
+     * @see SchemaContext
+     */
+    List<Type> generateTypes(final SchemaContext context);
+
+    /**
+     * Generate Types from Schema Context restricted by sub set of specified
+     * Modules. The Schema Context MUST contain all of the sub modules otherwise
+     * the there is no guarantee that result List of Generated Types will
+     * contain correct Generated Types.
+     * 
+     * @param context
+     *            Schema Context
+     * @param modules
+     *            Sub Set of Modules
+     * @return List of Generated Types restricted by sub set of Modules
+     * 
+     * @see Module
+     * @see SchemaContext
+     * 
+     */
+    List<Type> generateTypes(final SchemaContext context, final Set<Module> modules);
+}
diff --git a/code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/ClassLoadingStrategy.java b/code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/ClassLoadingStrategy.java
new file mode 100644 (file)
index 0000000..2d9e32d
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.sal.binding.generator.api;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+public interface ClassLoadingStrategy {
+
+    Class<?> loadClass(Type type) throws ClassNotFoundException;
+
+    Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException;
+
+}
diff --git a/code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/ModuleInfoRegistry.java b/code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/ModuleInfoRegistry.java
new file mode 100644 (file)
index 0000000..9888b1d
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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.sal.binding.generator.api;
+
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+
+public interface ModuleInfoRegistry {
+
+    ObjectRegistration<YangModuleInfo> registerModuleInfo(YangModuleInfo yangModuleInfo);
+}
diff --git a/code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/package-info.java b/code-generator/binding-generator-api/src/main/java/org/opendaylight/yangtools/sal/binding/generator/api/package-info.java
new file mode 100644 (file)
index 0000000..13b7296
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.sal.binding.generator.api;
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/pom.xml b/code-generator/binding-generator-impl/pom.xml
new file mode 100644 (file)
index 0000000..d446c82
--- /dev/null
@@ -0,0 +1,104 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>binding-generator-impl</artifactId>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.javassist</groupId>
+            <artifactId>javassist</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-type-provider</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Export-Package>
+                            org.opendaylight.yangtools.sal.binding.generator.impl.*,
+                            org.opendaylight.yangtools.sal.binding.generator.util.*
+                        </Export-Package>
+                        <Embed-Dependency>
+                            org.eclipse.xtend.lib;inline=true,
+                            org.eclipse.xtend.lib.macro;inline=true,
+                            org.eclipse.xtext.xbase.lib;inline=true,
+                        </Embed-Dependency>
+                        <Embed-Transitive>true</Embed-Transitive>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.java
new file mode 100644 (file)
index 0000000..3854be4
--- /dev/null
@@ -0,0 +1,2200 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.computeDefaultSUID;
+import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.packageNameForGeneratedType;
+import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.DATA_OBJECT;
+import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.DATA_ROOT;
+import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.IDENTIFIABLE;
+import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.IDENTIFIER;
+import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.NOTIFICATION;
+import static org.opendaylight.yangtools.binding.generator.util.BindingTypes.augmentable;
+import static org.opendaylight.yangtools.binding.generator.util.Types.BOOLEAN;
+import static org.opendaylight.yangtools.binding.generator.util.Types.FUTURE;
+import static org.opendaylight.yangtools.binding.generator.util.Types.VOID;
+import static org.opendaylight.yangtools.binding.generator.util.Types.typeForClass;
+import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
+import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findNodeInSchemaContext;
+import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
+import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.sal.binding.yang.types.GroupingDefinitionDependencySort;
+import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+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.DerivableSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+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.ModuleImport;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+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.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.BaseTypes;
+import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
+import org.opendaylight.yangtools.yang.model.util.UnionType;
+import org.opendaylight.yangtools.yang.parser.builder.util.Comparators;
+import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BindingGeneratorImpl implements BindingGenerator {
+    private static final Logger LOG = LoggerFactory.getLogger(BindingGeneratorImpl.class);
+    private static final Splitter COLON_SPLITTER = Splitter.on(':');
+    private static final Splitter BSDOT_SPLITTER = Splitter.on("\\.");
+    private static final char NEW_LINE = '\n';
+    private static final String QNAME_FQCN = QName.class.getName();
+
+    /**
+     * Constant with the concrete name of identifier.
+     */
+    private static final String AUGMENT_IDENTIFIER_NAME = "augment-identifier";
+
+    /**
+     * Constant with the concrete name of namespace.
+     */
+    private static final String YANG_EXT_NAMESPACE = "urn:opendaylight:yang:extension:yang-ext";
+
+    private static final Pattern UNICODE_CHAR_PATTERN = Pattern.compile("\\\\+u");
+
+    private final Map<Module, ModuleContext> genCtx = new HashMap<>();
+
+    /**
+     * When set to true, generated classes will include javadoc comments which
+     * are useful for users.
+     */
+    private final boolean verboseClassComments;
+
+    /**
+     * Outer key represents the package name. Outer value represents map of all
+     * builders in the same package. Inner key represents the schema node name
+     * (in JAVA class/interface name format). Inner value represents instance of
+     * builder for schema node specified in key part.
+     */
+    private Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders;
+
+    /**
+     * Provide methods for converting YANG types to JAVA types.
+     */
+    private TypeProvider typeProvider;
+
+    /**
+     * Holds reference to schema context to resolve data of augmented element
+     * when creating augmentation builder
+     */
+    private SchemaContext schemaContext;
+
+    /**
+     * Create a new binding generator with verboe comments.
+     *
+     * @deprecated Use {@link #BindingGeneratorImpl(boolean)} instead.
+     */
+    @Deprecated
+    public BindingGeneratorImpl() {
+        this(true);
+    }
+
+    /**
+     * Create a new binding generator.
+     *
+     * @param verboseClassComments generate verbose comments
+     */
+    public BindingGeneratorImpl(final boolean verboseClassComments) {
+        this.verboseClassComments = verboseClassComments;
+    }
+
+    /**
+     * Resolves generated types from <code>context</code> schema nodes of all
+     * modules.
+     *
+     * Generated types are created for modules, groupings, types, containers,
+     * lists, choices, augments, rpcs, notification, identities.
+     *
+     * @param context
+     *            schema context which contains data about all schema nodes
+     *            saved in modules
+     * @return list of types (usually <code>GeneratedType</code>
+     *         <code>GeneratedTransferObject</code>which are generated from
+     *         <code>context</code> data.
+     * @throws IllegalArgumentException
+     *             if arg <code>context</code> is null
+     * @throws IllegalStateException
+     *             if <code>context</code> contain no modules
+     */
+    @Override
+    public List<Type> generateTypes(final SchemaContext context) {
+        checkArgument(context != null, "Schema Context reference cannot be NULL.");
+        checkState(context.getModules() != null, "Schema Context does not contain defined modules.");
+        schemaContext = context;
+        typeProvider = new TypeProviderImpl(context);
+        final Set<Module> modules = context.getModules();
+        return generateTypes(context, modules);
+    }
+
+    /**
+     * Resolves generated types from <code>context</code> schema nodes only for
+     * modules specified in <code>modules</code>
+     *
+     * Generated types are created for modules, groupings, types, containers,
+     * lists, choices, augments, rpcs, notification, identities.
+     *
+     * @param context
+     *            schema context which contains data about all schema nodes
+     *            saved in modules
+     * @param modules
+     *            set of modules for which schema nodes should be generated
+     *            types
+     * @return list of types (usually <code>GeneratedType</code> or
+     *         <code>GeneratedTransferObject</code>) which:
+     *         <ul>
+     *         <li>are generated from <code>context</code> schema nodes and</li>
+     *         <li>are also part of some of the module in <code>modules</code>
+     *         set.</li>
+     *         </ul>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if arg <code>context</code> is null or</li>
+     *             <li>if arg <code>modules</code> is null</li>
+     *             </ul>
+     * @throws IllegalStateException
+     *             if <code>context</code> contain no modules
+     */
+    @Override
+    public List<Type> generateTypes(final SchemaContext context, final Set<Module> modules) {
+        checkArgument(context != null, "Schema Context reference cannot be NULL.");
+        checkState(context.getModules() != null, "Schema Context does not contain defined modules.");
+        checkArgument(modules != null, "Set of Modules cannot be NULL.");
+
+        schemaContext = context;
+        typeProvider = new TypeProviderImpl(context);
+        final Module[] modulesArray = new Module[context.getModules().size()];
+        context.getModules().toArray(modulesArray);
+        final List<Module> contextModules = ModuleDependencySort.sort(modulesArray);
+        genTypeBuilders = new HashMap<>();
+
+        for (final Module contextModule : contextModules) {
+            moduleToGenTypes(contextModule, context);
+        }
+        for (final Module contextModule : contextModules) {
+            allAugmentsToGenTypes(contextModule);
+        }
+
+        final List<Type> filteredGenTypes = new ArrayList<>();
+        for (final Module m : modules) {
+            final ModuleContext ctx = checkNotNull(genCtx.get(m), "Module context not found for module %s", m);
+            filteredGenTypes.addAll(ctx.getGeneratedTypes());
+            final Set<Type> additionalTypes = ((TypeProviderImpl) typeProvider).getAdditionalTypes().get(m);
+            if (additionalTypes != null) {
+                filteredGenTypes.addAll(additionalTypes);
+            }
+        }
+
+        return filteredGenTypes;
+    }
+
+    private void moduleToGenTypes(final Module m, final SchemaContext context) {
+        genCtx.put(m, new ModuleContext());
+        allTypeDefinitionsToGenTypes(m);
+        groupingsToGenTypes(m, m.getGroupings());
+        rpcMethodsToGenType(m);
+        allIdentitiesToGenTypes(m, context);
+        notificationsToGenType(m);
+
+        if (!m.getChildNodes().isEmpty()) {
+            final GeneratedTypeBuilder moduleType = moduleToDataType(m);
+            genCtx.get(m).addModuleNode(moduleType);
+            final String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
+            resolveDataSchemaNodes(m, basePackageName, moduleType, moduleType, m.getChildNodes());
+        }
+    }
+
+    /**
+     * Converts all extended type definitions of module to the list of
+     * <code>Type</code> objects.
+     *
+     * @param module
+     *            module from which is obtained set of type definitions
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if module is null</li>
+     *             <li>if name of module is null</li>
+     *             </ul>
+     * @throws IllegalStateException
+     *             if set of type definitions from module is null
+     */
+    private void allTypeDefinitionsToGenTypes(final Module module) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        checkArgument(module.getName() != null, "Module name cannot be NULL.");
+        final DataNodeIterator it = new DataNodeIterator(module);
+        final List<TypeDefinition<?>> typeDefinitions = it.allTypedefs();
+        checkState(typeDefinitions != null, "Type Definitions for module Â«module.name» cannot be NULL.");
+
+        for (final TypeDefinition<?> typedef : typeDefinitions) {
+            if (typedef != null) {
+                final Type type = ((TypeProviderImpl) typeProvider).generatedTypeForExtendedDefinitionType(typedef,
+                        typedef);
+                if (type != null) {
+                    final ModuleContext ctx = genCtx.get(module);
+                    ctx.addTypedefType(typedef.getPath(), type);
+                    ctx.addTypeToSchema(type,typedef);
+                }
+            }
+        }
+    }
+
+    private GeneratedTypeBuilder processDataSchemaNode(final Module module, final String basePackageName,
+            final GeneratedTypeBuilder childOf, final DataSchemaNode node) {
+        if (node.isAugmenting() || node.isAddedByUses()) {
+            return null;
+        }
+        final String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
+        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, node, childOf, module);
+        genType.addComment(node.getDescription());
+        genType.setDescription(createDescription(node, genType.getFullyQualifiedName()));
+        genType.setModuleName(module.getName());
+        genType.setReference(node.getReference());
+        genType.setSchemaPath(node.getPath().getPathFromRoot());
+        if (node instanceof DataNodeContainer) {
+            genCtx.get(module).addChildNodeType(node, genType);
+            groupingsToGenTypes(module, ((DataNodeContainer) node).getGroupings());
+            processUsesAugments((DataNodeContainer) node, module);
+        }
+        return genType;
+    }
+
+    private void containerToGenType(final Module module, final String basePackageName,
+            final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final ContainerSchemaNode node) {
+        final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node);
+        if (genType != null) {
+            constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), genType);
+            resolveDataSchemaNodes(module, basePackageName, genType, genType, node.getChildNodes());
+        }
+    }
+
+    private void listToGenType(final Module module, final String basePackageName, final GeneratedTypeBuilder parent,
+            final GeneratedTypeBuilder childOf, final ListSchemaNode node) {
+        final GeneratedTypeBuilder genType = processDataSchemaNode(module, basePackageName, childOf, node);
+        if (genType != null) {
+            constructGetter(parent, node.getQName().getLocalName(), node.getDescription(), Types.listTypeFor(genType));
+
+            final List<String> listKeys = listKeys(node);
+            final String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
+            final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(packageName, node);
+            if (genTOBuilder != null) {
+                final Type identifierMarker = Types.parameterizedTypeFor(IDENTIFIER, genType);
+                final Type identifiableMarker = Types.parameterizedTypeFor(IDENTIFIABLE, genTOBuilder);
+                genTOBuilder.addImplementsType(identifierMarker);
+                genType.addImplementsType(identifiableMarker);
+            }
+
+            for (final DataSchemaNode schemaNode : node.getChildNodes()) {
+                if (!schemaNode.isAugmenting()) {
+                    addSchemaNodeToListBuilders(basePackageName, schemaNode, genType, genTOBuilder, listKeys, module);
+                }
+            }
+
+            // serialVersionUID
+            if (genTOBuilder != null) {
+                final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
+                prop.setValue(Long.toString(computeDefaultSUID(genTOBuilder)));
+                genTOBuilder.setSUID(prop);
+            }
+
+            typeBuildersToGenTypes(module, genType, genTOBuilder);
+        }
+    }
+
+    private void processUsesAugments(final DataNodeContainer node, final Module module) {
+        final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+        for (final UsesNode usesNode : node.getUses()) {
+            for (final AugmentationSchema augment : usesNode.getAugmentations()) {
+                usesAugmentationToGenTypes(basePackageName, augment, module, usesNode, node);
+                processUsesAugments(augment, module);
+            }
+        }
+    }
+
+    /**
+     * Converts all <b>augmentation</b> of the module to the list
+     * <code>Type</code> objects.
+     *
+     * @param module
+     *            module from which is obtained list of all augmentation objects
+     *            to iterate over them
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if the module is null</li>
+     *             <li>if the name of module is null</li>
+     *             </ul>
+     * @throws IllegalStateException
+     *             if set of augmentations from module is null
+     */
+    private void allAugmentsToGenTypes(final Module module) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        checkArgument(module.getName() != null, "Module name cannot be NULL.");
+        checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL.");
+
+        final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+        final List<AugmentationSchema> augmentations = resolveAugmentations(module);
+        for (final AugmentationSchema augment : augmentations) {
+            augmentationToGenTypes(basePackageName, augment, module);
+        }
+    }
+
+    /**
+     * Returns list of <code>AugmentationSchema</code> objects. The objects are
+     * sorted according to the length of their target path from the shortest to
+     * the longest.
+     *
+     * @param module
+     *            module from which is obtained list of all augmentation objects
+     * @return list of sorted <code>AugmentationSchema</code> objects obtained
+     *         from <code>module</code>
+     * @throws IllegalArgumentException
+     *             if module is null
+     * @throws IllegalStateException
+     *             if set of module augmentations is null
+     */
+    private static List<AugmentationSchema> resolveAugmentations(final Module module) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        checkState(module.getAugmentations() != null, "Augmentations Set cannot be NULL.");
+
+        final Set<AugmentationSchema> augmentations = module.getAugmentations();
+        final List<AugmentationSchema> sortedAugmentations = new ArrayList<>(augmentations);
+        Collections.sort(sortedAugmentations, Comparators.AUGMENT_COMP);
+
+        return sortedAugmentations;
+    }
+
+    /**
+     * Create GeneratedTypeBuilder object from module argument.
+     *
+     * @param module
+     *            Module object from which builder will be created
+     * @return <code>GeneratedTypeBuilder</code> which is internal
+     *         representation of the module
+     * @throws IllegalArgumentException
+     *             if module is null
+     */
+    private GeneratedTypeBuilder moduleToDataType(final Module module) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+
+        final GeneratedTypeBuilder moduleDataTypeBuilder = moduleTypeBuilder(module, "Data");
+        addImplementedInterfaceFromUses(module, moduleDataTypeBuilder);
+        moduleDataTypeBuilder.addImplementsType(DATA_ROOT);
+        moduleDataTypeBuilder.addComment(module.getDescription());
+        moduleDataTypeBuilder.setDescription(createDescription(module));
+        moduleDataTypeBuilder.setReference(module.getReference());
+        return moduleDataTypeBuilder;
+    }
+
+    /**
+     * Converts all <b>rpcs</b> inputs and outputs substatements of the module
+     * to the list of <code>Type</code> objects. In addition are to containers
+     * and lists which belong to input or output also part of returning list.
+     *
+     * @param module
+     *            module from which is obtained set of all rpc objects to
+     *            iterate over them
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if the module is null</li>
+     *             <li>if the name of module is null</li>
+     *             </ul>
+     * @throws IllegalStateException
+     *             if set of rpcs from module is null
+     */
+    private void rpcMethodsToGenType(final Module module) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        checkArgument(module.getName() != null, "Module name cannot be NULL.");
+        final Set<RpcDefinition> rpcDefinitions = module.getRpcs();
+        checkState(rpcDefinitions != null, "Set of rpcs from module " + module.getName() + " cannot be NULL.");
+        if (rpcDefinitions.isEmpty()) {
+            return;
+        }
+
+        final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+        final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, "Service");
+        interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class));
+        interfaceBuilder.setDescription(createDescription(rpcDefinitions, module.getName(), module.getModuleSourcePath()));
+
+        for (final RpcDefinition rpc : rpcDefinitions) {
+            if (rpc != null) {
+                final String rpcName = BindingMapping.getClassName(rpc.getQName());
+                final String rpcMethodName = BindingMapping.getPropertyName(rpcName);
+                final String rpcComment = rpc.getDescription();
+                final MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName);
+                final ContainerSchemaNode input = rpc.getInput();
+                final ContainerSchemaNode output = rpc.getOutput();
+
+                if (input != null) {
+                    final GeneratedTypeBuilder inType = addRawInterfaceDefinition(basePackageName, input, rpcName);
+                    addImplementedInterfaceFromUses(input, inType);
+                    inType.addImplementsType(DATA_OBJECT);
+                    inType.addImplementsType(augmentable(inType));
+                    resolveDataSchemaNodes(module, basePackageName, inType, inType, input.getChildNodes());
+                    genCtx.get(module).addChildNodeType(input, inType);
+                    final GeneratedType inTypeInstance = inType.toInstance();
+                    method.addParameter(inTypeInstance, "input");
+                }
+
+                Type outTypeInstance = VOID;
+                if (output != null) {
+                    final GeneratedTypeBuilder outType = addRawInterfaceDefinition(basePackageName, output, rpcName);
+                    addImplementedInterfaceFromUses(output, outType);
+                    outType.addImplementsType(DATA_OBJECT);
+                    outType.addImplementsType(augmentable(outType));
+                    resolveDataSchemaNodes(module, basePackageName, outType, outType, output.getChildNodes());
+                    genCtx.get(module).addChildNodeType(output, outType);
+                    outTypeInstance = outType.toInstance();
+                }
+
+                final Type rpcRes = Types.parameterizedTypeFor(Types.typeForClass(RpcResult.class), outTypeInstance);
+                method.setComment(rpcComment);
+                method.setReturnType(Types.parameterizedTypeFor(FUTURE, rpcRes));
+            }
+        }
+
+        genCtx.get(module).addTopLevelNodeType(interfaceBuilder);
+    }
+
+    /**
+     * Converts all <b>notifications</b> of the module to the list of
+     * <code>Type</code> objects. In addition are to this list added containers
+     * and lists which are part of this notification.
+     *
+     * @param module
+     *            module from which is obtained set of all notification objects
+     *            to iterate over them
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if the module equals null</li>
+     *             <li>if the name of module equals null</li>
+     *             </ul>
+     * @throws IllegalStateException
+     *             if set of notifications from module is null
+     */
+    private void notificationsToGenType(final Module module) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        checkArgument(module.getName() != null, "Module name cannot be NULL.");
+        final Set<NotificationDefinition> notifications = module.getNotifications();
+        checkState(notifications != null, "Set of notification from module " + module.getName() + " cannot be NULL.");
+        if (notifications.isEmpty()) {
+            return;
+        }
+
+        final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(module, "Listener");
+        listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER);
+        final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+
+
+
+        for (final NotificationDefinition notification : notifications) {
+            if (notification != null) {
+                processUsesAugments(notification, module);
+
+                final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(basePackageName,
+                        notification, null, module);
+                notificationInterface.addImplementsType(NOTIFICATION);
+                genCtx.get(module).addChildNodeType(notification, notificationInterface);
+
+                // Notification object
+                resolveDataSchemaNodes(module, basePackageName, notificationInterface, notificationInterface,
+                        notification.getChildNodes());
+
+                listenerInterface.addMethod("on" + notificationInterface.getName())
+                .setAccessModifier(AccessModifier.PUBLIC).addParameter(notificationInterface, "notification")
+                .setComment(notification.getDescription()).setReturnType(Types.VOID);
+            }
+        }
+        listenerInterface.setDescription(createDescription(notifications, module.getName(), module.getModuleSourcePath()));
+
+        genCtx.get(module).addTopLevelNodeType(listenerInterface);
+    }
+
+    /**
+     * Converts all <b>identities</b> of the module to the list of
+     * <code>Type</code> objects.
+     *
+     * @param module
+     *            module from which is obtained set of all identity objects to
+     *            iterate over them
+     * @param context
+     *            schema context only used as input parameter for method
+     *            {@link identityToGenType}
+     *
+     */
+    private void allIdentitiesToGenTypes(final Module module, final SchemaContext context) {
+        final Set<IdentitySchemaNode> schemaIdentities = module.getIdentities();
+        final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+
+        if (schemaIdentities != null && !schemaIdentities.isEmpty()) {
+            for (final IdentitySchemaNode identity : schemaIdentities) {
+                identityToGenType(module, basePackageName, identity, context);
+            }
+        }
+    }
+
+    /**
+     * Converts the <b>identity</b> object to GeneratedType. Firstly it is
+     * created transport object builder. If identity contains base identity then
+     * reference to base identity is added to superior identity as its extend.
+     * If identity doesn't contain base identity then only reference to abstract
+     * class {@link org.opendaylight.yangtools.yang.model.api.BaseIdentity
+     * BaseIdentity} is added
+     *
+     * @param module
+     *            current module
+     * @param basePackageName
+     *            string contains the module package name
+     * @param identity
+     *            IdentitySchemaNode which contains data about identity
+     * @param context
+     *            SchemaContext which is used to get package and name
+     *            information about base of identity
+     *
+     */
+    private void identityToGenType(final Module module, final String basePackageName,
+            final IdentitySchemaNode identity, final SchemaContext context) {
+        if (identity == null) {
+            return;
+        }
+        final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
+        final String genTypeName = BindingMapping.getClassName(identity.getQName());
+        final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTypeName);
+        final IdentitySchemaNode baseIdentity = identity.getBaseIdentity();
+        if (baseIdentity == null) {
+            final GeneratedTOBuilderImpl gto = new GeneratedTOBuilderImpl(BaseIdentity.class.getPackage().getName(),
+                    BaseIdentity.class.getSimpleName());
+            newType.setExtendsType(gto.toInstance());
+        } else {
+            final Module baseIdentityParentModule = SchemaContextUtil.findParentModule(context, baseIdentity);
+            final String returnTypePkgName = BindingMapping.getRootPackageName(baseIdentityParentModule
+                    .getQNameModule());
+            final String returnTypeName = BindingMapping.getClassName(baseIdentity.getQName());
+            final GeneratedTransferObject gto = new GeneratedTOBuilderImpl(returnTypePkgName, returnTypeName)
+            .toInstance();
+            newType.setExtendsType(gto);
+        }
+        newType.setAbstract(true);
+        newType.addComment(identity.getDescription());
+        newType.setDescription(createDescription(identity, newType.getFullyQualifiedName()));
+        newType.setReference(identity.getReference());
+        newType.setModuleName(module.getName());
+        newType.setSchemaPath(identity.getPath().getPathFromRoot());
+
+        final QName qname = identity.getQName();
+        qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, qname);
+
+        genCtx.get(module).addIdentityType(identity.getQName(), newType);
+    }
+
+    private static Constant qnameConstant(final GeneratedTypeBuilderBase<?> toBuilder, final String constantName,
+            final QName name) {
+        final StringBuilder sb = new StringBuilder(QNAME_FQCN);
+        sb.append(".cachedReference(");
+        sb.append(QNAME_FQCN);
+        sb.append(".create(");
+        sb.append('"');
+        sb.append(name.getNamespace());
+        sb.append("\",\"");
+        sb.append(name.getFormattedRevision());
+        sb.append("\",\"");
+        sb.append(name.getLocalName());
+        sb.append("\"))");
+
+        return toBuilder.addConstant(typeForClass(QName.class), constantName, sb.toString());
+    }
+
+    /**
+     * Converts all <b>groupings</b> of the module to the list of
+     * <code>Type</code> objects. Firstly are groupings sorted according mutual
+     * dependencies. At least dependent (independent) groupings are in the list
+     * saved at first positions. For every grouping the record is added to map
+     * {@link BindingGeneratorImpl#allGroupings allGroupings}
+     *
+     * @param module
+     *            current module
+     * @param collection
+     *            of groupings from which types will be generated
+     *
+     */
+    private void groupingsToGenTypes(final Module module, final Collection<GroupingDefinition> groupings) {
+        final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+        final List<GroupingDefinition> groupingsSortedByDependencies = new GroupingDefinitionDependencySort()
+        .sort(groupings);
+        for (final GroupingDefinition grouping : groupingsSortedByDependencies) {
+            groupingToGenType(basePackageName, grouping, module);
+        }
+    }
+
+    /**
+     * Converts individual grouping to GeneratedType. Firstly generated type
+     * builder is created and every child node of grouping is resolved to the
+     * method.
+     *
+     * @param basePackageName
+     *            string contains the module package name
+     * @param grouping
+     *            GroupingDefinition which contains data about grouping
+     * @param module
+     *            current module
+     * @return GeneratedType which is generated from grouping (object of type
+     *         <code>GroupingDefinition</code>)
+     */
+    private void groupingToGenType(final String basePackageName, final GroupingDefinition grouping, final Module module) {
+        final String packageName = packageNameForGeneratedType(basePackageName, grouping.getPath());
+        final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(packageName, grouping, module);
+        genCtx.get(module).addGroupingType(grouping.getPath(), genType);
+        resolveDataSchemaNodes(module, basePackageName, genType, genType, grouping.getChildNodes());
+        groupingsToGenTypes(module, grouping.getGroupings());
+        processUsesAugments(grouping, module);
+    }
+
+    /**
+     * Adds enumeration builder created from <code>enumTypeDef</code> to
+     * <code>typeBuilder</code>.
+     *
+     * Each <code>enumTypeDef</code> item is added to builder with its name and
+     * value.
+     *
+     * @param enumTypeDef
+     *            EnumTypeDefinition contains enum data
+     * @param enumName
+     *            string contains name which will be assigned to enumeration
+     *            builder
+     * @param typeBuilder
+     *            GeneratedTypeBuilder to which will be enum builder assigned
+     * @param module
+     *            Module in which type should be generated
+     * @return enumeration builder which contains data from
+     *         <code>enumTypeDef</code>
+     */
+    private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final QName enumName,
+            final GeneratedTypeBuilder typeBuilder, final Module module) {
+        if ((enumTypeDef != null) && (typeBuilder != null) && (enumTypeDef.getQName() != null)
+                && (enumTypeDef.getQName().getLocalName() != null)) {
+            final String enumerationName = BindingMapping.getClassName(enumName);
+            final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
+            enumBuilder.setDescription(enumTypeDef.getDescription());
+            enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
+            ModuleContext ctx = genCtx.get(module);
+            ctx.addInnerTypedefType(enumTypeDef.getPath(), enumBuilder);
+            return enumBuilder;
+        }
+        return null;
+    }
+
+    /**
+     * Generates type builder for <code>module</code>.
+     *
+     * @param module
+     *            Module which is source of package name for generated type
+     *            builder
+     * @param postfix
+     *            string which is added to the module class name representation
+     *            as suffix
+     * @return instance of GeneratedTypeBuilder which represents
+     *         <code>module</code>.
+     * @throws IllegalArgumentException
+     *             if <code>module</code> is null
+     */
+    private GeneratedTypeBuilder moduleTypeBuilder(final Module module, final String postfix) {
+        checkArgument(module != null, "Module reference cannot be NULL.");
+        final String packageName = BindingMapping.getRootPackageName(module.getQNameModule());
+        final String moduleName = BindingMapping.getClassName(module.getName()) + postfix;
+
+        final GeneratedTypeBuilderImpl moduleBuilder = new GeneratedTypeBuilderImpl(packageName, moduleName);
+        moduleBuilder.setDescription(createDescription(module));
+        moduleBuilder.setReference(module.getReference());
+        moduleBuilder.setModuleName(moduleName);
+
+        return moduleBuilder;
+    }
+
+    /**
+     * Converts <code>augSchema</code> to list of <code>Type</code> which
+     * contains generated type for augmentation. In addition there are also
+     * generated types for all containers, list and choices which are child of
+     * <code>augSchema</code> node or a generated types for cases are added if
+     * augmented node is choice.
+     *
+     * @param augmentPackageName
+     *            string with the name of the package to which the augmentation
+     *            belongs
+     * @param augSchema
+     *            AugmentationSchema which is contains data about augmentation
+     *            (target path, childs...)
+     * @param module
+     *            current module
+     * @param parentUsesNode
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>augmentPackageName</code> equals null</li>
+     *             <li>if <code>augSchema</code> equals null</li>
+     *             </ul>
+     * @throws IllegalStateException
+     *             if augment target path is null
+     */
+    private void augmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema,
+            final Module module) {
+        checkArgument(augmentPackageName != null, "Package Name cannot be NULL.");
+        checkArgument(augSchema != null, "Augmentation Schema cannot be NULL.");
+        checkState(augSchema.getTargetPath() != null,
+                "Augmentation Schema does not contain Target Path (Target Path is NULL).");
+
+        processUsesAugments(augSchema, module);
+        final SchemaPath targetPath = augSchema.getTargetPath();
+        SchemaNode targetSchemaNode = null;
+
+        targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
+        if (targetSchemaNode instanceof DataSchemaNode && ((DataSchemaNode) targetSchemaNode).isAddedByUses()) {
+            if (targetSchemaNode instanceof DerivableSchemaNode) {
+                targetSchemaNode = ((DerivableSchemaNode) targetSchemaNode).getOriginal().orNull();
+            }
+            if (targetSchemaNode == null) {
+                throw new IllegalStateException("Failed to find target node from grouping in augmentation " + augSchema
+                        + " in module " + module.getName());
+            }
+        }
+        if (targetSchemaNode == null) {
+            throw new IllegalArgumentException("augment target not found: " + targetPath);
+        }
+
+        GeneratedTypeBuilder targetTypeBuilder = findChildNodeByPath(targetSchemaNode.getPath());
+        if (targetTypeBuilder == null) {
+            targetTypeBuilder = findCaseByPath(targetSchemaNode.getPath());
+        }
+        if (targetTypeBuilder == null) {
+            throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
+        }
+
+        if (!(targetSchemaNode instanceof ChoiceSchemaNode)) {
+            final String packageName = augmentPackageName;
+            final Type targetType = new ReferencedTypeImpl(targetTypeBuilder.getPackageName(),
+                    targetTypeBuilder.getName());
+            addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName, targetType, augSchema);
+
+        } else {
+            generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(),
+                    (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes());
+        }
+    }
+
+    private void usesAugmentationToGenTypes(final String augmentPackageName, final AugmentationSchema augSchema,
+            final Module module, final UsesNode usesNode, final DataNodeContainer usesNodeParent) {
+        checkArgument(augmentPackageName != null, "Package Name cannot be NULL.");
+        checkArgument(augSchema != null, "Augmentation Schema cannot be NULL.");
+        checkState(augSchema.getTargetPath() != null,
+                "Augmentation Schema does not contain Target Path (Target Path is NULL).");
+
+        processUsesAugments(augSchema, module);
+        final SchemaPath targetPath = augSchema.getTargetPath();
+        final SchemaNode targetSchemaNode = findOriginalTargetFromGrouping(targetPath, usesNode);
+        if (targetSchemaNode == null) {
+            throw new IllegalArgumentException("augment target not found: " + targetPath);
+        }
+
+        GeneratedTypeBuilder targetTypeBuilder = findChildNodeByPath(targetSchemaNode.getPath());
+        if (targetTypeBuilder == null) {
+            targetTypeBuilder = findCaseByPath(targetSchemaNode.getPath());
+        }
+        if (targetTypeBuilder == null) {
+            throw new NullPointerException("Target type not yet generated: " + targetSchemaNode);
+        }
+
+        if (!(targetSchemaNode instanceof ChoiceSchemaNode)) {
+            String packageName = augmentPackageName;
+            if (usesNodeParent instanceof SchemaNode) {
+                packageName = packageNameForGeneratedType(augmentPackageName, ((SchemaNode) usesNodeParent).getPath(),
+                        true);
+            }
+            addRawAugmentGenTypeDefinition(module, packageName, augmentPackageName, targetTypeBuilder.toInstance(),
+                    augSchema);
+        } else {
+            generateTypesFromAugmentedChoiceCases(module, augmentPackageName, targetTypeBuilder.toInstance(),
+                    (ChoiceSchemaNode) targetSchemaNode, augSchema.getChildNodes());
+        }
+    }
+
+    /**
+     * Convenient method to find node added by uses statement.
+     *
+     * @param targetPath
+     *            node path
+     * @param parentUsesNode
+     *            parent of uses node
+     * @return node from its original location in grouping
+     */
+    private DataSchemaNode findOriginalTargetFromGrouping(final SchemaPath targetPath, final UsesNode parentUsesNode) {
+        final SchemaNode targetGrouping = findNodeInSchemaContext(schemaContext, parentUsesNode.getGroupingPath()
+                .getPathFromRoot());
+        if (!(targetGrouping instanceof GroupingDefinition)) {
+            throw new IllegalArgumentException("Failed to generate code for augment in " + parentUsesNode);
+        }
+
+        final GroupingDefinition grouping = (GroupingDefinition) targetGrouping;
+        SchemaNode result = grouping;
+        for (final QName node : targetPath.getPathFromRoot()) {
+            // finding by local name is valid, grouping cannot contain nodes
+            // with same name and different namespace
+            if (result instanceof DataNodeContainer) {
+                result = ((DataNodeContainer) result).getDataChildByName(node.getLocalName());
+            } else if (result instanceof ChoiceSchemaNode) {
+                result = ((ChoiceSchemaNode) result).getCaseNodeByName(node.getLocalName());
+            }
+        }
+        if (result == null) {
+            return null;
+        }
+
+        boolean fromUses = ((DataSchemaNode) result).isAddedByUses();
+        final Iterator<UsesNode> groupingUses = grouping.getUses().iterator();
+        while (groupingUses.hasNext() && fromUses) {
+            result = findOriginalTargetFromGrouping(targetPath, groupingUses.next());
+            if (result != null) {
+                fromUses = ((DataSchemaNode) result).isAddedByUses();
+            }
+        }
+        if (fromUses) {
+            // this indicates invalid yang and thus possible bug in code because
+            // invalid yang should be already spotted by parser
+            throw new IllegalStateException("Failed to generate code for augment in " + parentUsesNode);
+        }
+
+        return (DataSchemaNode) result;
+    }
+
+    /**
+     * Returns a generated type builder for an augmentation.
+     *
+     * The name of the type builder is equal to the name of augmented node with
+     * serial number as suffix.
+     *
+     * @param module
+     *            current module
+     * @param augmentPackageName
+     *            string with contains the package name to which the augment
+     *            belongs
+     * @param basePackageName
+     *            string with the package name to which the augmented node
+     *            belongs
+     * @param targetTypeRef
+     *            target type
+     * @param augSchema
+     *            augmentation schema which contains data about the child nodes
+     *            and uses of augment
+     * @return generated type builder for augment
+     */
+    private GeneratedTypeBuilder addRawAugmentGenTypeDefinition(final Module module, final String augmentPackageName,
+            final String basePackageName, final Type targetTypeRef, final AugmentationSchema augSchema) {
+        Map<String, GeneratedTypeBuilder> augmentBuilders = genTypeBuilders.get(augmentPackageName);
+        if (augmentBuilders == null) {
+            augmentBuilders = new HashMap<>();
+            genTypeBuilders.put(augmentPackageName, augmentBuilders);
+        }
+        final String augIdentifier = getAugmentIdentifier(augSchema.getUnknownSchemaNodes());
+
+        String augTypeName;
+        if (augIdentifier != null) {
+            augTypeName = BindingMapping.getClassName(augIdentifier);
+        } else {
+            augTypeName = augGenTypeName(augmentBuilders, targetTypeRef.getName());
+        }
+
+        final GeneratedTypeBuilder augTypeBuilder = new GeneratedTypeBuilderImpl(augmentPackageName, augTypeName);
+
+        augTypeBuilder.addImplementsType(DATA_OBJECT);
+        augTypeBuilder.addImplementsType(Types.augmentationTypeFor(targetTypeRef));
+        addImplementedInterfaceFromUses(augSchema, augTypeBuilder);
+
+        augSchemaNodeToMethods(module, basePackageName, augTypeBuilder, augTypeBuilder, augSchema.getChildNodes());
+        augmentBuilders.put(augTypeName, augTypeBuilder);
+
+        if(!augSchema.getChildNodes().isEmpty()) {
+            genCtx.get(module).addTargetToAugmentation(targetTypeRef, augTypeBuilder);
+            genCtx.get(module).addTypeToAugmentation(augTypeBuilder, augSchema);
+
+        }
+        genCtx.get(module).addAugmentType(augTypeBuilder);
+        return augTypeBuilder;
+    }
+
+    /**
+     *
+     * @param unknownSchemaNodes
+     * @return nodeParameter of UnknownSchemaNode
+     */
+    private static String getAugmentIdentifier(final List<UnknownSchemaNode> unknownSchemaNodes) {
+        for (final UnknownSchemaNode unknownSchemaNode : unknownSchemaNodes) {
+            final QName nodeType = unknownSchemaNode.getNodeType();
+            if (AUGMENT_IDENTIFIER_NAME.equals(nodeType.getLocalName())
+                    && YANG_EXT_NAMESPACE.equals(nodeType.getNamespace().toString())) {
+                return unknownSchemaNode.getNodeParameter();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns first unique name for the augment generated type builder. The
+     * generated type builder name for augment consists from name of augmented
+     * node and serial number of its augmentation.
+     *
+     * @param builders
+     *            map of builders which were created in the package to which the
+     *            augmentation belongs
+     * @param genTypeName
+     *            string with name of augmented node
+     * @return string with unique name for augmentation builder
+     */
+    private static String augGenTypeName(final Map<String, GeneratedTypeBuilder> builders, final String genTypeName) {
+        int index = 1;
+        if (builders != null) {
+            while (builders.containsKey(genTypeName + index)) {
+                index = index + 1;
+            }
+        }
+        return genTypeName + index;
+    }
+
+    /**
+     * Adds the methods to <code>typeBuilder</code> which represent subnodes of
+     * node for which <code>typeBuilder</code> was created.
+     *
+     * The subnodes aren't mapped to the methods if they are part of grouping or
+     * augment (in this case are already part of them).
+     *
+     * @param module
+     *            current module
+     * @param basePackageName
+     *            string contains the module package name
+     * @param parent
+     *            generated type builder which represents any node. The subnodes
+     *            of this node are added to the <code>typeBuilder</code> as
+     *            methods. The subnode can be of type leaf, leaf-list, list,
+     *            container, choice.
+     * @param childOf
+     *            parent type
+     * @param schemaNodes
+     *            set of data schema nodes which are the children of the node
+     *            for which <code>typeBuilder</code> was created
+     * @return generated type builder which is the same builder as input
+     *         parameter. The getter methods (representing child nodes) could be
+     *         added to it.
+     */
+    private GeneratedTypeBuilder resolveDataSchemaNodes(final Module module, final String basePackageName,
+            final GeneratedTypeBuilder parent, final GeneratedTypeBuilder childOf, final Iterable<DataSchemaNode> schemaNodes) {
+        if (schemaNodes != null && parent != null) {
+            for (final DataSchemaNode schemaNode : schemaNodes) {
+                if (!schemaNode.isAugmenting() && !schemaNode.isAddedByUses()) {
+                    addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, parent, childOf, module);
+                }
+            }
+        }
+        return parent;
+    }
+
+    /**
+     * Adds the methods to <code>typeBuilder</code> what represents subnodes of
+     * node for which <code>typeBuilder</code> was created.
+     *
+     * @param module
+     *            current module
+     * @param basePackageName
+     *            string contains the module package name
+     * @param typeBuilder
+     *            generated type builder which represents any node. The subnodes
+     *            of this node are added to the <code>typeBuilder</code> as
+     *            methods. The subnode can be of type leaf, leaf-list, list,
+     *            container, choice.
+     * @param childOf
+     *            parent type
+     * @param schemaNodes
+     *            set of data schema nodes which are the children of the node
+     *            for which <code>typeBuilder</code> was created
+     * @return generated type builder which is the same object as the input
+     *         parameter <code>typeBuilder</code>. The getter method could be
+     *         added to it.
+     */
+    private GeneratedTypeBuilder augSchemaNodeToMethods(final Module module, final String basePackageName,
+            final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf,
+            final Iterable<DataSchemaNode> schemaNodes) {
+        if ((schemaNodes != null) && (typeBuilder != null)) {
+            for (final DataSchemaNode schemaNode : schemaNodes) {
+                if (!schemaNode.isAugmenting()) {
+                    addSchemaNodeToBuilderAsMethod(basePackageName, schemaNode, typeBuilder, childOf, module);
+                }
+            }
+        }
+        return typeBuilder;
+    }
+
+    /**
+     * Adds to <code>typeBuilder</code> a method which is derived from
+     * <code>schemaNode</code>.
+     *
+     * @param basePackageName
+     *            string with the module package name
+     * @param node
+     *            data schema node which is added to <code>typeBuilder</code> as
+     *            a method
+     * @param typeBuilder
+     *            generated type builder to which is <code>schemaNode</code>
+     *            added as a method.
+     * @param childOf
+     *            parent type
+     * @param module
+     *            current module
+     */
+    private void addSchemaNodeToBuilderAsMethod(final String basePackageName, final DataSchemaNode node,
+            final GeneratedTypeBuilder typeBuilder, final GeneratedTypeBuilder childOf, final Module module) {
+        if (node != null && typeBuilder != null) {
+            if (node instanceof LeafSchemaNode) {
+                resolveLeafSchemaNodeAsMethod(typeBuilder, (LeafSchemaNode) node, module);
+            } else if (node instanceof LeafListSchemaNode) {
+                resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) node,module);
+            } else if (node instanceof ContainerSchemaNode) {
+                containerToGenType(module, basePackageName, typeBuilder, childOf, (ContainerSchemaNode) node);
+            } else if (node instanceof ListSchemaNode) {
+                listToGenType(module, basePackageName, typeBuilder, childOf, (ListSchemaNode) node);
+            } else if (node instanceof ChoiceSchemaNode) {
+                choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceSchemaNode) node);
+            } else {
+                // TODO: anyxml not yet supported
+                LOG.debug("Unable to add schema node {} as method in {}: unsupported type of node.", node.getClass(),
+                        typeBuilder.getFullyQualifiedName());
+            }
+        }
+    }
+
+    /**
+     * Converts <code>choiceNode</code> to the list of generated types for
+     * choice and its cases.
+     *
+     * The package names for choice and for its cases are created as
+     * concatenation of the module package (<code>basePackageName</code>) and
+     * names of all parents node.
+     *
+     * @param module
+     *            current module
+     * @param basePackageName
+     *            string with the module package name
+     * @param parent
+     *            parent type
+     * @param choiceNode
+     *            choice node which is mapped to generated type. Also child
+     *            nodes - cases are mapped to generated types.
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>basePackageName</code> is null</li>
+     *             <li>if <code>choiceNode</code> is null</li>
+     *             </ul>
+     */
+    private void choiceToGeneratedType(final Module module, final String basePackageName,
+            final GeneratedTypeBuilder parent, final ChoiceSchemaNode choiceNode) {
+        checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
+        checkArgument(choiceNode != null, "Choice Schema Node cannot be NULL.");
+
+        if (!choiceNode.isAddedByUses()) {
+            final String packageName = packageNameForGeneratedType(basePackageName, choiceNode.getPath());
+            final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(packageName, choiceNode);
+            constructGetter(parent, choiceNode.getQName().getLocalName(), choiceNode.getDescription(),
+                    choiceTypeBuilder);
+            choiceTypeBuilder.addImplementsType(typeForClass(DataContainer.class));
+            genCtx.get(module).addChildNodeType(choiceNode, choiceTypeBuilder);
+            generateTypesFromChoiceCases(module, basePackageName, choiceTypeBuilder.toInstance(), choiceNode);
+        }
+    }
+
+    /**
+     * Converts <code>caseNodes</code> set to list of corresponding generated
+     * types.
+     *
+     * For every <i>case</i> which isn't added through augment or <i>uses</i> is
+     * created generated type builder. The package names for the builder is
+     * created as concatenation of the module package (
+     * <code>basePackageName</code>) and names of all parents nodes of the
+     * concrete <i>case</i>. There is also relation "<i>implements type</i>"
+     * between every case builder and <i>choice</i> type
+     *
+     * @param module
+     *            current module
+     * @param basePackageName
+     *            string with the module package name
+     * @param refChoiceType
+     *            type which represents superior <i>case</i>
+     * @param choiceNode
+     *            choice case node which is mapped to generated type
+     * @return list of generated types for <code>caseNodes</code>.
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>basePackageName</code> equals null</li>
+     *             <li>if <code>refChoiceType</code> equals null</li>
+     *             <li>if <code>caseNodes</code> equals null</li>
+     *             </ul>
+     */
+    private void generateTypesFromChoiceCases(final Module module, final String basePackageName,
+            final Type refChoiceType, final ChoiceSchemaNode choiceNode) {
+        checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
+        checkArgument(refChoiceType != null, "Referenced Choice Type cannot be NULL.");
+        checkArgument(choiceNode != null, "ChoiceNode cannot be NULL.");
+
+        final Set<ChoiceCaseNode> caseNodes = choiceNode.getCases();
+        if (caseNodes == null) {
+            return;
+        }
+
+        for (final ChoiceCaseNode caseNode : caseNodes) {
+            if (caseNode != null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {
+                final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
+                final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module);
+                caseTypeBuilder.addImplementsType(refChoiceType);
+                genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
+                genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
+                final Iterable<DataSchemaNode> caseChildNodes = caseNode.getChildNodes();
+                if (caseChildNodes != null) {
+                    final SchemaPath choiceNodeParentPath = choiceNode.getPath().getParent();
+
+                    if (!Iterables.isEmpty(choiceNodeParentPath.getPathFromRoot())) {
+                        SchemaNode parent = findDataSchemaNode(schemaContext, choiceNodeParentPath);
+
+                        if (parent instanceof AugmentationSchema) {
+                            final AugmentationSchema augSchema = (AugmentationSchema) parent;
+                            final SchemaPath targetPath = augSchema.getTargetPath();
+                            SchemaNode targetSchemaNode = findDataSchemaNode(schemaContext, targetPath);
+                            if (targetSchemaNode instanceof DataSchemaNode
+                                    && ((DataSchemaNode) targetSchemaNode).isAddedByUses()) {
+                                if (targetSchemaNode instanceof DerivableSchemaNode) {
+                                    targetSchemaNode = ((DerivableSchemaNode) targetSchemaNode).getOriginal().orNull();
+                                }
+                                if (targetSchemaNode == null) {
+                                    throw new IllegalStateException(
+                                            "Failed to find target node from grouping for augmentation " + augSchema
+                                                    + " in module " + module.getName());
+                                }
+                            }
+                            parent = targetSchemaNode;
+                        }
+
+                        Preconditions.checkState(parent != null, "Could not find Choice node parent %s",
+                                choiceNodeParentPath);
+                        GeneratedTypeBuilder childOfType = findChildNodeByPath(parent.getPath());
+                        if (childOfType == null) {
+                            childOfType = findGroupingByPath(parent.getPath());
+                        }
+                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, caseChildNodes);
+                    } else {
+                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, moduleToDataType(module),
+                                caseChildNodes);
+                    }
+               }
+            }
+            processUsesAugments(caseNode, module);
+        }
+    }
+
+    /**
+     * Generates list of generated types for all the cases of a choice which are
+     * added to the choice through the augment.
+     *
+     * @param module
+     *            current module
+     * @param basePackageName
+     *            string contains name of package to which augment belongs. If
+     *            an augmented choice is from an other package (pcg1) than an
+     *            augmenting choice (pcg2) then case's of the augmenting choice
+     *            will belong to pcg2.
+     * @param targetType
+     *            Type which represents target choice
+     * @param targetNode
+     *            node which represents target choice
+     * @param augmentedNodes
+     *            set of choice case nodes for which is checked if are/aren't
+     *            added to choice through augmentation
+     * @return list of generated types which represents augmented cases of
+     *         choice <code>refChoiceType</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>basePackageName</code> is null</li>
+     *             <li>if <code>targetType</code> is null</li>
+     *             <li>if <code>augmentedNodes</code> is null</li>
+     *             </ul>
+     */
+    private void generateTypesFromAugmentedChoiceCases(final Module module, final String basePackageName,
+            final Type targetType, final ChoiceSchemaNode targetNode, final Iterable<DataSchemaNode> augmentedNodes) {
+        checkArgument(basePackageName != null, "Base Package Name cannot be NULL.");
+        checkArgument(targetType != null, "Referenced Choice Type cannot be NULL.");
+        checkArgument(augmentedNodes != null, "Set of Choice Case Nodes cannot be NULL.");
+
+        for (final DataSchemaNode caseNode : augmentedNodes) {
+            if (caseNode != null) {
+                final String packageName = packageNameForGeneratedType(basePackageName, caseNode.getPath());
+                final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode, module);
+                caseTypeBuilder.addImplementsType(targetType);
+
+                SchemaNode parent = null;
+                final SchemaPath nodeSp = targetNode.getPath();
+                parent = findDataSchemaNode(schemaContext, nodeSp.getParent());
+
+                GeneratedTypeBuilder childOfType = null;
+                if (parent instanceof Module) {
+                    childOfType = genCtx.get(parent).getModuleNode();
+                } else if (parent instanceof ChoiceCaseNode) {
+                    childOfType = findCaseByPath(parent.getPath());
+                } else if (parent instanceof DataSchemaNode || parent instanceof NotificationDefinition) {
+                    childOfType = findChildNodeByPath(parent.getPath());
+                } else if (parent instanceof GroupingDefinition) {
+                    childOfType = findGroupingByPath(parent.getPath());
+                }
+
+                if (childOfType == null) {
+                    throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
+                }
+
+                ChoiceCaseNode node = null;
+                if (caseNode instanceof ChoiceCaseNode) {
+                    node = (ChoiceCaseNode) caseNode;
+                } else {
+                    node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName());
+                }
+                final Iterable<DataSchemaNode> childNodes = node.getChildNodes();
+                if (childNodes != null) {
+                    resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
+                }
+                genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
+                genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder, node);
+            }
+        }
+    }
+
+    /**
+     * Converts <code>leaf</code> to the getter method which is added to
+     * <code>typeBuilder</code>.
+     *
+     * @param typeBuilder
+     *            generated type builder to which is added getter method as
+     *            <code>leaf</code> mapping
+     * @param leaf
+     *            leaf schema node which is mapped as getter method which is
+     *            added to <code>typeBuilder</code>
+     * @param module
+     *            Module in which type was defined
+     * @return boolean value
+     *         <ul>
+     *         <li>false - if <code>leaf</code> or <code>typeBuilder</code> are
+     *         null</li>
+     *         <li>true - in other cases</li>
+     *         </ul>
+     */
+    private Type resolveLeafSchemaNodeAsMethod(final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf, final Module module) {
+        Type returnType = null;
+        if ((leaf != null) && (typeBuilder != null)) {
+            final String leafName = leaf.getQName().getLocalName();
+            String leafDesc = leaf.getDescription();
+            if (leafDesc == null) {
+                leafDesc = "";
+            }
+
+            final Module parentModule = findParentModule(schemaContext, leaf);
+            if (leafName != null && !leaf.isAddedByUses()) {
+                final TypeDefinition<?> typeDef = leaf.getType();
+
+                GeneratedTOBuilder genTOBuilder;
+                if (typeDef instanceof EnumTypeDefinition) {
+                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
+                    final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
+                    final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(),
+                            typeBuilder,module);
+
+                    if (enumBuilder != null) {
+                        returnType = enumBuilder.toInstance(typeBuilder);
+                    }
+                    ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
+                } else if (typeDef instanceof UnionType) {
+                    genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule);
+                    if (genTOBuilder != null) {
+                        returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
+                    }
+                } else if (typeDef instanceof BitsTypeDefinition) {
+                    genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule);
+                    if (genTOBuilder != null) {
+                        returnType = genTOBuilder.toInstance();
+                    }
+                } else {
+                    final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions);
+                }
+                if (returnType != null) {
+                    final MethodSignatureBuilder getter = constructGetter(typeBuilder, leafName, leafDesc, returnType);
+                    processContextRefExtension(leaf, getter, parentModule);
+                }
+            }
+        }
+        return returnType;
+    }
+
+    private void processContextRefExtension(final LeafSchemaNode leaf, final MethodSignatureBuilder getter,
+            final Module module) {
+        for (final UnknownSchemaNode node : leaf.getUnknownSchemaNodes()) {
+            final QName nodeType = node.getNodeType();
+            if ("context-reference".equals(nodeType.getLocalName())) {
+                final String nodeParam = node.getNodeParameter();
+                IdentitySchemaNode identity = null;
+                String basePackageName = null;
+                final Iterable<String> splittedElement = COLON_SPLITTER.split(nodeParam);
+                final Iterator<String> iterator = splittedElement.iterator();
+                final int length = Iterables.size(splittedElement);
+                if (length == 1) {
+                    identity = findIdentityByName(module.getIdentities(), iterator.next());
+                    basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+                } else if (length == 2) {
+                    final String prefix = iterator.next();
+                    final Module dependentModule = findModuleFromImports(module.getImports(), prefix);
+                    if (dependentModule == null) {
+                        throw new IllegalArgumentException("Failed to process context-reference: unknown prefix "
+                                + prefix);
+                    }
+                    identity = findIdentityByName(dependentModule.getIdentities(), iterator.next());
+                    basePackageName = BindingMapping.getRootPackageName(dependentModule.getQNameModule());
+                } else {
+                    throw new IllegalArgumentException("Failed to process context-reference: unknown identity "
+                            + nodeParam);
+                }
+                if (identity == null) {
+                    throw new IllegalArgumentException("Failed to process context-reference: unknown identity "
+                            + nodeParam);
+                }
+
+                final Class<RoutingContext> clazz = RoutingContext.class;
+                final AnnotationTypeBuilder rc = getter.addAnnotation(clazz.getPackage().getName(),
+                        clazz.getSimpleName());
+                final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
+                final String genTypeName = BindingMapping.getClassName(identity.getQName().getLocalName());
+                rc.addParameter("value", packageName + "." + genTypeName + ".class");
+            }
+        }
+    }
+
+    private static IdentitySchemaNode findIdentityByName(final Set<IdentitySchemaNode> identities, final String name) {
+        for (final IdentitySchemaNode id : identities) {
+            if (id.getQName().getLocalName().equals(name)) {
+                return id;
+            }
+        }
+        return null;
+    }
+
+    private Module findModuleFromImports(final Set<ModuleImport> imports, final String prefix) {
+        for (final ModuleImport imp : imports) {
+            if (imp.getPrefix().equals(prefix)) {
+                return schemaContext.findModuleByName(imp.getModuleName(), imp.getRevision());
+            }
+        }
+        return null;
+    }
+
+    private boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf,
+            final boolean isReadOnly, final Module module) {
+        if ((leaf != null) && (toBuilder != null)) {
+            final String leafName = leaf.getQName().getLocalName();
+            String leafDesc = leaf.getDescription();
+            if (leafDesc == null) {
+                leafDesc = "";
+            }
+            Type returnType = null;
+            final TypeDefinition<?> typeDef = leaf.getType();
+            if (typeDef instanceof UnionTypeDefinition) {
+                // GeneratedType for this type definition should be already
+                // created
+                final QName qname = typeDef.getQName();
+                final Module unionModule = schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
+                        qname.getRevision());
+                final ModuleContext mc = genCtx.get(unionModule);
+                returnType = mc.getTypedefs().get(typeDef.getPath());
+            } else if (typeDef instanceof EnumTypeDefinition && BaseTypes.ENUMERATION_QNAME.equals(typeDef.getQName())) {
+                // Annonymous enumeration (already generated, since it is inherited via uses).
+                LeafSchemaNode originalLeaf = (LeafSchemaNode) SchemaNodeUtils.getRootOriginalIfPossible(leaf);
+                QName qname = originalLeaf.getQName();
+                final Module enumModule =  schemaContext.findModuleByNamespaceAndRevision(qname.getNamespace(),
+                        qname.getRevision());
+                returnType = genCtx.get(enumModule).getInnerType(originalLeaf.getType().getPath());
+            } else {
+                returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf);
+            }
+            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 static boolean resolveLeafSchemaNodeAsProperty(final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf,
+            final Type returnType, final boolean isReadOnly) {
+        if (returnType == null) {
+            return false;
+        }
+        final String leafName = leaf.getQName().getLocalName();
+        final String leafDesc = leaf.getDescription();
+        final GeneratedPropertyBuilder propBuilder = toBuilder.addProperty(BindingMapping.getPropertyName(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>.
+     *
+     * @param typeBuilder
+     *            generated type builder to which is <code>node</code> added as
+     *            getter method
+     * @param node
+     *            leaf list schema node which is added to
+     *            <code>typeBuilder</code> as getter method
+     * @param module
+     * @return boolean value
+     *         <ul>
+     *         <li>true - if <code>node</code>, <code>typeBuilder</code>,
+     *         nodeName equal null or <code>node</code> is added by <i>uses</i></li>
+     *         <li>false - other cases</li>
+     *         </ul>
+     */
+    private boolean resolveLeafListSchemaNode(final GeneratedTypeBuilder typeBuilder, final LeafListSchemaNode node, final Module module) {
+        if ((node != null) && (typeBuilder != null)) {
+            final QName nodeName = node.getQName();
+
+            if (nodeName != null && !node.isAddedByUses()) {
+                final TypeDefinition<?> typeDef = node.getType();
+                final Module parentModule = findParentModule(schemaContext, node);
+
+                Type returnType = null;
+                if (typeDef instanceof EnumTypeDefinition) {
+                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node);
+                    final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
+                    final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName,
+                            typeBuilder,module);
+                    returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName());
+                    ((TypeProviderImpl) typeProvider).putReferencedType(node.getPath(), returnType);
+                } else if (typeDef instanceof UnionType) {
+                    final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule);
+                    if (genTOBuilder != null) {
+                        returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule);
+                    }
+                } else if (typeDef instanceof BitsTypeDefinition) {
+                    final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule);
+                    returnType = genTOBuilder.toInstance();
+                } else {
+                    final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+                    returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions);
+                }
+
+                final ParameterizedType listType = Types.listTypeFor(returnType);
+                constructGetter(typeBuilder, nodeName.getLocalName(), node.getDescription(), listType);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Type createReturnTypeForUnion(final GeneratedTOBuilder genTOBuilder, final TypeDefinition<?> typeDef,
+            final GeneratedTypeBuilder typeBuilder, final Module parentModule) {
+        final GeneratedTOBuilderImpl returnType = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
+                genTOBuilder.getName());
+
+        returnType.setDescription(typeDef.getDescription());
+        returnType.setReference(typeDef.getReference());
+        returnType.setSchemaPath(typeDef.getPath().getPathFromRoot());
+        returnType.setModuleName(parentModule.getName());
+
+        genTOBuilder.setTypedef(true);
+        genTOBuilder.setIsUnion(true);
+        ((TypeProviderImpl) typeProvider).addUnitsToGenTO(genTOBuilder, typeDef.getUnits());
+
+
+
+        final GeneratedTOBuilder unionBuilder = createUnionBuilder(genTOBuilder,typeBuilder);
+
+
+        final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
+        method.setReturnType(returnType);
+        method.addParameter(Types.STRING, "defaultValue");
+        method.setAccessModifier(AccessModifier.PUBLIC);
+        method.setStatic(true);
+
+        final Set<Type> types = ((TypeProviderImpl) typeProvider).getAdditionalTypes().get(parentModule);
+        if (types == null) {
+            ((TypeProviderImpl) typeProvider).getAdditionalTypes().put(parentModule,
+                    Sets.<Type> newHashSet(unionBuilder.toInstance()));
+        } else {
+            types.add(unionBuilder.toInstance());
+        }
+        return returnType.toInstance();
+    }
+
+    private static GeneratedTOBuilder createUnionBuilder(final GeneratedTOBuilder genTOBuilder, final GeneratedTypeBuilder typeBuilder) {
+        final String outerCls = Types.getOuterClassName(genTOBuilder);
+        final StringBuilder name;
+        if (outerCls != null) {
+            name = new StringBuilder(outerCls);
+        } else {
+            name = new StringBuilder();
+        }
+        name.append(genTOBuilder.getName());
+        name.append("Builder");
+        final GeneratedTOBuilderImpl unionBuilder = new GeneratedTOBuilderImpl(typeBuilder.getPackageName(),name.toString());
+        unionBuilder.setIsUnionBuilder(true);
+        return unionBuilder;
+    }
+
+    private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
+            final Module module) {
+        return addDefaultInterfaceDefinition(packageName, schemaNode, null, module);
+    }
+
+    /**
+     * Instantiates generated type builder with <code>packageName</code> and
+     * <code>schemaNode</code>.
+     *
+     * The new builder always implements
+     * {@link org.opendaylight.yangtools.yang.binding.DataObject DataObject}.<br>
+     * If <code>schemaNode</code> is instance of GroupingDefinition it also
+     * implements {@link org.opendaylight.yangtools.yang.binding.Augmentable
+     * Augmentable}.<br>
+     * If <code>schemaNode</code> is instance of
+     * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer
+     * DataNodeContainer} it can also implement nodes which are specified in
+     * <i>uses</i>.
+     *
+     * @param packageName
+     *            string with the name of the package to which
+     *            <code>schemaNode</code> belongs.
+     * @param schemaNode
+     *            schema node for which is created generated type builder
+     * @param parent
+     *            parent type (can be null)
+     * @return generated type builder <code>schemaNode</code>
+     */
+    private GeneratedTypeBuilder addDefaultInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
+            final Type parent, final Module module) {
+        final GeneratedTypeBuilder it = addRawInterfaceDefinition(packageName, schemaNode, "");
+        if (parent == null) {
+            it.addImplementsType(DATA_OBJECT);
+        } else {
+            it.addImplementsType(BindingTypes.childOf(parent));
+        }
+        if (!(schemaNode instanceof GroupingDefinition)) {
+            it.addImplementsType(augmentable(it));
+        }
+
+        if (schemaNode instanceof DataNodeContainer) {
+            groupingsToGenTypes(module, ((DataNodeContainer) schemaNode).getGroupings());
+            addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it);
+        }
+
+        return it;
+    }
+
+    /**
+     * Wraps the calling of the same overloaded method.
+     *
+     * @param packageName
+     *            string with the package name to which returning generated type
+     *            builder belongs
+     * @param schemaNode
+     *            schema node which provide data about the schema node name
+     * @return generated type builder for <code>schemaNode</code>
+     */
+    private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode) {
+        return addRawInterfaceDefinition(packageName, schemaNode, "");
+    }
+
+    /**
+     * Returns reference to generated type builder for specified
+     * <code>schemaNode</code> with <code>packageName</code>.
+     *
+     * Firstly the generated type builder is searched in
+     * {@link BindingGeneratorImpl#genTypeBuilders genTypeBuilders}. If it isn't
+     * found it is created and added to <code>genTypeBuilders</code>.
+     *
+     * @param packageName
+     *            string with the package name to which returning generated type
+     *            builder belongs
+     * @param schemaNode
+     *            schema node which provide data about the schema node name
+     * @param prefix
+     *            return type name prefix
+     * @return generated type builder for <code>schemaNode</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>schemaNode</code> is null</li>
+     *             <li>if <code>packageName</code> is null</li>
+     *             <li>if QName of schema node is null</li>
+     *             <li>if schemaNode name is null</li>
+     *             </ul>
+     *
+     */
+    private GeneratedTypeBuilder addRawInterfaceDefinition(final String packageName, final SchemaNode schemaNode,
+            final String prefix) {
+        checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
+        checkArgument(packageName != null, "Package Name for Generated Type cannot be NULL.");
+        checkArgument(schemaNode.getQName() != null, "QName for Data Schema Node cannot be NULL.");
+        final String schemaNodeName = schemaNode.getQName().getLocalName();
+        checkArgument(schemaNodeName != null, "Local Name of QName for Data Schema Node cannot be NULL.");
+
+        String genTypeName;
+        if (prefix == null) {
+            genTypeName = BindingMapping.getClassName(schemaNodeName);
+        } else {
+            genTypeName = prefix + BindingMapping.getClassName(schemaNodeName);
+        }
+
+        // FIXME: Validation of name conflict
+        final GeneratedTypeBuilderImpl newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
+        final Module module = findParentModule(schemaContext, schemaNode);
+        qnameConstant(newType, BindingMapping.QNAME_STATIC_FIELD_NAME, schemaNode.getQName());
+        newType.addComment(schemaNode.getDescription());
+        newType.setDescription(createDescription(schemaNode, newType.getFullyQualifiedName()));
+        newType.setReference(schemaNode.getReference());
+        newType.setSchemaPath(schemaNode.getPath().getPathFromRoot());
+        newType.setModuleName(module.getName());
+
+        if (!genTypeBuilders.containsKey(packageName)) {
+            final Map<String, GeneratedTypeBuilder> builders = new HashMap<>();
+            builders.put(genTypeName, newType);
+            genTypeBuilders.put(packageName, builders);
+        } else {
+            final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders.get(packageName);
+            if (!builders.containsKey(genTypeName)) {
+                builders.put(genTypeName, newType);
+            }
+        }
+        return newType;
+    }
+
+    /**
+     * Creates the name of the getter method name from <code>localName</code>.
+     *
+     * @param localName
+     *            string with the name of the getter method
+     * @param returnType
+     *            return type
+     * @return string with the name of the getter method for
+     *         <code>methodName</code> in JAVA method format
+     */
+    public static String getterMethodName(final String localName, final Type returnType) {
+        final StringBuilder method = new StringBuilder();
+        if (BOOLEAN.equals(returnType)) {
+            method.append("is");
+        } else {
+            method.append("get");
+        }
+        final String name = BindingMapping.toFirstUpper(BindingMapping.getPropertyName(localName));
+        method.append(name);
+        return method.toString();
+    }
+
+    /**
+     * Created a method signature builder as part of
+     * <code>interfaceBuilder</code>.
+     *
+     * The method signature builder is created for the getter method of
+     * <code>schemaNodeName</code>. Also <code>comment</code> and
+     * <code>returnType</code> information are added to the builder.
+     *
+     * @param interfaceBuilder
+     *            generated type builder for which the getter method should be
+     *            created
+     * @param schemaNodeName
+     *            string with schema node name. The name will be the part of the
+     *            getter method name.
+     * @param comment
+     *            string with comment for the getter method
+     * @param returnType
+     *            type which represents the return type of the getter method
+     * @return method signature builder which represents the getter method of
+     *         <code>interfaceBuilder</code>
+     */
+    private static MethodSignatureBuilder constructGetter(final GeneratedTypeBuilder interfaceBuilder,
+            final String schemaNodeName, final String comment, final Type returnType) {
+        final MethodSignatureBuilder getMethod = interfaceBuilder
+                .addMethod(getterMethodName(schemaNodeName, returnType));
+        getMethod.setComment(comment);
+        getMethod.setReturnType(returnType);
+        return getMethod;
+    }
+
+    /**
+     * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method
+     * or to <code>genTOBuilder</code> as property.
+     *
+     * @param basePackageName
+     *            string contains the module package name
+     * @param schemaNode
+     *            data schema node which should be added as getter method to
+     *            <code>typeBuilder</code> or as a property to
+     *            <code>genTOBuilder</code> if is part of the list key
+     * @param typeBuilder
+     *            generated type builder for the list schema node
+     * @param genTOBuilder
+     *            generated TO builder for the list keys
+     * @param listKeys
+     *            list of string which contains names of the list keys
+     * @param module
+     *            current module
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>schemaNode</code> equals null</li>
+     *             <li>if <code>typeBuilder</code> equals null</li>
+     *             </ul>
+     */
+    private void addSchemaNodeToListBuilders(final String basePackageName, final DataSchemaNode schemaNode,
+            final GeneratedTypeBuilder typeBuilder, final GeneratedTOBuilder genTOBuilder, final List<String> listKeys,
+            final Module module) {
+        checkArgument(schemaNode != null, "Data Schema Node cannot be NULL.");
+        checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
+
+        if (schemaNode instanceof LeafSchemaNode) {
+            final LeafSchemaNode leaf = (LeafSchemaNode) schemaNode;
+            final String leafName = leaf.getQName().getLocalName();
+            final Type type = resolveLeafSchemaNodeAsMethod(typeBuilder, leaf,module);
+            if (listKeys.contains(leafName)) {
+                if (type == null) {
+                    resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true, module);
+                } else {
+                    resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, type, true);
+                }
+            }
+        } else if (!schemaNode.isAddedByUses()) {
+            if (schemaNode instanceof LeafListSchemaNode) {
+                resolveLeafListSchemaNode(typeBuilder, (LeafListSchemaNode) schemaNode, module);
+            } else if (schemaNode instanceof ContainerSchemaNode) {
+                containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode);
+            } else if (schemaNode instanceof ChoiceSchemaNode) {
+                choiceToGeneratedType(module, basePackageName, typeBuilder, (ChoiceSchemaNode) schemaNode);
+            } else if (schemaNode instanceof ListSchemaNode) {
+                listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode);
+            }
+        }
+    }
+
+    private void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder,
+            final GeneratedTOBuilder genTOBuilder) {
+        checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
+
+        if (genTOBuilder != null) {
+            final GeneratedTransferObject genTO = genTOBuilder.toInstance();
+            constructGetter(typeBuilder, "key", "Returns Primary Key of Yang List Type", genTO);
+            genCtx.get(module).addGeneratedTOBuilder(genTOBuilder);
+        }
+    }
+
+    /**
+     * Selects the names of the list keys from <code>list</code> and returns
+     * them as the list of the strings
+     *
+     * @param list
+     *            of string with names of the list keys
+     * @return list of string which represents names of the list keys. If the
+     *         <code>list</code> contains no keys then the empty list is
+     *         returned.
+     */
+    private static List<String> listKeys(final ListSchemaNode list) {
+        final List<String> listKeys = new ArrayList<>();
+
+        final List<QName> keyDefinition = list.getKeyDefinition();
+        if (keyDefinition != null) {
+            for (final QName keyDef : keyDefinition) {
+                listKeys.add(keyDef.getLocalName());
+            }
+        }
+        return listKeys;
+    }
+
+    /**
+     * Generates for the <code>list</code> which contains any list keys special
+     * generated TO builder.
+     *
+     * @param packageName
+     *            string with package name to which the list belongs
+     * @param list
+     *            list schema node which is source of data about the list name
+     * @return generated TO builder which represents the keys of the
+     *         <code>list</code> or null if <code>list</code> is null or list of
+     *         key definitions is null or empty.
+     */
+    private static GeneratedTOBuilder resolveListKeyTOBuilder(final String packageName, final ListSchemaNode list) {
+        GeneratedTOBuilder genTOBuilder = null;
+        if ((list.getKeyDefinition() != null) && (!list.getKeyDefinition().isEmpty())) {
+            final String listName = list.getQName().getLocalName() + "Key";
+            final String genTOName = BindingMapping.getClassName(listName);
+            genTOBuilder = new GeneratedTOBuilderImpl(packageName, genTOName);
+        }
+        return genTOBuilder;
+    }
+
+    /**
+     * Builds generated TO builders for <code>typeDef</code> of type
+     * {@link org.opendaylight.yangtools.yang.model.util.UnionType UnionType} or
+     * {@link org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
+     * BitsTypeDefinition} which are also added to <code>typeBuilder</code> as
+     * enclosing transfer object.
+     *
+     * If more then one generated TO builder is created for enclosing then all
+     * of the generated TO builders are added to <code>typeBuilder</code> as
+     * enclosing transfer objects.
+     *
+     * @param typeDef
+     *            type definition which can be of type <code>UnionType</code> or
+     *            <code>BitsTypeDefinition</code>
+     * @param typeBuilder
+     *            generated type builder to which is added generated TO created
+     *            from <code>typeDef</code>
+     * @param leafName
+     *            string with name for generated TO builder
+     * @param leaf
+     * @return generated TO builder for <code>typeDef</code>
+     */
+    private GeneratedTOBuilder addTOToTypeBuilder(final TypeDefinition<?> typeDef,
+            final GeneratedTypeBuilder typeBuilder, final DataSchemaNode leaf, final Module parentModule) {
+        final String classNameFromLeaf = BindingMapping.getClassName(leaf.getQName());
+        final List<GeneratedTOBuilder> genTOBuilders = new ArrayList<>();
+        final String packageName = typeBuilder.getFullyQualifiedName();
+        if (typeDef instanceof UnionTypeDefinition) {
+            final List<GeneratedTOBuilder> types = ((TypeProviderImpl) typeProvider)
+                    .provideGeneratedTOBuildersForUnionTypeDef(packageName, ((UnionTypeDefinition) typeDef),
+                            classNameFromLeaf, leaf);
+            genTOBuilders.addAll(types);
+
+            GeneratedTOBuilder resultTOBuilder = null;
+            if (types.isEmpty()) {
+                throw new IllegalStateException("No GeneratedTOBuilder objects generated from union " + typeDef);
+            }
+            resultTOBuilder = types.remove(0);
+            for (final GeneratedTOBuilder genTOBuilder : types) {
+                resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
+            }
+
+            final GeneratedPropertyBuilder genPropBuilder = resultTOBuilder.addProperty("value");
+            genPropBuilder.setReturnType(Types.CHAR_ARRAY);
+            resultTOBuilder.addEqualsIdentity(genPropBuilder);
+            resultTOBuilder.addHashIdentity(genPropBuilder);
+            resultTOBuilder.addToStringProperty(genPropBuilder);
+
+        } else if (typeDef instanceof BitsTypeDefinition) {
+            genTOBuilders.add((((TypeProviderImpl) typeProvider)).provideGeneratedTOBuilderForBitsTypeDefinition(
+                    packageName, typeDef, classNameFromLeaf, parentModule.getName()));
+        }
+        if (genTOBuilders != null && !genTOBuilders.isEmpty()) {
+            for (final GeneratedTOBuilder genTOBuilder : genTOBuilders) {
+                typeBuilder.addEnclosingTransferObject(genTOBuilder);
+            }
+            return genTOBuilders.get(0);
+        }
+        return null;
+
+    }
+
+    /**
+     * Adds the implemented types to type builder.
+     *
+     * The method passes through the list of <i>uses</i> in
+     * {@code dataNodeContainer}. For every <i>use</i> is obtained corresponding
+     * generated type from {@link BindingGeneratorImpl#allGroupings
+     * allGroupings} which is added as <i>implements type</i> to
+     * <code>builder</code>
+     *
+     * @param dataNodeContainer
+     *            element which contains the list of used YANG groupings
+     * @param builder
+     *            builder to which are added implemented types according to
+     *            <code>dataNodeContainer</code>
+     * @return generated type builder with all implemented types
+     */
+    private GeneratedTypeBuilder addImplementedInterfaceFromUses(final DataNodeContainer dataNodeContainer,
+            final GeneratedTypeBuilder builder) {
+        for (final UsesNode usesNode : dataNodeContainer.getUses()) {
+            if (usesNode.getGroupingPath() != null) {
+                final GeneratedType genType = findGroupingByPath(usesNode.getGroupingPath()).toInstance();
+                if (genType == null) {
+                    throw new IllegalStateException("Grouping " + usesNode.getGroupingPath() + "is not resolved for "
+                            + builder.getName());
+                }
+
+                builder.addImplementsType(genType);
+                /*
+                builder.addComment(genType.getDescription());
+                builder.setDescription(genType.getDescription());
+                builder.setModuleName(genType.getModuleName());
+                builder.setReference(genType.getReference());
+                builder.setSchemaPath(genType.getSchemaPath());
+                */
+            }
+        }
+        return builder;
+    }
+
+    private static boolean isNullOrEmpty(final Collection<?> list) {
+        return list == null || list.isEmpty();
+    }
+
+    private String createDescription(final Set<? extends SchemaNode> schemaNodes, final String moduleName, final String moduleSourcePath) {
+        final StringBuilder sb = new StringBuilder();
+
+        if (!isNullOrEmpty(schemaNodes)) {
+            final SchemaNode node = schemaNodes.iterator().next();
+
+            if (node instanceof RpcDefinition) {
+                sb.append("Interface for implementing the following YANG RPCs defined in module <b>" + moduleName + "</b>");
+            } else if (node instanceof NotificationDefinition) {
+                sb.append("Interface for receiving the following YANG notifications defined in module <b>" + moduleName + "</b>");
+            }
+        }
+        sb.append(NEW_LINE);
+        sb.append("<br>(Source path: <i>");
+        sb.append(moduleSourcePath);
+        sb.append("</i>):");
+        sb.append(NEW_LINE);
+
+        if (verboseClassComments) {
+            sb.append("<pre>");
+            sb.append(NEW_LINE);
+            sb.append(YangTemplate.generateYangSnipet(schemaNodes));
+            sb.append("</pre>");
+            sb.append(NEW_LINE);
+        }
+
+        return replaceAllIllegalChars(sb);
+    }
+
+    private String createDescription(final SchemaNode schemaNode, final String fullyQualifiedName) {
+        final StringBuilder sb = new StringBuilder();
+        final String formattedDescription = YangTemplate.formatToParagraph(schemaNode.getDescription(), 0);
+
+        if (!Strings.isNullOrEmpty(formattedDescription)) {
+            sb.append(formattedDescription);
+            sb.append(NEW_LINE);
+        }
+
+        if (verboseClassComments) {
+            final Module module = findParentModule(schemaContext, schemaNode);
+            final StringBuilder linkToBuilderClass = new StringBuilder();
+            final String[] namespace = Iterables.toArray(BSDOT_SPLITTER.split(fullyQualifiedName), String.class);
+            final String className = namespace[namespace.length - 1];
+
+            if (hasBuilderClass(schemaNode)) {
+                linkToBuilderClass.append(className);
+                linkToBuilderClass.append("Builder");
+            }
+
+            sb.append("<p>");
+            sb.append("This class represents the following YANG schema fragment defined in module <b>");
+            sb.append(module.getName());
+            sb.append("</b>");
+            sb.append(NEW_LINE);
+            sb.append("<br>(Source path: <i>");
+            sb.append(module.getModuleSourcePath());
+            sb.append("</i>):");
+            sb.append(NEW_LINE);
+            sb.append("<pre>");
+            sb.append(NEW_LINE);
+            sb.append(YangTemplate.generateYangSnipet(schemaNode));
+            sb.append("</pre>");
+            sb.append(NEW_LINE);
+            sb.append("The schema path to identify an instance is");
+            sb.append(NEW_LINE);
+            sb.append("<i>");
+            sb.append(YangTemplate.formatSchemaPath(module.getName(), schemaNode.getPath().getPathFromRoot()));
+            sb.append("</i>");
+            sb.append(NEW_LINE);
+
+            if (hasBuilderClass(schemaNode)) {
+                sb.append(NEW_LINE);
+                sb.append("<p>To create instances of this class use " + "{@link " + linkToBuilderClass + "}.");
+                sb.append(NEW_LINE);
+                sb.append("@see ");
+                sb.append(linkToBuilderClass);
+                sb.append(NEW_LINE);
+                if (schemaNode instanceof ListSchemaNode) {
+                    final List<QName> keyDef = ((ListSchemaNode)schemaNode).getKeyDefinition();
+                    if (keyDef != null && !keyDef.isEmpty()) {
+                        sb.append("@see ");
+                        sb.append(className);
+                        sb.append("Key");
+                    }
+                   sb.append(NEW_LINE);
+                }
+            }
+        }
+
+        return replaceAllIllegalChars(sb);
+    }
+
+    private static boolean hasBuilderClass(final SchemaNode schemaNode) {
+        if (schemaNode instanceof ContainerSchemaNode || schemaNode instanceof ListSchemaNode ||
+                schemaNode instanceof RpcDefinition || schemaNode instanceof NotificationDefinition) {
+            return true;
+        }
+        return false;
+    }
+
+    private String createDescription(final Module module) {
+        final StringBuilder sb = new StringBuilder();
+        final String formattedDescription = YangTemplate.formatToParagraph(module.getDescription(), 0);
+
+        if (!Strings.isNullOrEmpty(formattedDescription)) {
+            sb.append(formattedDescription);
+            sb.append(NEW_LINE);
+        }
+
+        if (verboseClassComments) {
+            sb.append("<p>");
+            sb.append("This class represents the following YANG schema fragment defined in module <b>");
+            sb.append(module.getName());
+            sb.append("</b>");
+            sb.append(NEW_LINE);
+            sb.append("<br>Source path: <i>");
+            sb.append(module.getModuleSourcePath());
+            sb.append("</i>):");
+            sb.append(NEW_LINE);
+            sb.append("<pre>");
+            sb.append(NEW_LINE);
+            sb.append(YangTemplate.generateYangSnipet(module));
+            sb.append("</pre>");
+        }
+
+        return replaceAllIllegalChars(sb);
+    }
+
+    private GeneratedTypeBuilder findChildNodeByPath(final SchemaPath path) {
+        for (final ModuleContext ctx : genCtx.values()) {
+            final GeneratedTypeBuilder result = ctx.getChildNode(path);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    private GeneratedTypeBuilder findGroupingByPath(final SchemaPath path) {
+        for (final ModuleContext ctx : genCtx.values()) {
+            final GeneratedTypeBuilder result = ctx.getGrouping(path);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    private GeneratedTypeBuilder findCaseByPath(final SchemaPath path) {
+        for (final ModuleContext ctx : genCtx.values()) {
+            final GeneratedTypeBuilder result = ctx.getCase(path);
+            if (result != null) {
+                return result;
+            }
+        }
+        return null;
+    }
+
+    public Map<Module, ModuleContext> getModuleContexts() {
+        return genCtx;
+    }
+
+    @VisibleForTesting
+    static String replaceAllIllegalChars(final StringBuilder stringBuilder){
+        return UNICODE_CHAR_PATTERN.matcher(stringBuilder).replaceAll("\\\\\\\\u");
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingSchemaContextUtils.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingSchemaContextUtils.java
new file mode 100644 (file)
index 0000000..a43cf39
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2014, 2015 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.sal.binding.generator.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+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.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
+
+public final class BindingSchemaContextUtils {
+
+    private BindingSchemaContextUtils() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
+    // FIXME: THis method does not search in case augmentations.
+    public static Optional<DataNodeContainer> findDataNodeContainer(final SchemaContext ctx,
+            final InstanceIdentifier<?> path) {
+        Iterator<PathArgument> pathArguments = path.getPathArguments().iterator();
+        PathArgument currentArg = pathArguments.next();
+        Preconditions.checkArgument(currentArg != null);
+        QName currentQName = BindingReflections.findQName(currentArg.getType());
+
+        Optional<DataNodeContainer> currentContainer = Optional.absent();
+        if (BindingReflections.isNotification(currentArg.getType())) {
+            currentContainer = findNotification(ctx, currentQName);
+        } else if (BindingReflections.isRpcType(currentArg.getType())) {
+            currentContainer = findFirstDataNodeContainerInRpc(ctx, currentArg.getType());
+            if(currentQName == null && currentContainer.isPresent()) {
+                currentQName = ((DataSchemaNode) currentContainer.get()).getQName();
+            }
+        } else {
+            currentContainer = findDataNodeContainer(ctx, currentQName);
+        }
+
+        while (currentContainer.isPresent() && pathArguments.hasNext()) {
+            currentArg = pathArguments.next();
+            if (Augmentation.class.isAssignableFrom(currentArg.getType())) {
+                currentQName = BindingReflections.findQName(currentArg.getType());
+                if(pathArguments.hasNext()) {
+                    currentArg = pathArguments.next();
+                } else {
+                    return currentContainer;
+                }
+            }
+            if(ChildOf.class.isAssignableFrom(currentArg.getType()) && BindingReflections.isAugmentationChild(currentArg.getType())) {
+                currentQName = BindingReflections.findQName(currentArg.getType());
+            } else {
+                currentQName = QName.create(currentQName, BindingReflections.findQName(currentArg.getType()).getLocalName());
+            }
+            Optional<DataNodeContainer> potential = findDataNodeContainer(currentContainer.get(), currentQName);
+            if (potential.isPresent()) {
+                currentContainer = potential;
+            } else {
+                return Optional.absent();
+            }
+        }
+        return currentContainer;
+    }
+
+    private static Optional<DataNodeContainer> findNotification(final SchemaContext ctx, final QName notificationQName) {
+        for (NotificationDefinition notification : ctx.getNotifications()) {
+            if (notification.getQName().equals(notificationQName)) {
+                return Optional.<DataNodeContainer> of(notification);
+            }
+        }
+        return Optional.absent();
+    }
+
+    private static Optional<DataNodeContainer> findDataNodeContainer(final DataNodeContainer ctx,
+            final QName targetQName) {
+
+        for (DataSchemaNode child : ctx.getChildNodes()) {
+            if (child instanceof ChoiceSchemaNode) {
+                DataNodeContainer potential = findInCases(((ChoiceSchemaNode) child), targetQName);
+                if (potential != null) {
+                    return Optional.of(potential);
+                }
+            } else if (child instanceof DataNodeContainer && child.getQName().equals(targetQName)) {
+                return Optional.of((DataNodeContainer) child);
+            } else if (child instanceof DataNodeContainer //
+                    && child.isAddedByUses() //
+                    && child.getQName().getLocalName().equals(targetQName.getLocalName())) {
+                return Optional.of((DataNodeContainer) child);
+            }
+
+        }
+        return Optional.absent();
+    }
+
+    private static DataNodeContainer findInCases(final ChoiceSchemaNode choiceNode, final QName targetQName) {
+        for (ChoiceCaseNode caze : choiceNode.getCases()) {
+            Optional<DataNodeContainer> potential = findDataNodeContainer(caze, targetQName);
+            if (potential.isPresent()) {
+                return potential.get();
+            }
+        }
+        return null;
+    }
+
+    private static Optional<DataNodeContainer> findFirstDataNodeContainerInRpc(final SchemaContext ctx,
+            final Class<? extends DataObject> targetType) {
+        final YangModuleInfo moduleInfo;
+        try {
+            moduleInfo = BindingReflections.getModuleInfo(targetType);
+        } catch (Exception e) {
+            throw new IllegalArgumentException(
+                    String.format("Failed to load module information for class %s", targetType), e);
+        }
+
+        for(RpcDefinition rpc : ctx.getOperations()) {
+            String rpcNamespace = rpc.getQName().getNamespace().toString();
+            String rpcRevision = rpc.getQName().getFormattedRevision();
+            if(moduleInfo.getNamespace().equals(rpcNamespace) && moduleInfo.getRevision().equals(rpcRevision)) {
+                Optional<DataNodeContainer> potential = findInputOutput(rpc,targetType.getSimpleName());
+                if(potential.isPresent()) {
+                    return potential;
+                }
+            }
+        }
+        return Optional.absent();
+    }
+
+    private static Optional<DataNodeContainer> findInputOutput(final RpcDefinition rpc, final String targetType) {
+        String rpcName = BindingMapping.getClassName(rpc.getQName());
+        String rpcInputName = rpcName + BindingMapping.RPC_INPUT_SUFFIX;
+        String rpcOutputName = rpcName + BindingMapping.RPC_OUTPUT_SUFFIX;
+        if(targetType.equals(rpcInputName)) {
+            return Optional.<DataNodeContainer>of(rpc.getInput());
+        } else if (targetType.equals(rpcOutputName)) {
+            return Optional.<DataNodeContainer>of(rpc.getOutput());
+        }
+       return Optional.absent();
+    }
+
+    public static Set<AugmentationSchema> collectAllAugmentationDefinitions(final SchemaContext currentSchema, final AugmentationTarget ctxNode) {
+        HashSet<AugmentationSchema> augmentations = new HashSet<>();
+        augmentations.addAll(ctxNode.getAvailableAugmentations());
+        if(ctxNode instanceof DataSchemaNode && ((DataSchemaNode) ctxNode).isAddedByUses()) {
+
+            System.out.println(ctxNode);
+
+        }
+
+        // TODO Auto-generated method stub
+        return augmentations;
+    }
+
+    public static Optional<ChoiceSchemaNode> findInstantiatedChoice(final DataNodeContainer parent, final Class<?> choiceClass) {
+        return findInstantiatedChoice(parent, BindingReflections.findQName(choiceClass));
+    }
+
+    public static Optional<ChoiceSchemaNode> findInstantiatedChoice(final DataNodeContainer ctxNode, final QName choiceName) {
+        DataSchemaNode potential = ctxNode.getDataChildByName(choiceName);
+        if (potential == null) {
+            potential = ctxNode.getDataChildByName(choiceName.getLocalName());
+        }
+
+        if (potential instanceof ChoiceSchemaNode) {
+            return Optional.of((ChoiceSchemaNode) potential);
+        }
+
+        return Optional.absent();
+    }
+
+    public static Optional<ChoiceCaseNode> findInstantiatedCase(final ChoiceSchemaNode instantiatedChoice, final ChoiceCaseNode originalDefinition) {
+        ChoiceCaseNode potential = instantiatedChoice.getCaseNodeByName(originalDefinition.getQName());
+        if(originalDefinition.equals(potential)) {
+            return Optional.of(potential);
+        }
+        if (potential != null) {
+            SchemaNode potentialRoot = SchemaNodeUtils.getRootOriginalIfPossible(potential);
+            if (originalDefinition.equals(potentialRoot)) {
+                return Optional.of(potential);
+            }
+        }
+        // We try to find case by name, then lookup its root definition
+        // and compare it with original definition
+        // This solves case, if choice was inside grouping
+        // which was used in different module and thus namespaces are
+        // different, but local names are still same.
+        //
+        // Still we need to check equality of definition, because local name is not
+        // sufficient to uniquelly determine equality of cases
+        //
+        potential = instantiatedChoice.getCaseNodeByName(originalDefinition.getQName().getLocalName());
+        if(potential != null && (originalDefinition.equals(SchemaNodeUtils.getRootOriginalIfPossible(potential)))) {
+            return Optional.of(potential);
+        }
+        return Optional.absent();
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/CodecTypeUtils.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/CodecTypeUtils.java
new file mode 100644 (file)
index 0000000..447dbdc
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+
+public final class CodecTypeUtils {
+
+    private CodecTypeUtils() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
+    @SuppressWarnings({"unchecked","rawtypes"})
+    public static IdentifiableItem<?, ?> newIdentifiableItem(Class<?> type, Object key) {
+        Class<? extends Identifiable<?>> identifiableType = (Class<? extends Identifiable<?>>) type;
+        Identifier<? extends Identifiable<?>> identifier = (Identifier<? extends Identifiable<?>>) key;
+        return new IdentifiableItem(identifiableType,identifier);
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedClassLoadingStrategy.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedClassLoadingStrategy.java
new file mode 100644 (file)
index 0000000..d8f3b73
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
+
+public abstract class GeneratedClassLoadingStrategy implements ClassLoadingStrategy {
+
+    private static final GeneratedClassLoadingStrategy TCCL_STRATEGY = new TCCLClassLoadingStrategy();
+
+    private static final GeneratedClassLoadingStrategy ALWAYS_FAIL_STRATEGY = new GeneratedClassLoadingStrategy() {
+        @Override
+        public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
+            throw new ClassNotFoundException(fullyQualifiedName);
+        }
+    };
+
+    @Override
+    public Class<?> loadClass(final Type type) throws ClassNotFoundException {
+        return loadClass(type.getFullyQualifiedName());
+    }
+
+    @Override
+    public abstract Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException;
+
+    public static final GeneratedClassLoadingStrategy getTCCLClassLoadingStrategy() {
+        return TCCL_STRATEGY;
+    }
+
+    public static final GeneratedClassLoadingStrategy getAlwaysFailClassLoadingStrategy() {
+        return ALWAYS_FAIL_STRATEGY;
+    }
+
+    private static final class TCCLClassLoadingStrategy extends GeneratedClassLoadingStrategy {
+        @Override
+        public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
+            return ClassLoaderUtils.loadClassWithTCCL(fullyQualifiedName);
+        }
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/ModuleContext.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/ModuleContext.java
new file mode 100644 (file)
index 0000000..aac2135
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+public final class ModuleContext {
+    private GeneratedTypeBuilder moduleNode;
+    private final List<GeneratedTOBuilder> genTOs = new ArrayList<GeneratedTOBuilder>();
+    private final Map<SchemaPath, Type> typedefs = new HashMap<SchemaPath, Type>();
+    private final Map<SchemaPath, GeneratedTypeBuilder> childNodes = new HashMap<SchemaPath, GeneratedTypeBuilder>();
+    private final Map<SchemaPath, GeneratedTypeBuilder> groupings = new HashMap<SchemaPath, GeneratedTypeBuilder>();
+    private final Map<SchemaPath, GeneratedTypeBuilder> cases = new HashMap<SchemaPath, GeneratedTypeBuilder>();
+    private final Map<QName,GeneratedTOBuilder> identities = new HashMap<>();
+    private final Set<GeneratedTypeBuilder> topLevelNodes = new HashSet<GeneratedTypeBuilder>();
+    private final List<GeneratedTypeBuilder> augmentations = new ArrayList<GeneratedTypeBuilder>();
+    private final BiMap<Type,AugmentationSchema> typeToAugmentation = HashBiMap.create();
+
+    private final Map<Type,Object> typeToSchema = new HashMap<>();
+
+
+    private final Multimap<Type, Type> choiceToCases = HashMultimap.create();
+    private final BiMap<Type,ChoiceCaseNode> caseTypeToSchema = HashBiMap.create();
+
+    private final Multimap<Type, Type> augmentableToAugmentations = HashMultimap.create();
+    private final Map<SchemaPath, Type> innerTypes = new HashMap<>();
+
+    List<Type> getGeneratedTypes() {
+        List<Type> result = new ArrayList<>();
+
+        if (moduleNode != null) {
+            result.add(moduleNode.toInstance());
+        }
+
+        for (GeneratedTOBuilder b : genTOs) {
+            result.add(b.toInstance());
+        }
+        for (Type b : typedefs.values()) {
+            if (b != null) {
+                result.add(b);
+            }
+        }
+        for (GeneratedTypeBuilder b : childNodes.values()) {
+            result.add(b.toInstance());
+        }
+        for (GeneratedTypeBuilder b : groupings.values()) {
+            result.add(b.toInstance());
+        }
+        for (GeneratedTypeBuilder b : cases.values()) {
+            result.add(b.toInstance());
+        }
+        for (GeneratedTOBuilder b : identities.values()) {
+            result.add(b.toInstance());
+        }
+        for (GeneratedTypeBuilder b : topLevelNodes) {
+            result.add(b.toInstance());
+        }
+        for (GeneratedTypeBuilder b : augmentations) {
+            result.add(b.toInstance());
+        }
+        return result;
+    }
+
+    public Multimap<Type, Type> getChoiceToCases() {
+        return Multimaps.unmodifiableMultimap(choiceToCases);
+    }
+
+    public Multimap<Type, Type> getAugmentableToAugmentations() {
+        return Multimaps.unmodifiableMultimap(augmentableToAugmentations);
+    }
+
+    public GeneratedTypeBuilder getModuleNode() {
+        return moduleNode;
+    }
+
+    public GeneratedTypeBuilder getChildNode(final SchemaPath p) {
+        return childNodes.get(p);
+    }
+
+    public GeneratedTypeBuilder getGrouping(final SchemaPath p) {
+        return groupings.get(p);
+    }
+
+    public GeneratedTypeBuilder getCase(final SchemaPath p) {
+        return cases.get(p);
+    }
+
+    public void addModuleNode(final GeneratedTypeBuilder moduleNode) {
+        this.moduleNode = moduleNode;
+    }
+
+    public void addGeneratedTOBuilder(final GeneratedTOBuilder b) {
+        genTOs.add(b);
+    }
+
+    public void addChildNodeType(final SchemaNode p, final GeneratedTypeBuilder b) {
+        childNodes.put(p.getPath(), b);
+        typeToSchema.put(b,p);
+    }
+
+    public void addGroupingType(final SchemaPath p, final GeneratedTypeBuilder b) {
+        groupings.put(p, b);
+    }
+
+    public void addTypedefType(final SchemaPath p, final Type t) {
+        typedefs.put(p, t);
+    }
+
+    public void addCaseType(final SchemaPath p, final GeneratedTypeBuilder b) {
+        cases.put(p, b);
+    }
+
+    public void addIdentityType(final QName name,final GeneratedTOBuilder b) {
+        identities.put(name,b);
+    }
+
+    public void addTopLevelNodeType(final GeneratedTypeBuilder b) {
+        topLevelNodes.add(b);
+    }
+
+    public void addAugmentType(final GeneratedTypeBuilder b) {
+        augmentations.add(b);
+    }
+
+    public Map<SchemaPath, Type> getTypedefs() {
+        return typedefs;
+    }
+
+    public Map<SchemaPath, GeneratedTypeBuilder> getChildNodes() {
+        return Collections.unmodifiableMap(childNodes);
+    }
+
+    public Map<SchemaPath, GeneratedTypeBuilder> getGroupings() {
+        return Collections.unmodifiableMap(groupings);
+    }
+
+    public Map<SchemaPath, GeneratedTypeBuilder> getCases() {
+        return Collections.unmodifiableMap(cases);
+    }
+
+    public Map<QName,GeneratedTOBuilder> getIdentities() {
+        return Collections.unmodifiableMap(identities);
+    }
+
+    public Set<GeneratedTypeBuilder> getTopLevelNodes() {
+        return Collections.unmodifiableSet(topLevelNodes);
+    }
+
+    public List<GeneratedTypeBuilder> getAugmentations() {
+        return Collections.unmodifiableList(augmentations);
+    }
+
+    public BiMap<Type, AugmentationSchema> getTypeToAugmentation() {
+        return Maps.unmodifiableBiMap(typeToAugmentation);
+    }
+
+    public void addTypeToAugmentation(final GeneratedTypeBuilder builder, final AugmentationSchema schema) {
+            typeToAugmentation.put(builder, schema);
+            typeToSchema.put(builder, schema);
+    }
+
+    public void addTargetToAugmentation(final Type target, final GeneratedTypeBuilder augmentation) {
+        augmentableToAugmentations.put(target,augmentation);
+    }
+
+    public void addChoiceToCaseMapping(final Type choiceType, final Type caseType, final ChoiceCaseNode schema) {
+        choiceToCases.put(choiceType, caseType);
+        caseTypeToSchema.put(caseType, schema);
+        typeToSchema.put(caseType, schema);
+    }
+
+    public BiMap<Type, ChoiceCaseNode> getCaseTypeToSchemas() {
+        return Maps.unmodifiableBiMap(caseTypeToSchema);
+    }
+
+    /**
+     *
+     * Returns mapping of type to its schema.
+     *
+     * Valid values are only instances of {@link DataSchemaNode} or {@link AugmentationSchema}
+     *
+     * @return
+     */
+    public Map<Type, Object> getTypeToSchema() {
+        return Collections.unmodifiableMap(typeToSchema);
+    }
+
+    protected void addTypeToSchema(Type type, TypeDefinition<?> typedef) {
+        typeToSchema.put(type, typedef);
+    }
+
+    /**
+     * Adds mapping between schema path and inner enum.
+     *
+     * @param path
+     * @param enumBuilder
+     */
+    void addInnerTypedefType(SchemaPath path, EnumBuilder enumBuilder) {
+        innerTypes.put(path, enumBuilder);
+    }
+
+    public Type getInnerType(SchemaPath path) {
+        return innerTypes.get(path);
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/ModuleInfoBackedContext.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/ModuleInfoBackedContext.java
new file mode 100644 (file)
index 0000000..b20a170
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import org.opendaylight.yangtools.concepts.AbstractObjectRegistration;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ModuleInfoBackedContext extends GeneratedClassLoadingStrategy //
+        implements //
+        ModuleInfoRegistry, SchemaContextProvider {
+
+    private ModuleInfoBackedContext(final ClassLoadingStrategy loadingStrategy) {
+        this.backingLoadingStrategy = loadingStrategy;
+    }
+
+    public static ModuleInfoBackedContext create() {
+        return new ModuleInfoBackedContext(getTCCLClassLoadingStrategy());
+    }
+
+    public static ModuleInfoBackedContext create(final ClassLoadingStrategy loadingStrategy) {
+        return new ModuleInfoBackedContext(loadingStrategy);
+    }
+
+    private static final Logger LOG = LoggerFactory.getLogger(ModuleInfoBackedContext.class);
+
+    private final ConcurrentMap<String, WeakReference<ClassLoader>> packageNameToClassLoader = new ConcurrentHashMap<>();
+    private final ConcurrentMap<SourceIdentifier, YangModuleInfo> sourceIdentifierToModuleInfo = new ConcurrentHashMap<>();
+
+    private final ClassLoadingStrategy backingLoadingStrategy;
+
+    @Override
+    public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
+        String modulePackageName = BindingReflections.getModelRootPackageName(fullyQualifiedName);
+
+        WeakReference<ClassLoader> classLoaderRef = packageNameToClassLoader.get(modulePackageName);
+        ClassLoader classloader = null;
+        if (classLoaderRef != null && (classloader = classLoaderRef.get()) != null) {
+            return ClassLoaderUtils.loadClass(classloader, fullyQualifiedName);
+        }
+        if (backingLoadingStrategy == null) {
+            throw new ClassNotFoundException(fullyQualifiedName);
+        }
+        Class<?> cls = backingLoadingStrategy.loadClass(fullyQualifiedName);
+        if (BindingReflections.isBindingClass(cls)) {
+            boolean newModule = resolveModuleInfo(cls);
+            if (newModule) {
+                recreateSchemaContext();
+            }
+        }
+        return cls;
+    }
+
+
+    private synchronized Optional<SchemaContext> recreateSchemaContext() {
+        try {
+            ImmutableList<InputStream> streams = getAvailableStreams();
+            YangParserImpl parser = new YangParserImpl();
+            Set<Module> modules = parser.parseYangModelsFromStreams(streams);
+            SchemaContext schemaContext = parser.resolveSchemaContext(modules);
+            return Optional.of(schemaContext);
+        } catch (IOException e) {
+            LOG.error("Schema was not recreated.",e);
+        }
+        return Optional.absent();
+    }
+
+    // TODO finish schema parsing and expose as SchemaService
+    // Unite with current SchemaService
+    // Implement remove ModuleInfo to update SchemaContext
+
+    public synchronized Optional<SchemaContext> tryToCreateSchemaContext() {
+        return recreateSchemaContext();
+    }
+
+    private ImmutableList<InputStream> getAvailableStreams() throws IOException {
+        ImmutableSet<YangModuleInfo> moduleInfos = ImmutableSet.copyOf(sourceIdentifierToModuleInfo.values());
+
+        ImmutableList.Builder<InputStream> sourceStreams = ImmutableList.<InputStream> builder();
+        for (YangModuleInfo moduleInfo : moduleInfos) {
+            sourceStreams.add(moduleInfo.getModuleSourceStream());
+        }
+        return sourceStreams.build();
+    }
+
+    private boolean resolveModuleInfo(final Class<?> cls) {
+        try {
+            return resolveModuleInfo(BindingReflections.getModuleInfo(cls));
+        } catch (Exception e) {
+            throw new IllegalStateException(String.format("Failed to resolve module information for class %s", cls), e);
+        }
+    }
+
+    private boolean resolveModuleInfo(final YangModuleInfo moduleInfo) {
+
+        SourceIdentifier identifier = sourceIdentifierFrom(moduleInfo);
+        YangModuleInfo previous = sourceIdentifierToModuleInfo.putIfAbsent(identifier, moduleInfo);
+        ClassLoader moduleClassLoader = moduleInfo.getClass().getClassLoader();
+        if (previous == null) {
+            String modulePackageName = moduleInfo.getClass().getPackage().getName();
+            packageNameToClassLoader.putIfAbsent(modulePackageName, new WeakReference<ClassLoader>(moduleClassLoader));
+
+            for (YangModuleInfo importedInfo : moduleInfo.getImportedModules()) {
+                resolveModuleInfo(importedInfo);
+            }
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    private static SourceIdentifier sourceIdentifierFrom(final YangModuleInfo moduleInfo) {
+        return SourceIdentifier.create(moduleInfo.getName(), Optional.of(moduleInfo.getRevision()));
+    }
+
+    public void addModuleInfos(final Iterable<? extends YangModuleInfo> moduleInfos) {
+        for (YangModuleInfo yangModuleInfo : moduleInfos) {
+            registerModuleInfo(yangModuleInfo);
+        }
+    }
+
+    @Override
+    public ObjectRegistration<YangModuleInfo> registerModuleInfo(final YangModuleInfo yangModuleInfo) {
+        YangModuleInfoRegistration registration = new YangModuleInfoRegistration(yangModuleInfo, this);
+
+        resolveModuleInfo(yangModuleInfo);
+
+        return registration;
+    }
+
+    private static class YangModuleInfoRegistration extends AbstractObjectRegistration<YangModuleInfo> {
+
+        private final ModuleInfoBackedContext context;
+
+        public YangModuleInfoRegistration(final YangModuleInfo instance, final ModuleInfoBackedContext context) {
+            super(instance);
+            this.context = context;
+        }
+
+        @Override
+        protected void removeRegistration() {
+            context.remove(this);
+        }
+
+    }
+
+    private void remove(final YangModuleInfoRegistration registration) {
+        // FIXME implement
+    }
+
+    @Override
+    public SchemaContext getSchemaContext() {
+        final Optional<SchemaContext> contextOptional = tryToCreateSchemaContext();
+        if (contextOptional.isPresent()) {
+            return contextOptional.get();
+
+        }
+        throw new IllegalStateException("Unable to recreate SchemaContext, error while parsing");
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/SchemaLock.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/SchemaLock.java
new file mode 100644 (file)
index 0000000..4633a22
--- /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
+ */
+package org.opendaylight.yangtools.sal.binding.generator.impl;
+
+interface SchemaLock {
+    void waitForSchema(Class<?> cls);
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGeneratorException.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGeneratorException.java
new file mode 100644 (file)
index 0000000..1b160f0
--- /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.sal.binding.generator.impl;
+
+final class TransformerGeneratorException extends RuntimeException {
+    private static final long serialVersionUID = 1L;
+
+    public TransformerGeneratorException(final String message, final Throwable cause) {
+        super(message, cause);
+    }
+
+    public static TransformerGeneratorException wrap(final Class<?> cls, final Throwable cause) throws TransformerGeneratorException {
+        return new TransformerGeneratorException(String.format("Failed to generate for type %s", cls), cause);
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/YangTemplate.xtend b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/YangTemplate.xtend
new file mode 100644 (file)
index 0000000..913d685
--- /dev/null
@@ -0,0 +1,803 @@
+/*
+ * 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.sal.binding.generator.impl
+
+import java.util.Collection
+import java.util.Date
+import java.util.List
+import java.util.Map
+import java.util.Set
+import java.util.StringTokenizer
+import org.opendaylight.yangtools.yang.common.QName
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode
+import org.opendaylight.yangtools.yang.model.api.Deviation
+import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition
+import org.opendaylight.yangtools.yang.model.api.FeatureDefinition
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode
+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.ModuleImport
+import org.opendaylight.yangtools.yang.model.api.NotificationDefinition
+import org.opendaylight.yangtools.yang.model.api.RpcDefinition
+import org.opendaylight.yangtools.yang.model.api.SchemaNode
+import org.opendaylight.yangtools.yang.model.api.SchemaPath
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode
+import org.opendaylight.yangtools.yang.model.api.UsesNode
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair
+import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil
+import com.google.common.base.CharMatcher
+
+class YangTemplate {
+
+    // FIXME: this is not thread-safe and seems to be unused!
+    private static var Module module = null
+
+    private static val CharMatcher NEWLINE_OR_TAB = CharMatcher.anyOf("\n\t")
+
+    def static String generateYangSnipet(SchemaNode schemaNode) {
+        if (schemaNode == null)
+            return ''
+
+        '''
+            Â«IF schemaNode instanceof DataSchemaNode»
+            Â«writeDataSchemaNode(schemaNode)»
+            Â«ENDIF»
+            Â«IF schemaNode instanceof EnumTypeDefinition.EnumPair»
+            Â«writeEnumPair(schemaNode)»
+            Â«ENDIF»
+            Â«IF schemaNode instanceof ExtensionDefinition»
+            Â«writeExtension(schemaNode)»
+            Â«ENDIF»
+            Â«IF schemaNode instanceof FeatureDefinition»
+            Â«writeFeature(schemaNode)»
+            Â«ENDIF»
+            Â«IF schemaNode instanceof GroupingDefinition»
+            Â«writeGroupingDef(schemaNode)»
+            Â«ENDIF»
+            Â«IF schemaNode instanceof IdentitySchemaNode»
+            Â«writeIdentity(schemaNode)»
+            Â«ENDIF»
+            Â«IF schemaNode instanceof NotificationDefinition»
+            Â«writeNotification(schemaNode)»
+            Â«ENDIF»
+            Â«IF schemaNode instanceof RpcDefinition»
+            Â«writeRPC(schemaNode)»
+            Â«ENDIF»
+            Â«IF schemaNode instanceof TypeDefinition<?>»
+            Â«writeTypeDefinition(schemaNode)»
+            Â«ENDIF»
+            Â«IF schemaNode instanceof UnknownSchemaNode»
+            Â«writeUnknownSchemaNode(schemaNode)»
+            Â«ENDIF»
+        '''
+    }
+    
+    def static String generateYangSnipet(Set<? extends SchemaNode> nodes) {
+        if (nodes.nullOrEmpty)
+            return ''
+        
+        '''
+            Â«FOR node : nodes»
+                Â«IF node instanceof NotificationDefinition»
+                Â«writeNotification(node)»
+                Â«ELSEIF node instanceof RpcDefinition»
+                Â«writeRPC(node as RpcDefinition)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeEnumPair(EnumPair pair) {
+        var boolean hasEnumPairValue = pair.value != null
+        '''
+            enum Â«pair.name»«IF !hasEnumPairValue»;«ELSE»{
+                value Â«pair.value»;
+            }
+            Â«ENDIF»
+        '''
+    }
+
+    def static String writeModuleImports(Set<ModuleImport> moduleImports) {
+        if (moduleImports.nullOrEmpty)
+            return ''
+
+        '''
+            Â«FOR moduleImport : moduleImports SEPARATOR "\n"»
+                Â«IF moduleImport != null && !moduleImport.moduleName.nullOrEmpty»
+                import Â«moduleImport.moduleName» { prefix "«moduleImport.prefix»"; }
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeRevision(Date moduleRevision, String moduleDescription) {
+        val revisionIndent = 12
+
+        '''
+            revision Â«SimpleDateFormatUtil.getRevisionFormat.format(moduleRevision)» {
+                description "«formatToParagraph(moduleDescription, revisionIndent)»";
+            }
+        '''
+    }
+
+    def static String generateYangSnipet(Module module) {
+
+        '''
+            module Â«module.name» {
+                yang-version Â«module.yangVersion»;
+                namespace "«module.QNameModule.namespace.toString»";
+                prefix "«module.prefix»";
+
+                Â«IF !module.imports.nullOrEmpty»
+                Â«writeModuleImports(module.imports)»
+                Â«ENDIF»
+                Â«IF module.revision != null»
+                Â«writeRevision(module.revision, module.description)»
+                Â«ENDIF»
+                Â«IF !module.childNodes.nullOrEmpty»
+
+                Â«writeDataSchemaNodes(module.childNodes)»
+                Â«ENDIF»
+                Â«IF !module.groupings.nullOrEmpty»
+
+                Â«writeGroupingDefs(module.groupings)»
+                Â«ENDIF»
+                Â«IF !module.augmentations.nullOrEmpty»
+
+                Â«writeAugments(module.augmentations)»
+                Â«ENDIF»
+                Â«IF !module.deviations.nullOrEmpty»
+
+                Â«writeDeviations(module.deviations)»
+                Â«ENDIF»
+                Â«IF !module.extensionSchemaNodes.nullOrEmpty»
+
+                Â«writeExtensions(module.extensionSchemaNodes)»
+                Â«ENDIF»
+                Â«IF !module.features.nullOrEmpty»
+
+                Â«writeFeatures(module.features)»
+                Â«ENDIF»
+                Â«IF !module.identities.nullOrEmpty»
+
+                Â«writeIdentities(module.identities)»
+                Â«ENDIF»
+                Â«IF !module.notifications.nullOrEmpty»
+
+                Â«writeNotifications(module.notifications)»
+                Â«ENDIF»
+                Â«IF !module.rpcs.nullOrEmpty»
+
+                Â«writeRPCs(module.rpcs)»
+                Â«ENDIF»
+                Â«IF !module.unknownSchemaNodes.nullOrEmpty»
+
+                Â«writeUnknownSchemaNodes(module.unknownSchemaNodes)»
+                Â«ENDIF»
+                Â«IF !module.uses.nullOrEmpty»
+
+                Â«writeUsesNodes(module.uses)»
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeRPCs(Set<RpcDefinition> rpcDefs) {
+        '''
+            Â«FOR rpc : rpcDefs»
+                Â«IF rpc != null»
+                Â«writeRPC(rpc)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeRPC(RpcDefinition rpc) {
+        '''
+            rpc Â«rpc.QName.localName» {
+                Â«IF !rpc.description.nullOrEmpty»
+                    "«rpc.description»";
+                Â«ENDIF»
+                Â«IF !rpc.groupings.nullOrEmpty»
+                    Â«writeGroupingDefs(rpc.groupings)»
+                Â«ENDIF»
+                Â«IF rpc.input != null»
+                    Â«writeRpcInput(rpc.input)»
+                Â«ENDIF»
+                Â«IF rpc.output != null»
+                    Â«writeRpcOutput(rpc.output)»
+                Â«ENDIF»
+                Â«IF !rpc.reference.nullOrEmpty»
+                reference
+                    "«rpc.reference»";
+                Â«ENDIF»
+                Â«IF rpc.status != null»
+                status Â«rpc.status»;
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeRpcInput(ContainerSchemaNode input) {
+        if(input == null)
+            return ''
+
+        '''
+            input {
+                Â«IF !input.childNodes.nullOrEmpty»
+                Â«writeDataSchemaNodes(input.childNodes)»
+                Â«ENDIF»
+            }
+
+        '''
+    }
+
+    def static writeRpcOutput(ContainerSchemaNode output) {
+        if(output == null)
+            return ''
+
+        '''
+            output {
+                Â«IF !output.childNodes.nullOrEmpty»
+                Â«writeDataSchemaNodes(output.childNodes)»
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeNotifications(Set<NotificationDefinition> notifications) {
+        '''
+            Â«FOR notification : notifications»
+                Â«IF notification != null»
+                Â«writeNotification(notification)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeNotification(NotificationDefinition notification) {
+        '''
+            notification Â«notification.QName.localName» {
+                Â«IF !notification.description.nullOrEmpty»
+                description
+                    "«notification.description»";
+                Â«ENDIF»
+                Â«IF !notification.childNodes.nullOrEmpty»
+                    Â«writeDataSchemaNodes(notification.childNodes)»
+                Â«ENDIF»
+                Â«IF !notification.availableAugmentations.nullOrEmpty»
+                    Â«writeAugments(notification.availableAugmentations)»
+                Â«ENDIF»
+                Â«IF !notification.groupings.nullOrEmpty»
+                    Â«writeGroupingDefs(notification.groupings)»
+                Â«ENDIF»
+                Â«IF !notification.uses.nullOrEmpty»
+                    Â«writeUsesNodes(notification.uses)»
+                Â«ENDIF»
+                Â«IF !notification.reference.nullOrEmpty»
+                reference
+                    "«notification.reference»";
+                Â«ENDIF»
+                Â«IF notification.status != null»
+                status Â«notification.status»;
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
+        if (unknownSchemaNodes.nullOrEmpty)
+            return ''
+
+        '''
+            Â«FOR unknownSchemaNode : unknownSchemaNodes»
+                Â«writeUnknownSchemaNode(unknownSchemaNode)»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeUnknownSchemaNode(UnknownSchemaNode unknownSchemaNode) {
+        if (unknownSchemaNode == null)
+            return ''
+
+        '''
+            anyxml Â«unknownSchemaNode.QName.localName» {
+                Â«IF !unknownSchemaNode.description.nullOrEmpty»
+                description
+                    "«unknownSchemaNode.description»";
+                Â«ENDIF»
+                Â«IF !unknownSchemaNode.reference.nullOrEmpty»
+                reference
+                    "«unknownSchemaNode.reference»";
+                Â«ENDIF»
+                Â«IF unknownSchemaNode.status != null»
+                status Â«unknownSchemaNode.status»;
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeUsesNodes(Set<UsesNode> usesNodes) {
+        if (usesNodes == null) {
+            return ''
+        }
+
+        '''
+            Â«FOR usesNode : usesNodes»
+                Â«IF usesNode != null»
+                Â«writeUsesNode(usesNode)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeUsesNode(UsesNode usesNode) {
+        val hasRefines = !usesNode.refines.empty
+
+        '''
+            uses Â«usesNode.groupingPath.pathFromRoot.head.localName»«IF !hasRefines»;«ELSE» {«ENDIF»
+            Â«IF hasRefines»
+                Â«writeRefines(usesNode.refines)»
+            }
+            Â«ENDIF»
+        '''
+    }
+
+    def static writeRefines(Map<SchemaPath, SchemaNode> refines) {
+        '''
+            Â«FOR path : refines.keySet»
+            Â«val schemaNode = refines.get(path)»
+            Â«writeRefine(path, schemaNode)»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeRefine(SchemaPath path, SchemaNode schemaNode) {
+        '''
+            refine Â«path.pathFromRoot.last» {
+                Â«IF schemaNode instanceof DataSchemaNode»
+                Â«writeDataSchemaNode(schemaNode)»
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
+        '''
+            Â«FOR typeDefinition : typeDefinitions»
+                Â«IF typeDefinition != null»
+                Â«writeTypeDefinition(typeDefinition)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeTypeDefinition(TypeDefinition<?> typeDefinition) {
+        '''
+            type Â«typeDefinition.QName.localName»;
+        '''
+    }
+
+    def static writeIdentities(Set<IdentitySchemaNode> identities) {
+        if (identities.nullOrEmpty)
+            return ''
+        '''
+            Â«FOR identity : identities»
+                Â«writeIdentity(identity)»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeIdentity(IdentitySchemaNode identity) {
+        if (identity == null)
+            return ''
+        '''
+            identity Â«identity.QName.localName» {
+                Â«IF identity.baseIdentity != null»
+                base "(«writeIdentityNs(identity.baseIdentity)»)«identity.baseIdentity»";
+                Â«ENDIF»
+                Â«IF !identity.description.nullOrEmpty»
+                description
+                    "«identity.description»";
+                Â«ENDIF»
+                Â«IF !identity.reference.nullOrEmpty»
+                reference
+                    "«identity.reference»";
+                Â«ENDIF»
+                Â«IF identity.status != null»
+                status Â«identity.status»;
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeIdentityNs(IdentitySchemaNode identity) {
+        if(module == null)
+            return ''
+
+        val identityNs = identity.QName.namespace
+
+        if(!module.namespace.equals(identityNs))
+            return identityNs + ":"
+        return ''
+    }
+
+    def static writeFeatures(Set<FeatureDefinition> features) {
+        '''
+            Â«FOR feature : features»
+                Â«IF feature != null»
+                Â«writeFeature(feature)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeFeature(FeatureDefinition featureDef) {
+        '''
+            feature Â«featureDef.QName.localName» {
+                Â«IF !featureDef.description.nullOrEmpty»
+                description
+                    "«featureDef.description»";
+                Â«ENDIF»
+                Â«IF !featureDef.reference.nullOrEmpty»
+                reference
+                    "«featureDef.reference»";
+                Â«ENDIF»
+                Â«IF featureDef.status != null»
+                status Â«featureDef.status»;
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeExtensions(List<ExtensionDefinition> extensions) {
+        '''
+            Â«FOR anExtension : extensions»
+                Â«IF anExtension != null»
+                Â«writeExtension(anExtension)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeExtension(ExtensionDefinition extensionDef) {
+        '''
+            extension Â«extensionDef.QName.localName» {
+                Â«IF !extensionDef.description.nullOrEmpty»
+                description
+                    "«extensionDef.description»";
+                Â«ENDIF»
+                Â«IF !extensionDef.argument.nullOrEmpty»
+                argument "«extensionDef.argument»";
+                Â«ENDIF»
+                Â«IF !extensionDef.reference.nullOrEmpty»
+                reference
+                    "«extensionDef.reference»";
+                Â«ENDIF»
+                Â«IF extensionDef.status != null»
+                status Â«extensionDef.status»;
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeDeviations(Set<Deviation> deviations) {
+        '''
+            Â«FOR deviation : deviations»
+                Â«IF deviation != null»
+                Â«writeDeviation(deviation)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeDeviation(Deviation deviation) {
+        '''
+            deviation Â«deviation.targetPath» {
+                Â«IF !deviation.reference.nullOrEmpty»
+                    reference
+                        "«deviation.reference»";
+                Â«ENDIF»
+                Â«IF deviation.deviate != null && !deviation.deviate.name.nullOrEmpty»
+                    deviation Â«deviation.deviate.name»;
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeAugments(Set<AugmentationSchema> augments) {
+        '''
+            Â«FOR augment : augments»
+                Â«IF augment != null»
+                Â«writeAugment(augment)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeDataSchemaNodes(Collection<DataSchemaNode> dataSchemaNodes) {
+        '''
+            Â«FOR schemaNode : dataSchemaNodes»
+                Â«writeDataSchemaNode(schemaNode)»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static CharSequence writeGroupingDefs(Set<GroupingDefinition> groupingDefs) {
+        '''
+            Â«FOR groupingDef : groupingDefs»
+                Â«IF groupingDef != null»
+                Â«writeGroupingDef(groupingDef)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        '''
+    }
+
+    def static writeAugment(AugmentationSchema augment) {
+        '''
+            augment Â«formatToAugmentPath(augment.targetPath.pathFromRoot)» {
+                Â«IF augment.whenCondition != null && !augment.whenCondition.toString.nullOrEmpty»
+                when "«augment.whenCondition.toString»";
+                Â«ENDIF»
+                Â«IF !augment.description.nullOrEmpty»
+                description
+                    "«augment.description»";
+                Â«ENDIF»
+                Â«IF !augment.reference.nullOrEmpty»
+                reference
+                    "«augment.reference»";
+                Â«ENDIF»
+                Â«IF augment.status != null»
+                status Â«augment.status»;
+                Â«ENDIF»
+                Â«IF !augment.childNodes.nullOrEmpty»
+                Â«writeDataSchemaNodes(augment.childNodes)»
+                Â«ENDIF»
+                Â«IF !augment.uses.nullOrEmpty»
+                Â«writeUsesNodes(augment.uses)»
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeGroupingDef(GroupingDefinition groupingDef) {
+        '''
+            grouping Â«groupingDef.QName.localName» {
+                Â«IF !groupingDef.groupings.nullOrEmpty»
+                    Â«writeGroupingDefs(groupingDef.groupings)»
+                Â«ENDIF»
+                Â«IF !groupingDef.childNodes.nullOrEmpty»
+                    Â«writeDataSchemaNodes(groupingDef.childNodes)»
+                Â«ENDIF»
+                Â«IF !groupingDef.unknownSchemaNodes.nullOrEmpty»
+                    Â«writeUnknownSchemaNodes(groupingDef.unknownSchemaNodes)»
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeContSchemaNode(ContainerSchemaNode contSchemaNode) {
+        '''
+            container Â«contSchemaNode.getQName.localName» {
+                Â«IF !contSchemaNode.childNodes.nullOrEmpty»
+                Â«writeDataSchemaNodes(contSchemaNode.childNodes)»
+                Â«ENDIF»
+                Â«IF !contSchemaNode.availableAugmentations.nullOrEmpty»
+                Â«writeAugments(contSchemaNode.availableAugmentations)»
+                Â«ENDIF»
+                Â«IF !contSchemaNode.groupings.nullOrEmpty»
+                Â«writeGroupingDefs(contSchemaNode.groupings)»
+                Â«ENDIF»
+                Â«IF !contSchemaNode.uses.nullOrEmpty»
+                Â«writeUsesNodes(contSchemaNode.uses)»
+                Â«ENDIF»
+                Â«IF !contSchemaNode.unknownSchemaNodes.nullOrEmpty»
+                Â«writeUnknownSchemaNodes(contSchemaNode.unknownSchemaNodes)»
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static writeAnyXmlSchemaNode(AnyXmlSchemaNode anyXmlSchemaNode) {
+        '''
+            anyxml Â«anyXmlSchemaNode.getQName.localName»;
+        '''
+    }
+
+    def static writeLeafSchemaNode(LeafSchemaNode leafSchemaNode) {
+        '''
+            leaf Â«leafSchemaNode.getQName.localName» {
+                type Â«leafSchemaNode.type.getQName.localName»;
+            }
+        '''
+    }
+
+    def static writeLeafListSchemaNode(LeafListSchemaNode leafListSchemaNode) {
+        '''
+            leaf-list Â«leafListSchemaNode.getQName.localName» {
+                type Â«leafListSchemaNode.type.getQName.localName»;
+            }
+        '''
+    }
+
+    def static writeChoiceCaseNode(ChoiceCaseNode choiceCaseNode) {
+        '''
+            case Â«choiceCaseNode.getQName.localName» {
+                Â«FOR childNode : choiceCaseNode.childNodes»
+                    Â«writeDataSchemaNode(childNode)»
+                Â«ENDFOR»
+            }
+        '''
+    }
+
+    def static writeChoiceNode(ChoiceSchemaNode choiceNode) {
+        '''
+            choice Â«choiceNode.getQName.localName» {
+                Â«FOR child : choiceNode.cases»
+                    Â«writeDataSchemaNode(child)»
+                Â«ENDFOR»
+            }
+        '''
+    }
+
+    def static writeListSchemaNode(ListSchemaNode listSchemaNode) {
+        '''
+            list Â«listSchemaNode.getQName.localName» {
+                key Â«FOR listKey : listSchemaNode.keyDefinition SEPARATOR " "»"«listKey.localName»"
+                Â«ENDFOR»
+                Â«IF !listSchemaNode.childNodes.nullOrEmpty»
+                    Â«writeDataSchemaNodes(listSchemaNode.childNodes)»
+                Â«ENDIF»
+                Â«IF !listSchemaNode.availableAugmentations.nullOrEmpty»
+                    Â«writeAugments(listSchemaNode.availableAugmentations)»
+                Â«ENDIF»
+                Â«IF !listSchemaNode.groupings.nullOrEmpty»
+                    Â«writeGroupingDefs(listSchemaNode.groupings)»
+                Â«ENDIF»
+                Â«IF !listSchemaNode.uses.nullOrEmpty»
+                    Â«writeUsesNodes(listSchemaNode.uses)»
+                Â«ENDIF»
+                Â«IF !listSchemaNode.unknownSchemaNodes.nullOrEmpty»
+                    Â«writeUnknownSchemaNodes(listSchemaNode.unknownSchemaNodes)»
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    def static CharSequence writeDataSchemaNode(DataSchemaNode child) {
+        '''
+            Â«IF child instanceof ContainerSchemaNode»
+                Â«writeContSchemaNode(child)»
+            Â«ENDIF»
+            Â«IF child instanceof AnyXmlSchemaNode»
+                Â«writeAnyXmlSchemaNode(child)»
+            Â«ENDIF»
+            Â«IF child instanceof LeafSchemaNode»
+                Â«writeLeafSchemaNode(child)»
+            Â«ENDIF»
+            Â«IF child instanceof LeafListSchemaNode»
+                Â«writeLeafListSchemaNode(child)»
+            Â«ENDIF»
+            Â«IF child instanceof ChoiceCaseNode»
+                Â«writeChoiceCaseNode(child)»
+            Â«ENDIF»
+            Â«IF child instanceof ChoiceSchemaNode»
+                Â«writeChoiceNode(child)»
+            Â«ENDIF»
+            Â«IF child instanceof ListSchemaNode»
+                Â«writeListSchemaNode(child)»
+            Â«ENDIF»
+        '''
+    }
+    
+    static def String formatSchemaPath(String moduleName, Iterable<QName> schemaPath) {
+        var currentElement = schemaPath.head
+        val StringBuilder sb = new StringBuilder()
+        sb.append(moduleName)
+
+        for(pathElement : schemaPath) {
+            if(!currentElement.namespace.equals(pathElement.namespace)) {
+                currentElement = pathElement
+                sb.append('/')
+                sb.append(pathElement)
+            }
+            else {
+                sb.append('/')
+                sb.append(pathElement.localName)
+            }
+        }
+        return sb.toString
+    }
+
+    static def String formatToParagraph(String text, int nextLineIndent) {
+        if (text == null || text.isEmpty())
+            return '';
+
+        var String formattedText = text;
+        val StringBuilder sb = new StringBuilder();
+        val StringBuilder lineBuilder = new StringBuilder();
+        var boolean isFirstElementOnNewLineEmptyChar = false;
+        val lineIndent = computeNextLineIndent(nextLineIndent);
+
+        formattedText = formattedText.replace("*/", "&#42;&#47;");
+        formattedText = NEWLINE_OR_TAB.removeFrom(formattedText);
+        formattedText = formattedText.replaceAll(" +", " ");
+
+        val StringTokenizer tokenizer = new StringTokenizer(formattedText, " ", true);
+
+        while (tokenizer.hasMoreElements()) {
+            val String nextElement = tokenizer.nextElement().toString();
+
+            if (lineBuilder.length() + nextElement.length() > 80) {
+                if (lineBuilder.charAt(lineBuilder.length() - 1) == ' ') {
+                    lineBuilder.setLength(0);
+                    lineBuilder.append(lineBuilder.substring(0, lineBuilder.length() - 1));
+                }
+                if (lineBuilder.charAt(0) == ' ') {
+                    lineBuilder.setLength(0);
+                    lineBuilder.append(lineBuilder.substring(1));
+                }
+
+                sb.append(lineBuilder);
+                lineBuilder.setLength(0);
+                sb.append("\n");
+
+                if (nextLineIndent > 0) {
+                    sb.append(lineIndent)
+                }
+
+                if (nextElement.toString().equals(" "))
+                    isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
+            }
+            if (isFirstElementOnNewLineEmptyChar) {
+                isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
+            } else {
+                lineBuilder.append(nextElement);
+            }
+        }
+        sb.append(lineBuilder);
+        sb.append("\n");
+
+        return sb.toString();
+    }
+
+    def private static formatToAugmentPath(Iterable<QName> schemaPath) {
+        val StringBuilder sb = new StringBuilder();
+
+        for(pathElement : schemaPath) {
+            val ns = pathElement.namespace
+            val localName = pathElement.localName
+
+            sb.append("\\(")
+            sb.append(ns)
+            sb.append(')')
+            sb.append(localName)
+        }
+        return sb.toString
+    }
+
+    private static def computeNextLineIndent(int nextLineIndent) {
+        val StringBuilder sb = new StringBuilder()
+        var i = 0
+        while (i < nextLineIndent) {
+            sb.append(' ')
+            i = i + 1
+        }
+        return sb.toString
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/BindingRuntimeContext.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/BindingRuntimeContext.java
new file mode 100644 (file)
index 0000000..2c16ba4
--- /dev/null
@@ -0,0 +1,446 @@
+/*
+ * 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.sal.binding.generator.util;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Multimap;
+import java.util.AbstractMap;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingSchemaContextUtils;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+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.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+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.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.EffectiveAugmentationSchema;
+import org.opendaylight.yangtools.yang.model.util.EnumerationType;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+/**
+ *
+ * Runtime Context for Java YANG Binding classes
+ *
+ *<p>
+ * Runtime Context provides additional insight in Java YANG Binding,
+ * binding classes and underlying YANG schema, it contains
+ * runtime information, which could not be derived from generated
+ * classes alone using {@link org.opendaylight.yangtools.yang.binding.util.BindingReflections}.
+ * <p>
+ * Some of this information are for example list of all available
+ * children for cases {@link #getChoiceCaseChildren(DataNodeContainer)}, since
+ * choices are augmentable and new choices may be introduced by additional models.
+ * <p>
+ * Same goes for all possible augmentations.
+ *
+ */
+public class BindingRuntimeContext implements Immutable {
+    private static final Logger LOG = LoggerFactory.getLogger(BindingRuntimeContext.class);
+    private static final char DOT = '.';
+    private final ClassLoadingStrategy strategy;
+    private final SchemaContext schemaContext;
+
+    private final Map<Type, AugmentationSchema> augmentationToSchema = new HashMap<>();
+    private final BiMap<Type, Object> typeToDefiningSchema = HashBiMap.create();
+    private final Multimap<Type, Type> augmentableToAugmentations = HashMultimap.create();
+    private final Multimap<Type, Type> choiceToCases = HashMultimap.create();
+    private final Map<QName, Type> identities = new HashMap<>();
+
+    private final LoadingCache<QName, Class<?>> identityClasses = CacheBuilder.newBuilder().weakValues().build(
+        new CacheLoader<QName, Class<?>>() {
+            @Override
+            public Class<?> load(final QName key) {
+                final Type identityType = identities.get(key);
+                Preconditions.checkArgument(identityType != null, "Supplied QName %s is not a valid identity", key);
+                try {
+                    return strategy.loadClass(identityType);
+                } catch (final ClassNotFoundException e) {
+                    throw new IllegalArgumentException("Required class " + identityType + "was not found.", e);
+                }
+            }
+        });
+
+    private BindingRuntimeContext(final ClassLoadingStrategy strategy, final SchemaContext schema) {
+        this.strategy = strategy;
+        this.schemaContext = schema;
+
+        final BindingGeneratorImpl generator = new BindingGeneratorImpl(false);
+        generator.generateTypes(schema);
+        final Map<Module, ModuleContext> modules = generator.getModuleContexts();
+
+        for (final ModuleContext ctx : modules.values()) {
+            augmentationToSchema.putAll(ctx.getTypeToAugmentation());
+            typeToDefiningSchema.putAll(ctx.getTypeToSchema());
+
+            ctx.getTypedefs();
+            augmentableToAugmentations.putAll(ctx.getAugmentableToAugmentations());
+            choiceToCases.putAll(ctx.getChoiceToCases());
+            identities.putAll(ctx.getIdentities());
+        }
+    }
+
+    /**
+     *
+     * Creates Binding Runtime Context from supplied class loading strategy and schema context.
+     *
+     * @param strategy Class loading strategy to retrieve generated Binding classes
+     * @param ctx Schema Context which describes YANG model and to which Binding classes should be mapped
+     * @return Instance of BindingRuntimeContext for supplied schema context.
+     */
+    public static final BindingRuntimeContext create(final ClassLoadingStrategy strategy, final SchemaContext ctx) {
+        return new BindingRuntimeContext(strategy, ctx);
+    }
+
+    /**
+     * Returns a class loading strategy associated with this binding runtime context
+     * which is used to load classes.
+     *
+     * @return Class loading strategy.
+     */
+    public ClassLoadingStrategy getStrategy() {
+        return strategy;
+    }
+
+    /**
+     * Returns an stable immutable view of schema context associated with this Binding runtime context.
+     *
+     * @return stable view of schema context
+     */
+    public SchemaContext getSchemaContext() {
+        return schemaContext;
+    }
+
+    /**
+     * Returns schema of augmentation
+     * <p>
+     * Returned schema is schema definition from which augmentation class was generated.
+     * This schema is isolated from other augmentations. This means it contains
+     * augmentation definition as was present in original YANG module.
+     * <p>
+     * Children of returned schema does not contain any additional augmentations,
+     * which may be present in runtime for them, thus returned schema is unsuitable
+     * for use for validation of data.
+     * <p>
+     * For retrieving {@link AugmentationSchema}, which will contains
+     * full model for child nodes, you should use method {@link #getResolvedAugmentationSchema(DataNodeContainer, Class)}
+     * which will return augmentation schema derived from supplied augmentation target
+     * schema.
+     *
+     * @param augClass Augmentation class
+     * @return Schema of augmentation or null if augmentaiton is not known in this context
+     * @throws IllegalArgumentException If supplied class is not an augmentation
+     */
+    public @Nullable AugmentationSchema getAugmentationDefinition(final Class<?> augClass) throws IllegalArgumentException {
+        Preconditions.checkArgument(Augmentation.class.isAssignableFrom(augClass), "Class %s does not represent augmentation", augClass);
+        return augmentationToSchema.get(referencedType(augClass));
+    }
+
+    /**
+     * Returns defining {@link DataSchemaNode} for supplied class.
+     *
+     * <p>
+     * Returned schema is schema definition from which class was generated.
+     * This schema may be isolated from augmentations, if supplied class
+     * represent node, which was child of grouping or augmentation.
+     * <p>
+     * For getting augmentation schema from augmentation class use
+     * {@link #getAugmentationDefinition(Class)} instead.
+     *
+     * @param cls Class which represents list, container, choice or case.
+     * @return Schema node, from which class was generated.
+     */
+    public DataSchemaNode getSchemaDefinition(final Class<?> cls) {
+        Preconditions.checkArgument(!Augmentation.class.isAssignableFrom(cls),"Supplied class must not be augmentation (%s is)", cls);
+        return (DataSchemaNode) typeToDefiningSchema.get(referencedType(cls));
+    }
+
+    public Entry<AugmentationIdentifier, AugmentationSchema> getResolvedAugmentationSchema(final DataNodeContainer target,
+            final Class<? extends Augmentation<?>> aug) {
+        final AugmentationSchema origSchema = getAugmentationDefinition(aug);
+        Preconditions.checkArgument(origSchema != null, "Augmentation %s is not known in current schema context",aug);
+        /*
+         * FIXME: Validate augmentation schema lookup
+         *
+         * Currently this algorithm, does not verify if instantiated child nodes
+         * are real one derived from augmentation schema. The problem with
+         * full validation is, if user used copy builders, he may use
+         * augmentation which was generated for different place.
+         *
+         * If this augmentations have same definition, we emit same identifier
+         * with data and it is up to underlying user to validate data.
+         *
+         */
+        final Set<QName> childNames = new HashSet<>();
+        final Set<DataSchemaNode> realChilds = new HashSet<>();
+        for (final DataSchemaNode child : origSchema.getChildNodes()) {
+            realChilds.add(target.getDataChildByName(child.getQName()));
+            childNames.add(child.getQName());
+        }
+
+        final AugmentationIdentifier identifier = new AugmentationIdentifier(childNames);
+        final AugmentationSchema proxy = new EffectiveAugmentationSchema(origSchema, realChilds);
+        return new AbstractMap.SimpleEntry<>(identifier, proxy);
+    }
+
+    /**
+     *
+     * Returns resolved case schema for supplied class
+     *
+     * @param schema Resolved parent choice schema
+     * @param childClass Class representing case.
+     * @return Optionally a resolved case schema, absent if the choice is not legal in
+     *         the given context.
+     * @throws IllegalArgumentException If supplied class does not represent case.
+     */
+    public Optional<ChoiceCaseNode> getCaseSchemaDefinition(final ChoiceSchemaNode schema, final Class<?> childClass) throws IllegalArgumentException {
+        final DataSchemaNode origSchema = getSchemaDefinition(childClass);
+        Preconditions.checkArgument(origSchema instanceof ChoiceCaseNode, "Supplied schema %s is not case.", origSchema);
+
+        /* FIXME: Make sure that if there are multiple augmentations of same
+         * named case, with same structure we treat it as equals
+         * this is due property of Binding specification and copy builders
+         * that user may be unaware that he is using incorrect case
+         * which was generated for choice inside grouping.
+         */
+        final Optional<ChoiceCaseNode> found = BindingSchemaContextUtils.findInstantiatedCase(schema,
+                (ChoiceCaseNode) origSchema);
+        return found;
+    }
+
+    private static Type referencedType(final Class<?> type) {
+        return new ReferencedTypeImpl(type.getPackage().getName(), type.getSimpleName());
+    }
+
+    static Type referencedType(final String type) {
+        final int packageClassSeparator = type.lastIndexOf(DOT);
+        return new ReferencedTypeImpl(type.substring(0, packageClassSeparator), type.substring(packageClassSeparator + 1));
+    }
+
+    /**
+     * Returns schema ({@link DataSchemaNode}, {@link AugmentationSchema} or {@link TypeDefinition})
+     * from which supplied class was generated. Returned schema may be augmented with
+     * additional information, which was not available at compile type
+     * (e.g. third party augmentations).
+     *
+     * @param type Binding Class for which schema should be retrieved.
+     * @return Instance of generated type (definition of Java API), along with
+     *     {@link DataSchemaNode}, {@link AugmentationSchema} or {@link TypeDefinition}
+     *     which was used to generate supplied class.
+     */
+    public Entry<GeneratedType, Object> getTypeWithSchema(final Class<?> type) {
+        return getTypeWithSchema(referencedType(type));
+    }
+
+    public Entry<GeneratedType, Object> getTypeWithSchema(final String type) {
+        return getTypeWithSchema(referencedType(type));
+    }
+
+    private Entry<GeneratedType, Object> getTypeWithSchema(final Type referencedType) {
+        final Object schema = typeToDefiningSchema.get(referencedType);
+        final Type definedType = typeToDefiningSchema.inverse().get(schema);
+        Preconditions.checkNotNull(schema);
+        Preconditions.checkNotNull(definedType);
+        if(definedType instanceof GeneratedTypeBuilder) {
+            return new SimpleEntry<>(((GeneratedTypeBuilder) definedType).toInstance(), schema);
+        }
+        Preconditions.checkArgument(definedType instanceof GeneratedType,"Type {} is not GeneratedType", referencedType);
+        return new SimpleEntry<>((GeneratedType) definedType,schema);
+    }
+
+    public ImmutableMap<Type, Entry<Type, Type>> getChoiceCaseChildren(final DataNodeContainer schema) {
+        final Map<Type,Entry<Type,Type>> childToCase = new HashMap<>();
+        for (final ChoiceSchemaNode choice :  FluentIterable.from(schema.getChildNodes()).filter(ChoiceSchemaNode.class)) {
+            final ChoiceSchemaNode originalChoice = getOriginalSchema(choice);
+            final Type choiceType = referencedType(typeToDefiningSchema.inverse().get(originalChoice));
+            final Collection<Type> cases = choiceToCases.get(choiceType);
+
+            for (Type caze : cases) {
+                final Entry<Type,Type> caseIdentifier = new SimpleEntry<>(choiceType,caze);
+                final HashSet<Type> caseChildren = new HashSet<>();
+                if (caze instanceof GeneratedTypeBuilder) {
+                    caze = ((GeneratedTypeBuilder) caze).toInstance();
+                }
+                collectAllContainerTypes((GeneratedType) caze, caseChildren);
+                for (final Type caseChild : caseChildren) {
+                    childToCase.put(caseChild, caseIdentifier);
+                }
+            }
+        }
+        return ImmutableMap.copyOf(childToCase);
+    }
+
+    /**
+     * Map enum constants: yang - java
+     *
+     * @param enumClass enum generated class
+     * @return mapped enum constants from yang with their corresponding values in generated binding classes
+     */
+    public BiMap<String, String> getEnumMapping(final Class<?> enumClass) {
+        final Map.Entry<GeneratedType, Object> typeWithSchema = getTypeWithSchema(enumClass);
+        return getEnumMapping(typeWithSchema);
+    }
+
+    /**
+     * See {@link #getEnumMapping(Class)}}
+     */
+    public BiMap<String, String> getEnumMapping(final String enumClass) {
+        final Map.Entry<GeneratedType, Object> typeWithSchema = getTypeWithSchema(enumClass);
+        return getEnumMapping(typeWithSchema);
+    }
+
+    private static BiMap<String, String> getEnumMapping(final Entry<GeneratedType, Object> typeWithSchema) {
+        final TypeDefinition<?> typeDef = (TypeDefinition<?>) typeWithSchema.getValue();
+
+        final EnumerationType enumType;
+        if(typeDef instanceof ExtendedType) {
+            enumType = (EnumerationType) ((ExtendedType) typeDef).getBaseType();
+        } else {
+            Preconditions.checkArgument(typeDef instanceof EnumerationType);
+            enumType = (EnumerationType) typeDef;
+        }
+
+        final HashBiMap<String, String> mappedEnums = HashBiMap.create();
+
+        for (final EnumTypeDefinition.EnumPair enumPair : enumType.getValues()) {
+            mappedEnums.put(enumPair.getName(), BindingMapping.getClassName(enumPair.getName()));
+        }
+
+        // TODO cache these maps for future use
+        return mappedEnums;
+    }
+
+    public Set<Class<?>> getCases(final Class<?> choice) {
+        final Collection<Type> cazes = choiceToCases.get(referencedType(choice));
+        final Set<Class<?>> ret = new HashSet<>(cazes.size());
+        for(final Type caze : cazes) {
+            try {
+                final Class<?> c = strategy.loadClass(caze);
+                ret.add(c);
+            } catch (final ClassNotFoundException e) {
+                LOG.warn("Failed to load class for case {}, ignoring it", caze, e);
+            }
+        }
+        return ret;
+    }
+
+    public Class<?> getClassForSchema(final SchemaNode childSchema) {
+        final SchemaNode origSchema = getOriginalSchema(childSchema);
+        final Type clazzType = typeToDefiningSchema.inverse().get(origSchema);
+        try {
+            return strategy.loadClass(clazzType);
+        } catch (final ClassNotFoundException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public ImmutableMap<AugmentationIdentifier,Type> getAvailableAugmentationTypes(final DataNodeContainer container) {
+        final Map<AugmentationIdentifier,Type> identifierToType = new HashMap<>();
+        if (container instanceof AugmentationTarget) {
+            final Set<AugmentationSchema> augments = ((AugmentationTarget) container).getAvailableAugmentations();
+            for (final AugmentationSchema augment : augments) {
+                // Augmentation must have child nodes if is to be used with Binding classes
+                AugmentationSchema augOrig = augment;
+                while (augOrig.getOriginalDefinition().isPresent()) {
+                    augOrig = augOrig.getOriginalDefinition().get();
+                }
+
+                if (!augment.getChildNodes().isEmpty()) {
+                    final Type augType = typeToDefiningSchema.inverse().get(augOrig);
+                    if (augType != null) {
+                        identifierToType.put(getAugmentationIdentifier(augment),augType);
+                    }
+                }
+            }
+        }
+
+        return ImmutableMap.copyOf(identifierToType);
+    }
+
+    private static AugmentationIdentifier getAugmentationIdentifier(final AugmentationSchema augment) {
+        final Set<QName> childNames = new HashSet<>();
+        for (final DataSchemaNode child : augment.getChildNodes()) {
+            childNames.add(child.getQName());
+        }
+        return new AugmentationIdentifier(childNames);
+    }
+
+    private static Type referencedType(final Type type) {
+        if(type instanceof ReferencedTypeImpl) {
+            return type;
+        }
+        return new ReferencedTypeImpl(type.getPackageName(), type.getName());
+    }
+
+    private static Set<Type> collectAllContainerTypes(final GeneratedType type, final Set<Type> collection) {
+        for (final MethodSignature definition : type.getMethodDefinitions()) {
+            Type childType = definition.getReturnType();
+            if(childType instanceof ParameterizedType) {
+                childType = ((ParameterizedType) childType).getActualTypeArguments()[0];
+            }
+            if(childType instanceof GeneratedType || childType instanceof GeneratedTypeBuilder) {
+                collection.add(referencedType(childType));
+            }
+        }
+        for (final Type parent : type.getImplements()) {
+            if (parent instanceof GeneratedType) {
+                collectAllContainerTypes((GeneratedType) parent, collection);
+            }
+        }
+        return collection;
+    }
+
+    private static <T extends SchemaNode> T getOriginalSchema(final T choice) {
+        @SuppressWarnings("unchecked")
+        final T original = (T) SchemaNodeUtils.getRootOriginalIfPossible(choice);
+        if (original != null) {
+            return original;
+        }
+        return choice;
+    }
+
+    public Class<?> getIdentityClass(final QName input) {
+        return identityClasses.getUnchecked(input);
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/ClassCustomizer.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/ClassCustomizer.java
new file mode 100644 (file)
index 0000000..22d9e38
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.sal.binding.generator.util;
+
+import com.google.common.annotations.Beta;
+
+import javassist.CtClass;
+
+/**
+ * Interface allowing customization of classes after loading.
+ */
+@Beta
+public interface ClassCustomizer {
+    /**
+     * Customize a class.
+     *
+     * @param cls Class to be customized
+     * @throws Exception when a problem ensues.
+     */
+    void customizeClass(CtClass cls) throws Exception;
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/ClassGenerator.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/ClassGenerator.java
new file mode 100644 (file)
index 0000000..f67fc69
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * 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.sal.binding.generator.util;
+
+import javassist.CannotCompileException;
+import javassist.CtClass;
+
+public interface ClassGenerator {
+    void process(CtClass cls) throws CannotCompileException;
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/CodeGenerationException.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/CodeGenerationException.java
new file mode 100644 (file)
index 0000000..184898f
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.sal.binding.generator.util;
+
+public class CodeGenerationException extends RuntimeException{
+    private static final long serialVersionUID = 1L;
+
+    public CodeGenerationException() {
+        super();
+    }
+
+    public CodeGenerationException(String message, Throwable cause, boolean enableSuppression,
+            boolean writableStackTrace) {
+        super(message, cause, enableSuppression, writableStackTrace);
+    }
+
+    public CodeGenerationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public CodeGenerationException(String message) {
+        super(message);
+    }
+
+    public CodeGenerationException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/DefaultSourceCodeGenerator.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/DefaultSourceCodeGenerator.java
new file mode 100644 (file)
index 0000000..a98ccee
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014 Brocade Communications 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.sal.binding.generator.util;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.Modifier;
+import javassist.NotFoundException;
+
+/**
+ * The default implementation of the SourceCodeGenerator interface that generates readable source code
+ * for a runtime generated class. The appendField/appendMethod methods output source code to a temporary
+ * StringBuilder. When outputGeneratedSource is called, the entire class source code is generated and
+ * written to a file under a specified directory.
+ *
+ * @author Thomas Pantelis
+ */
+public class DefaultSourceCodeGenerator implements SourceCodeGenerator {
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultSourceCodeGenerator.class);
+
+    private static final String GENERATED_SOURCE_DIR_PROP = "org.opendaylight.yangtools.sal.generatedCodecSourceDir";
+
+    private final StringBuilder builder = new StringBuilder();
+    private final String generatedSourceDir;
+
+    /**
+     * Constructor.
+     *
+     * @param generatedSourceDir the directory in which to put generated source files. If null, the directory
+     *     is obtained from a system property (<i>org.opendaylight.yangtools.sal.generatedCodecSourceDir</i>) or
+     *     defaults to "generated-codecs".
+     */
+    public DefaultSourceCodeGenerator( String generatedSourceDir ) {
+        if( generatedSourceDir != null ) {
+            this.generatedSourceDir = generatedSourceDir;
+        }
+        else {
+            this.generatedSourceDir = System.getProperty( GENERATED_SOURCE_DIR_PROP, "generated-codecs" );
+        }
+    }
+
+    @Override
+    public void appendField(CtField field, String value) {
+        try {
+            builder.append('\n')
+                    .append(Modifier.toString(field.getModifiers()))
+                    .append(' ').append(field.getType().getName()).append(' ')
+                    .append(field.getName());
+            if (value != null) {
+                builder.append(" = ").append(value);
+            }
+
+            builder.append(";\n");
+        } catch (NotFoundException e) {
+            LOG.error("Error building field source for " + field.getName(), e);
+        }
+    }
+
+    @Override
+    public void appendMethod(CtMethod method, String code) {
+        try {
+            builder.append('\n')
+                    .append(Modifier.toString(method.getModifiers()))
+                    .append(' ').append(method.getReturnType().getName())
+                    .append(' ').append(method.getName()).append("( ");
+
+            CtClass[] paramTypes = method.getParameterTypes();
+            if (paramTypes != null) {
+                for (int i = 0; i < paramTypes.length; i++) {
+                    if (i > 0) {
+                        builder.append(", ");
+                    }
+                    builder.append(paramTypes[i].getName()).append(" $")
+                            .append(i + 1);
+                }
+            }
+
+            builder.append(" )\n").append(code).append("\n\n");
+        } catch (NotFoundException e) {
+            LOG.error("Error building method source for " + method.getName(), e);
+        }
+    }
+
+    @Override
+    public void outputGeneratedSource(CtClass ctClass) {
+        String name = ctClass.getName();
+
+        StringBuilder classBuilder = new StringBuilder();
+        classBuilder.append(Modifier.toString(ctClass.getModifiers()))
+                .append(" class ").append(ctClass.getSimpleName());
+
+        try {
+            CtClass superClass = ctClass.getSuperclass();
+            if (superClass != null) {
+                classBuilder.append(" extends ").append(superClass.getName());
+            }
+
+            CtClass[] interfaces = ctClass.getInterfaces();
+            if (interfaces.length > 0) {
+                classBuilder.append(" implements ");
+                for (int i = 0; i < interfaces.length; i++) {
+                    if (i > 0) {
+                        classBuilder.append(", ");
+                    }
+
+                    classBuilder.append(interfaces[i].getName());
+                }
+            }
+
+            classBuilder.append(" {\n").append(builder.toString())
+                    .append("\n}");
+        } catch (NotFoundException e) {
+            LOG.error("Error building class source for " + name, e);
+            return;
+        }
+
+        File dir = new File(generatedSourceDir);
+        dir.mkdir();
+        try (FileWriter writer = new FileWriter(new File(dir, name + ".java"))) {
+            writer.append(classBuilder.toString());
+            writer.flush();
+        } catch (IOException e) {
+            LOG.error("Error writing class source for " + name, e);
+        }
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/FieldGenerator.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/FieldGenerator.java
new file mode 100644 (file)
index 0000000..e69a273
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * 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.sal.binding.generator.util;
+
+import javassist.CtField;
+
+public interface FieldGenerator {
+    void process(CtField field);
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/JavassistUtils.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/JavassistUtils.java
new file mode 100644 (file)
index 0000000..e3a56e5
--- /dev/null
@@ -0,0 +1,207 @@
+/*
+ * 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.sal.binding.generator.util;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import java.util.Collection;
+import java.util.Map;
+import java.util.WeakHashMap;
+import javassist.CannotCompileException;
+import javassist.ClassClassPath;
+import javassist.ClassPath;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.LoaderClassPath;
+import javassist.Modifier;
+import javassist.NotFoundException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Users of this utility class are expected to synchronize on this instance
+ * it they need to ensure atomic operations on it.
+ */
+public final class JavassistUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(JavassistUtils.class);
+
+    private static final Map<ClassPool, JavassistUtils> INSTANCES = new WeakHashMap<>();
+    private final Map<ClassLoader, ClassPath> loaderClassPaths = new WeakHashMap<>();
+    private final ClassPool classPool;
+
+    private JavassistUtils(final ClassPool pool) {
+        classPool = Preconditions.checkNotNull(pool);
+    }
+
+    /**
+     * Get a utility instance for a particular class pool. A new instance is
+     * created if this is a new pool. If an instance already exists, is is
+     * returned.
+     *
+     * @param pool Backing class pool
+     * @return shared utility instance for specified pool
+     */
+    public static synchronized JavassistUtils forClassPool(final ClassPool pool) {
+        JavassistUtils ret = INSTANCES.get(Preconditions.checkNotNull(pool));
+        if (ret == null) {
+            ret = new JavassistUtils(pool);
+            INSTANCES.put(pool, ret);
+        }
+        return ret;
+    }
+
+    public void method(final CtClass it, final Class<? extends Object> returnType, final String name,
+            final Class<? extends Object> parameter, final MethodGenerator function1) throws CannotCompileException {
+        final CtClass[] pa = new CtClass[] { asCtClass(parameter) };
+        final CtMethod _ctMethod = new CtMethod(asCtClass(returnType), name, pa, it);
+
+        final CtMethod method = _ctMethod;
+        function1.process(method);
+        it.addMethod(method);
+    }
+
+    public void method(final CtClass it, final Class<? extends Object> returnType, final String name,
+            final Collection<? extends Class<?>> parameters, final MethodGenerator function1) throws CannotCompileException {
+        final CtClass[] pa = new CtClass[parameters.size()];
+
+        int i = 0;
+        for (Class<? extends Object> parameter : parameters) {
+            pa[i] = asCtClass(parameter);
+            ++i;
+        }
+
+        final CtMethod method = new CtMethod(asCtClass(returnType), name, pa, it);
+        function1.process(method);
+        it.addMethod(method);
+    }
+
+    public void staticMethod(final CtClass it, final Class<? extends Object> returnType, final String name,
+            final Class<? extends Object> parameter, final MethodGenerator function1) throws CannotCompileException {
+        final CtClass[] pa = new CtClass[] { asCtClass(parameter) };
+        final CtMethod _ctMethod = new CtMethod(asCtClass(returnType), name, pa, it);
+        final CtMethod method = _ctMethod;
+        function1.process(method);
+        it.addMethod(method);
+    }
+
+    public void implementMethodsFrom(final CtClass target, final CtClass source, final MethodGenerator function1) throws CannotCompileException {
+        for (CtMethod method : source.getMethods()) {
+            if (method.getDeclaringClass() == source) {
+                CtMethod redeclaredMethod = new CtMethod(method, target, null);
+                function1.process(redeclaredMethod);
+                target.addMethod(redeclaredMethod);
+            }
+        }
+    }
+
+    public CtClass createClass(final String fqn, final ClassGenerator cls) throws CannotCompileException {
+        CtClass target = classPool.makeClass(fqn);
+        cls.process(target);
+        return target;
+    }
+
+    public CtClass createClass(final String fqn, final CtClass superInterface, final ClassGenerator cls) throws CannotCompileException {
+        CtClass target = classPool.makeClass(fqn);
+        implementsType(target, superInterface);
+        cls.process(target);
+        return target;
+    }
+
+    /**
+     * Instantiate a new class based on a prototype. The class is set to automatically
+     * prune.
+     *
+     * @param prototype Prototype class fully qualified name
+     * @param fqn Target class fully qualified name
+     * @param customizer Customization callback to be invoked on the new class
+     * @return An instance of the new class
+     * @throws NotFoundException when the prototype class is not found
+     */
+    @Beta
+    public synchronized CtClass instantiatePrototype(final String prototype, final String fqn, final ClassCustomizer customizer) throws NotFoundException {
+        final CtClass result = classPool.getAndRename(prototype, fqn);
+        try {
+            customizer.customizeClass(result);
+        } catch (Exception e) {
+            LOG.warn("Failed to customize {} from prototype {}", fqn, prototype, e);
+            result.detach();
+            throw new IllegalStateException(String.format("Failed to instantiate prototype %s as %s", prototype, fqn), e);
+        }
+
+        result.stopPruning(false);
+        return result;
+    }
+
+    public void implementsType(final CtClass it, final CtClass supertype) {
+        Preconditions.checkArgument(supertype.isInterface(), "Supertype must be interface");
+        it.addInterface(supertype);
+    }
+
+    public CtClass asCtClass(final Class<? extends Object> class1) {
+        return get(this.classPool, class1);
+    }
+
+    public CtField field(final CtClass it, final String name, final Class<? extends Object> returnValue) throws CannotCompileException {
+        final CtField field = new CtField(asCtClass(returnValue), name, it);
+        field.setModifiers(Modifier.PUBLIC);
+        it.addField(field);
+        return field;
+    }
+
+    public CtField staticField(final CtClass it, final String name, final Class<? extends Object> returnValue) throws CannotCompileException {
+        return staticField(it, name, returnValue, null);
+    }
+
+    public CtField staticField(final CtClass it, final String name,
+            final Class<? extends Object> returnValue,
+            final SourceCodeGenerator sourceGenerator) throws CannotCompileException {
+        final CtField field = new CtField(asCtClass(returnValue), name, it);
+        field.setModifiers(Modifier.PUBLIC + Modifier.STATIC);
+        it.addField(field);
+
+        if (sourceGenerator != null) {
+            sourceGenerator.appendField(field, null);
+        }
+
+        return field;
+    }
+
+    public CtClass get(final ClassPool pool, final Class<? extends Object> cls) {
+        try {
+            return pool.get(cls.getName());
+        } catch (NotFoundException nfe1) {
+            appendClassLoaderIfMissing(cls.getClassLoader());
+            try {
+                return pool.get(cls.getName());
+            } catch (final NotFoundException nfe2) {
+                LOG.warn("Appending ClassClassPath for {}", cls, nfe2);
+                pool.appendClassPath(new ClassClassPath(cls));
+                try {
+                    return pool.get(cls.getName());
+                } catch (NotFoundException e) {
+                    LOG.warn("Failed to load class {} from pool {}", cls, pool, e);
+                    throw new IllegalStateException("Failed to load class", e);
+                }
+            }
+        }
+    }
+
+    public synchronized void appendClassLoaderIfMissing(final ClassLoader loader) {
+        if (!loaderClassPaths.containsKey(loader)) {
+            final ClassPath ctLoader = new LoaderClassPath(loader);
+            classPool.appendClassPath(ctLoader);
+            loaderClassPaths.put(loader, ctLoader);
+        }
+    }
+
+    public void ensureClassLoader(final Class<?> child) {
+        appendClassLoaderIfMissing(child.getClassLoader());
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/MethodGenerator.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/MethodGenerator.java
new file mode 100644 (file)
index 0000000..50d9f97
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * 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.sal.binding.generator.util;
+
+import javassist.CannotCompileException;
+import javassist.CtMethod;
+
+public interface MethodGenerator {
+    void process(CtMethod method) throws CannotCompileException;
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/NullSourceCodeGenerator.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/NullSourceCodeGenerator.java
new file mode 100644 (file)
index 0000000..f087d54
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014 Brocade Communications 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.sal.binding.generator.util;
+
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+
+/**
+ * Implementation of the SourceCodeGenerator interface that does nothing.
+ *
+ * @author Thomas Pantelis
+ */
+public class NullSourceCodeGenerator implements SourceCodeGenerator {
+
+    @Override
+    public void appendField( CtField field, String value ) {
+    }
+
+    @Override
+    public void appendMethod( CtMethod method, String code ) {
+    }
+
+    @Override
+    public void outputGeneratedSource( CtClass ctClass ) {
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGenerator.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGenerator.java
new file mode 100644 (file)
index 0000000..bfbb031
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Brocade Communications 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.sal.binding.generator.util;
+
+import javassist.CtClass;
+import javassist.CtField;
+import javassist.CtMethod;
+
+/**
+ * Interface for a class that that generates readable source code for a runtime generated class.
+ * The appendField/appendMethod methods append source code to a temporary output. When outputGeneratedSource
+ * is called, the entire class source code is generated and outputted.
+ *
+ * @author Thomas Pantelis
+ */
+public interface SourceCodeGenerator {
+
+    /**
+     * Appends the given class field and value to the temporary output.
+     */
+    void appendField( CtField field, String value );
+
+    /**
+     * Appends the given method and source code body to the temporary output.
+     */
+    void appendMethod( CtMethod method, String code );
+
+    /**
+     * Generates the full source code for the given class and outputs it.
+     */
+    void outputGeneratedSource( CtClass ctClass );
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGeneratorFactory.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/SourceCodeGeneratorFactory.java
new file mode 100644 (file)
index 0000000..23549c6
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014 Brocade Communications 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.sal.binding.generator.util;
+
+/**
+ * Factory class for creating SourceCodeGenerator instances.
+ *
+ * @author Thomas Pantelis
+ */
+public class SourceCodeGeneratorFactory {
+
+    private static final String GENERATE_CODEC_SOURCE_PROP = "org.opendaylight.yangtools.sal.generateCodecSource";
+
+    private static final SourceCodeGenerator NULL_GENERATOR = new NullSourceCodeGenerator();
+
+    /**
+     * Gets a SourceCodeGenerator instance.
+     * <p>
+     * Generation of source code is controlled by the <i>org.opendaylight.yangtools.sal.generateCodecSource</i>
+     * system property. If set to true, a DefaultSourceCodeGenerator instance is returned, otherwise a
+     * NullSourceCodeGenerator is returned.
+     *
+     * @param generatedSourceDir the directory in which to put generated source files. If null,
+     *     a default is used (see DefaultSourceCodeGenerator).
+     */
+    public SourceCodeGenerator getInstance( String generatedSourceDir ) {
+
+        boolean generateSource = Boolean.valueOf( System.getProperty( GENERATE_CODEC_SOURCE_PROP, "false") );
+        if( generateSource ) {
+            return new DefaultSourceCodeGenerator( generatedSourceDir );
+        }
+
+        return NULL_GENERATOR;
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/XtendHelper.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/XtendHelper.java
new file mode 100644 (file)
index 0000000..4809c50
--- /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.sal.binding.generator.util;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+
+public final class XtendHelper {
+    private XtendHelper() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
+    @SuppressWarnings({"rawtypes","unchecked"})
+    public static Iterable<TypeDefinition> getTypes(final UnionTypeDefinition definition) {
+        return (List) definition.getTypes();
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/YangSchemaUtils.java b/code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/util/YangSchemaUtils.java
new file mode 100644 (file)
index 0000000..5c35454
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * 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.sal.binding.generator.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Preconditions;
+import java.net.URI;
+import java.util.Date;
+import java.util.Iterator;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.NamespaceRevisionAware;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+
+public final class YangSchemaUtils {
+    public static final String AUGMENT_IDENTIFIER = "augment-identifier";
+
+    private YangSchemaUtils() {
+        throw new UnsupportedOperationException("Helper class. Instantiation is prohibited");
+    }
+
+    public static QName getAugmentationQName(final AugmentationSchema augmentation) {
+        checkNotNull(augmentation, "Augmentation must not be null.");
+        final QName identifier = getAugmentationIdentifier(augmentation);
+        if(identifier != null) {
+            return identifier;
+        }
+        URI namespace = null;
+        Date revision = null;
+        if(augmentation instanceof NamespaceRevisionAware) {
+            namespace = ((NamespaceRevisionAware) augmentation).getNamespace();
+            revision = ((NamespaceRevisionAware) augmentation).getRevision();
+        }
+        if(namespace == null || revision == null) {
+            for(final DataSchemaNode child : augmentation.getChildNodes()) {
+                // Derive QName from child nodes
+                if(!child.isAugmenting()) {
+                    namespace = child.getQName().getNamespace();
+                    revision = child.getQName().getRevision();
+                    break;
+                }
+            }
+        }
+        checkState(namespace != null, "Augmentation namespace must not be null");
+        checkState(revision != null, "Augmentation revision must not be null");
+        // FIXME: Allways return a qname with module namespace.
+        return QName.create(namespace,revision, "foo_augment");
+    }
+
+    public static QName getAugmentationIdentifier(final AugmentationSchema augmentation) {
+        for(final UnknownSchemaNode extension : augmentation.getUnknownSchemaNodes()) {
+            if(AUGMENT_IDENTIFIER.equals(extension.getNodeType().getLocalName())) {
+                return extension.getQName();
+            }
+        }
+        return null;
+    }
+
+    @Nullable
+    public static TypeDefinition<?> findTypeDefinition(final SchemaContext context, final SchemaPath path) {
+        final Iterator<QName> arguments = path.getPathFromRoot().iterator();
+        Preconditions.checkArgument(arguments.hasNext(), "Type Definition path must contain at least one element.");
+
+        QName currentArg = arguments.next();
+        DataNodeContainer currentNode = context.findModuleByNamespaceAndRevision(currentArg.getNamespace(), currentArg.getRevision());
+        if(currentNode == null) {
+            return null;
+        }
+        // Last argument is type definition, so we need to cycle until we hit last argument.
+        while(arguments.hasNext()) {
+            // Nested private type - we need to find container/grouping to which type belongs.
+            final DataSchemaNode child = currentNode.getDataChildByName(currentArg);
+            if(child instanceof DataNodeContainer) {
+                currentNode = (DataNodeContainer) child;
+            } else if (child instanceof ChoiceSchemaNode) {
+                final QName caseQName = arguments.next();
+                Preconditions.checkArgument(arguments.hasNext(), "Path must not refer case only.");
+                currentNode = ((ChoiceSchemaNode) child).getCaseNodeByName(caseQName);
+            } else {
+                // Search in grouping
+                for( final GroupingDefinition grouping : currentNode.getGroupings()) {
+                    if(currentArg.equals(grouping.getQName())) {
+                        currentNode = grouping;
+                        break;
+                    }
+                }
+            }
+            currentArg = arguments.next();
+        }
+
+        for(final TypeDefinition<?> typedef : currentNode.getTypeDefinitions()) {
+            if(typedef.getQName().equals(currentArg)) {
+                return typedef;
+            }
+        }
+        return null;
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/AbstractTypesTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/AbstractTypesTest.java
new file mode 100644 (file)
index 0000000..58b5133
--- /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.sal.binding.generator.impl;
+
+import com.google.common.base.Preconditions;
+import java.io.File;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Set;
+import org.junit.Before;
+
+public abstract class AbstractTypesTest {
+
+    private final URL testSourcesDirUrl;
+    protected Set<File> testModels;
+
+    AbstractTypesTest(final URL testSourcesDirUrl) {
+        this.testSourcesDirUrl = testSourcesDirUrl;
+    }
+
+    @Before
+    public void loadTestResources() throws URISyntaxException {
+        File testSourcesDir = new File(testSourcesDirUrl.toURI());
+        File[] testFiles = Preconditions.checkNotNull(testSourcesDir.listFiles(), testSourcesDir
+                + " does not denote a directory");
+        testModels = new HashSet<>();
+        for (File file : testFiles) {
+            if (file.isFile()) {
+                testModels.add(file);
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/AugmentRelativeXPathTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/AugmentRelativeXPathTest.java
new file mode 100644 (file)
index 0000000..250faf8
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class AugmentRelativeXPathTest extends AbstractTypesTest {
+
+    public AugmentRelativeXPathTest() {
+        super(AugmentRelativeXPathTest.class.getResource("/augment-relative-xpath-models"));
+    }
+
+    @Test
+    public void AugmentationWithRelativeXPathTest() throws IOException {
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull("context is null", context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull("genTypes is null", genTypes);
+        assertFalse("genTypes is empty", genTypes.isEmpty());
+
+        GeneratedTransferObject gtInterfaceKey = null;
+        GeneratedType gtInterface = null;
+        GeneratedType gtTunnel = null;
+        GeneratedTransferObject gtTunnelKey = null;
+
+        for (final Type type : genTypes) {
+            if (type.getName().equals("InterfaceKey") && type.getPackageName().contains("augment._abstract.topology")) {
+                gtInterfaceKey = (GeneratedTransferObject) type;
+            } else if (type.getName().equals("Interface")
+                    && type.getPackageName().contains("augment._abstract.topology")) {
+                gtInterface = (GeneratedType) type;
+            } else if (type.getName().equals("Tunnel") && type.getPackageName().contains("augment._abstract.topology")) {
+                gtTunnel = (GeneratedType) type;
+            } else if (type.getName().equals("TunnelKey")
+                    && type.getPackageName().contains("augment._abstract.topology")) {
+                gtTunnelKey = (GeneratedTransferObject) type;
+            }
+        }
+
+        // 'Interface
+        assertNotNull("Interface is null", gtInterface);
+        final List<MethodSignature> gtInterfaceMethods = gtInterface.getMethodDefinitions();
+        assertNotNull("Interface methods are null", gtInterfaceMethods);
+        MethodSignature getIfcKeyMethod = null;
+        for (final MethodSignature method : gtInterfaceMethods) {
+            if (method.getName().equals("getKey")) {
+                getIfcKeyMethod = method;
+                break;
+            }
+        }
+        assertNotNull("getKey method is null", getIfcKeyMethod);
+        assertNotNull("getKey method return type is null", getIfcKeyMethod.getReturnType());
+        assertTrue("getKey method return type name must be InterfaceKey", getIfcKeyMethod.getReturnType().getName()
+                .equals("InterfaceKey"));
+
+        // 'InterfaceKey'
+        assertNotNull("InterfaceKey is null", gtInterfaceKey);
+        final List<GeneratedProperty> properties = gtInterfaceKey.getProperties();
+        assertNotNull("InterfaceKey properties are null", properties);
+        GeneratedProperty gtInterfaceId = null;
+        for (final GeneratedProperty property : properties) {
+            if (property.getName().equals("interfaceId")) {
+                gtInterfaceId = property;
+                break;
+            }
+        }
+        assertNotNull("interfaceId is null", gtInterfaceId);
+        assertNotNull("interfaceId return type is null", gtInterfaceId.getReturnType());
+        assertTrue("interfaceId return type name must be String",
+                gtInterfaceId.getReturnType().getName().equals("String"));
+
+        // 'Tunnel'
+        assertNotNull("Tunnel is null", gtTunnel);
+        final List<MethodSignature> tunnelMethods = gtTunnel.getMethodDefinitions();
+        assertNotNull("Tunnel methods are null", tunnelMethods);
+        MethodSignature getTunnelKeyMethod = null;
+        for (MethodSignature method : tunnelMethods) {
+            if (method.getName().equals("getKey")) {
+                getTunnelKeyMethod = method;
+                break;
+            }
+        }
+        assertNotNull("getKey method is null", getTunnelKeyMethod);
+        assertNotNull("getKey method return type", getTunnelKeyMethod.getReturnType());
+        assertTrue("getKey method return type name must be TunnelKey", getTunnelKeyMethod.getReturnType().getName()
+                .equals("TunnelKey"));
+
+        // 'TunnelKey'
+        assertNotNull("TunnelKey is null", gtTunnelKey);
+        final List<GeneratedProperty> tunnelKeyProperties = gtTunnelKey.getProperties();
+        assertNotNull("TunnelKey properties are null", tunnelKeyProperties);
+
+        GeneratedProperty gtTunnelId = null;
+        for (final GeneratedProperty property : tunnelKeyProperties) {
+            if (property.getName().equals("tunnelId")) {
+                gtTunnelId = property;
+            }
+        }
+        assertNotNull("tunnelId is null", gtTunnelId);
+        assertNotNull("tunnelId return type is null", gtTunnelId.getReturnType());
+        assertTrue("tunnelId return type name must be Uri", gtTunnelId.getReturnType().getName().equals("Uri"));
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/AugmentedTypeTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/AugmentedTypeTest.java
new file mode 100644 (file)
index 0000000..70c7c66
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class AugmentedTypeTest {
+
+    @Test
+    public void augmentedAbstractTopologyTest() throws Exception {
+        File abstractTopology = new File(getClass().getResource(
+                "/augment-test-models/abstract-topology@2013-02-08.yang").toURI());
+        File augmentTopology = new File(getClass().getResource(
+                "/augment-test-models/augment-abstract-topology@2013-05-03.yang").toURI());
+        File augmentNetworkLink = new File(getClass().getResource(
+                "/augment-test-models/augment-network-link-attributes@2013-05-03.yang").toURI());
+        File augmentTopologyTunnels = new File(getClass().getResource(
+                "/augment-test-models/augment-topology-tunnels@2013-05-03.yang").toURI());
+        File ietfInterfaces = new File(getClass().getResource("/augment-test-models/ietf-interfaces@2012-11-15.yang")
+                .toURI());
+
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(abstractTopology, augmentTopology,
+                augmentNetworkLink, augmentTopologyTunnels, ietfInterfaces));
+        assertNotNull("Schema Context is null", context);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull("genTypes is null", genTypes);
+        assertFalse("genTypes is empty", genTypes.isEmpty());
+
+        GeneratedTransferObject gtInterfaceKey = null;
+        GeneratedType gtInterface = null;
+        GeneratedType gtTunnel = null;
+        GeneratedTransferObject gtTunnelKey = null;
+        GeneratedType gtNetworkLink2 = null;
+
+        for (final Type type : genTypes) {
+            if (type.getName().equals("InterfaceKey") && type.getPackageName().contains("augment._abstract.topology")) {
+                gtInterfaceKey = (GeneratedTransferObject) type;
+            } else if (type.getName().equals("Interface")
+                    && type.getPackageName().contains("augment._abstract.topology")) {
+                gtInterface = (GeneratedType) type;
+            } else if (type.getName().equals("Tunnel") && type.getPackageName().contains("augment._abstract.topology")) {
+                gtTunnel = (GeneratedType) type;
+            } else if (type.getName().equals("TunnelKey")
+                    && type.getPackageName().contains("augment._abstract.topology")) {
+                gtTunnelKey = (GeneratedTransferObject) type;
+            } else if (type.getName().equals("NetworkLink2")
+                    && type.getPackageName().contains("augment._abstract.topology")) {
+                gtNetworkLink2 = (GeneratedType) type;
+            }
+        }
+
+        // 'Interface
+        assertNotNull("gtInterface is null", gtInterface);
+        final List<MethodSignature> gtInterfaceMethods = gtInterface.getMethodDefinitions();
+        assertNotNull("gtInterfaceMethods is null", gtInterfaceMethods);
+        MethodSignature getIfcKeyMethod = null;
+        for (final MethodSignature method : gtInterfaceMethods) {
+            if (method.getName().equals("getKey")) {
+                getIfcKeyMethod = method;
+                break;
+            }
+        }
+        assertNotNull("getIfcKeyMethod is null", getIfcKeyMethod);
+        assertNotNull("getIfcKeyMethod.getReturnType() is null", getIfcKeyMethod.getReturnType());
+        assertFalse("getIfcKeyMethod.getReturnType() should not be Void",
+                getIfcKeyMethod.getReturnType().equals("java.lang.Void"));
+        assertTrue("getIfcKeyMethod.getReturnType().getName() must be InterfaceKey", getIfcKeyMethod.getReturnType()
+                .getName().equals("InterfaceKey"));
+
+        MethodSignature getHigherLayerIfMethod = null;
+        for (final MethodSignature method : gtInterfaceMethods) {
+            if (method.getName().equals("getHigherLayerIf")) {
+                getHigherLayerIfMethod = method;
+                break;
+            }
+        }
+        assertNotNull("getHigherLayerIf method is null", getHigherLayerIfMethod);
+        assertNotNull("getHigherLayerIf method return type is null", getHigherLayerIfMethod.getReturnType());
+        assertTrue("getHigherLayerIf method return type name must be List", getHigherLayerIfMethod.getReturnType()
+                .getName().equals("List"));
+
+        // 'InterfaceKey'
+        assertNotNull("InterfaceKey is null", gtInterfaceKey);
+        final List<GeneratedProperty> properties = gtInterfaceKey.getProperties();
+        assertNotNull("properties is null", properties);
+        GeneratedProperty gtInterfaceId = null;
+        for (final GeneratedProperty property : properties) {
+            if (property.getName().equals("interfaceId")) {
+                gtInterfaceId = property;
+                break;
+            }
+        }
+        assertNotNull("interfaceId is null", gtInterfaceId);
+        assertNotNull("interfaceId return type is null", gtInterfaceId.getReturnType());
+        assertTrue("interfaceId return type name must be String",
+                gtInterfaceId.getReturnType().getName().equals("String"));
+
+        // 'Tunnel'
+        assertNotNull("Tunnel is null", gtTunnel);
+        final List<MethodSignature> tunnelMethods = gtTunnel.getMethodDefinitions();
+        assertNotNull("Tunnel methods are null", tunnelMethods);
+        MethodSignature getTunnelKeyMethod = null;
+        for (MethodSignature method : tunnelMethods) {
+            if (method.getName().equals("getKey")) {
+                getTunnelKeyMethod = method;
+                break;
+            }
+        }
+        assertNotNull("getKey method of Tunnel is null", getTunnelKeyMethod);
+        assertNotNull("getKey method return type is null", getTunnelKeyMethod.getReturnType());
+        assertTrue("getKey method return type name must be TunnelKey", getTunnelKeyMethod.getReturnType().getName()
+                .equals("TunnelKey"));
+
+        // 'TunnelKey'
+        assertNotNull("TunnelKey is null", gtTunnelKey);
+        final List<GeneratedProperty> tunnelKeyProperties = gtTunnelKey.getProperties();
+        assertNotNull("TunnelKey properties are null", tunnelKeyProperties);
+
+        GeneratedProperty gtTunnelId = null;
+        for (final GeneratedProperty property : tunnelKeyProperties) {
+            if (property.getName().equals("tunnelId")) {
+                gtTunnelId = property;
+            }
+        }
+        assertNotNull("tunnelId is null", gtTunnelId);
+        assertNotNull("tunnelId return type is null", gtTunnelId.getReturnType());
+        assertTrue("tunnelId returnType name must be Integer", gtTunnelId.getReturnType().getName().equals("Integer"));
+
+        // 'NetworkLink2'
+        assertNotNull("NetworkLink2 is null", gtNetworkLink2);
+
+        final List<MethodSignature> networkLink2Methods = gtNetworkLink2.getMethodDefinitions();
+        assertNotNull("NetworkLink2 methods are null", networkLink2Methods);
+
+        MethodSignature getIfcMethod = null;
+        for (MethodSignature method : networkLink2Methods) {
+            if (method.getName().equals("getInterface")) {
+                getIfcMethod = method;
+                break;
+            }
+        }
+
+        assertNotNull("getInterface method is null", getIfcMethod);
+        assertNotNull("getInterface method return type is null", getIfcMethod.getReturnType());
+        assertTrue("getInterface method return type name must be String", getIfcMethod.getReturnType().getName()
+                .equals("String"));
+    }
+
+    @Test
+    public void augmentedNetworkLinkTest() {
+
+    }
+
+    @Test
+    public void augmentedTopologyTunnelsTest() {
+
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BaseTypeProvider.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BaseTypeProvider.java
new file mode 100644 (file)
index 0000000..f07ba14
--- /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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.yang.types.BaseYangTypes;
+
+public class BaseTypeProvider {
+
+    @Test
+    public void test() {
+        TypeProvider provider = BaseYangTypes.BASE_YANG_TYPES_PROVIDER;
+
+        Type stringType = provider.javaTypeForYangType("string");
+        assertEquals("java.lang", stringType.getPackageName());
+        assertEquals("String", stringType.getName());
+        assertTrue(stringType instanceof ConcreteType);
+        ParameterizedType stringBooleanMap = Types.mapTypeFor(
+                provider.javaTypeForYangType("string"),
+                provider.javaTypeForYangType("boolean"));
+        assertTrue(!(stringBooleanMap instanceof ConcreteType));
+        assertEquals("java.util", stringBooleanMap.getPackageName());
+        assertEquals("Map", stringBooleanMap.getName());
+        assertEquals(2, stringBooleanMap.getActualTypeArguments().length);
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BinaryTypeTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BinaryTypeTest.java
new file mode 100644 (file)
index 0000000..32b51af
--- /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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class BinaryTypeTest {
+    private final static List<File> yangModels = new ArrayList<>();
+    private final static URL yangModelsFolder = AugmentedTypeTest.class
+            .getResource("/binary-type-test-models");
+
+    @BeforeClass
+    public static void loadTestResources() throws URISyntaxException {
+        final File augFolder = new File(yangModelsFolder.toURI());
+        for (final File fileEntry : augFolder.listFiles()) {
+            if (fileEntry.isFile()) {
+                yangModels.add(fileEntry);
+            }
+        }
+    }
+
+    @Test
+    public void binaryTypeTest() throws IOException {
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(yangModels);
+
+        assertNotNull("context is null", context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull("genTypes is null", genTypes);
+        assertFalse("genTypes is empty", genTypes.isEmpty());
+
+        //TODO: implement test
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImplTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImplTest.java
new file mode 100644 (file)
index 0000000..3f37dcf
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2015 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class BindingGeneratorImplTest {
+
+    @Test
+    public void choiceNodeGenerationTest() throws IOException,
+            YangSyntaxErrorException, URISyntaxException {
+        File resourceFile = new File(getClass().getResource(
+                "/binding-generator-impl-test/choice-test.yang").toURI());
+        File resourceDir = resourceFile.getParentFile();
+
+        YangParserImpl parser = YangParserImpl.getInstance();
+        SchemaContext context = parser.parseFile(resourceFile, resourceDir);
+
+        List<Type> generateTypes = new BindingGeneratorImpl(false)
+                .generateTypes(context);
+
+        GeneratedType choiceTestData = null;
+        GeneratedType myRootContainer = null;
+        GeneratedType myList = null;
+        GeneratedType myContainer = null;
+        GeneratedType myList2 = null;
+        GeneratedType myContainer2 = null;
+
+        for (Type type : generateTypes) {
+            switch (type.getName()) {
+            case "ChoiceTestData":
+                choiceTestData = (GeneratedType) type;
+                break;
+            case "Myrootcontainer":
+                myRootContainer = (GeneratedType) type;
+                break;
+            case "Mylist":
+                myList = (GeneratedType) type;
+                break;
+            case "Mylist2":
+                myList2 = (GeneratedType) type;
+                break;
+            case "Mycontainer":
+                myContainer = (GeneratedType) type;
+                break;
+            case "Mycontainer2":
+                myContainer2 = (GeneratedType) type;
+                break;
+            }
+        }
+
+        assertNotNull(choiceTestData);
+        assertNotNull(myRootContainer);
+        assertNotNull(myList);
+        assertNotNull(myContainer);
+        assertNotNull(myList2);
+        assertNotNull(myContainer2);
+
+        List<Type> implements1 = myContainer.getImplements();
+        Type childOfParamType = null;
+        for (Type type : implements1) {
+            if (type.getName().equals("ChildOf")) {
+                childOfParamType = ((ParameterizedType) type)
+                        .getActualTypeArguments()[0];
+                break;
+            }
+        }
+        assertNotNull(childOfParamType);
+        assertTrue(childOfParamType.getName().equals("ChoiceTestData"));
+
+        implements1 = myList.getImplements();
+        childOfParamType = null;
+        for (Type type : implements1) {
+            if (type.getName().equals("ChildOf")) {
+                childOfParamType = ((ParameterizedType) type)
+                        .getActualTypeArguments()[0];
+                break;
+            }
+        }
+        assertNotNull(childOfParamType);
+        assertTrue(childOfParamType.getName().equals("ChoiceTestData"));
+
+        implements1 = myContainer2.getImplements();
+        childOfParamType = null;
+        for (Type type : implements1) {
+            if (type.getName().equals("ChildOf")) {
+                childOfParamType = ((ParameterizedType) type)
+                        .getActualTypeArguments()[0];
+                break;
+            }
+        }
+        assertNotNull(childOfParamType);
+        assertTrue(childOfParamType.getName().equals("Myrootcontainer"));
+
+        implements1 = myList2.getImplements();
+        childOfParamType = null;
+        for (Type type : implements1) {
+            if (type.getName().equals("ChildOf")) {
+                childOfParamType = ((ParameterizedType) type)
+                        .getActualTypeArguments()[0];
+                break;
+            }
+        }
+        assertNotNull(childOfParamType);
+        assertTrue(childOfParamType.getName().equals("Myrootcontainer"));
+
+    }
+
+    @Test
+    public void notificationGenerationTest() throws IOException, YangSyntaxErrorException, URISyntaxException {
+        File resourceFile = new File(getClass().getResource("/binding-generator-impl-test/notification-test.yang")
+                .toURI());
+        File resourceDir = resourceFile.getParentFile();
+
+        YangParserImpl parser = YangParserImpl.getInstance();
+        SchemaContext context = parser.parseFile(resourceFile, resourceDir);
+
+        List<Type> generateTypes = new BindingGeneratorImpl(false).generateTypes(context);
+
+        GeneratedType foo = null;
+        for (Type type : generateTypes) {
+            if (type.getName().equals("Foo")) {
+                foo = (GeneratedType) type;
+                break;
+            }
+        }
+
+        Type childOf = null;
+        Type dataObject = null;
+        List<Type> impl = foo.getImplements();
+        for (Type type : impl) {
+            switch (type.getName()) {
+            case "ChildOf":
+                childOf = type;
+                break;
+            case "DataObject":
+                dataObject = type;
+                break;
+            }
+        }
+
+        assertNull(childOf);
+        assertNotNull(dataObject);
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BitAndUnionTOEnclosingTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/BitAndUnionTOEnclosingTest.java
new file mode 100644 (file)
index 0000000..419551a
--- /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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.opendaylight.yangtools.sal.binding.generator.impl.SupportTestUtil.containsAttributes;
+import static org.opendaylight.yangtools.sal.binding.generator.impl.SupportTestUtil.containsMethods;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class BitAndUnionTOEnclosingTest {
+
+    private final static List<File> testModels = new ArrayList<File>();
+    private static List<Type> genTypes = null;
+    private static GeneratedType parentContainer = null;
+
+    public static void parseResources() throws IOException {
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        genTypes = bindingGen.generateTypes(context);
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("ParentContainer") && !(genType instanceof GeneratedTransferObject)) {
+                    parentContainer = genType;
+                }
+            }
+        }
+    }
+
+    @BeforeClass
+    public static void loadTestResources() throws IOException, URISyntaxException {
+        final File listModelFile = new File(ExtendedTypedefTest.class.getResource("/bit_and_union.yang").toURI());
+        testModels.add(listModelFile);
+        parseResources();
+    }
+
+    @Test
+    public void testNestedTypesInLeaf() {
+        GeneratedTransferObject lfLeaf = null;
+        int lfLeafCounter = 0;
+        GeneratedTransferObject lf1Leaf = null;
+        int lf1LeafCounter = 0;
+        GeneratedTransferObject lf2Leaf = null;
+        int lf2LeafCounter = 0;
+        List<GeneratedType> enclosedTypes = parentContainer.getEnclosedTypes();
+        for (GeneratedType genType : enclosedTypes) {
+            if (genType instanceof GeneratedTransferObject) {
+                if (genType.getName().equals("Lf")) {
+                    lfLeaf = (GeneratedTransferObject) genType;
+                    lfLeafCounter++;
+                } else if (genType.getName().equals("Lf1")) {
+                    lf1Leaf = (GeneratedTransferObject) genType;
+                    lf1LeafCounter++;
+                } else if (genType.getName().equals("Lf2")) {
+                    lf2Leaf = (GeneratedTransferObject) genType;
+                    lf2LeafCounter++;
+                }
+
+            }
+        }
+
+        // nested types in leaf, contains Lf?
+        assertNotNull("Lf TO wasn't found.", lfLeaf);
+        assertEquals("Lf TO has incorrect number of occurences.", 1, lfLeafCounter);
+        assertEquals("Lf has incorrect package name.",
+                "org.opendaylight.yang.gen.v1.urn.bit.union.in.leaf.rev130626.ParentContainer",
+                lfLeaf.getPackageName());
+
+        assertEquals("Lf generated TO has incorrect number of properties", 3, lfLeaf.getProperties().size());
+        containsAttributes(lfLeaf, true, true, true, new NameTypePattern("string", "String"));
+        containsAttributes(lfLeaf, true, false, true, new NameTypePattern("lf1", "Lf1"));
+
+        // nested types in leaf, contains Lf1?
+        assertNotNull("Lf1 TO wasn't found.", lf1Leaf);
+        assertEquals("Lf1 TO has incorrect number of occurences.", 1, lf1LeafCounter);
+        assertEquals("Lf1 has incorrect package name.",
+                "org.opendaylight.yang.gen.v1.urn.bit.union.in.leaf.rev130626.ParentContainer",
+                lf1Leaf.getPackageName());
+
+        assertEquals("Lf generated TO has incorrect number of properties", 4, lf1Leaf.getProperties().size());
+        containsAttributes(lf1Leaf, true, true, true, new NameTypePattern("uint32", "Long"));
+        containsAttributes(lf1Leaf, true, true, true, new NameTypePattern("int8", "Byte"));
+        containsAttributes(lf1Leaf, true, true, true, new NameTypePattern("string", "String"));
+        containsAttributes(lf1Leaf, true, false, true, new NameTypePattern("lf2", "Lf2"));
+
+        // nested types in leaf, contains Lf2?
+        assertNotNull("Lf2 TO wasn't found.", lf2Leaf);
+        assertEquals("Lf2 TO has incorrect number of occurences.", 1, lf2LeafCounter);
+        assertEquals("Lf2 has incorrect package name.",
+                "org.opendaylight.yang.gen.v1.urn.bit.union.in.leaf.rev130626.ParentContainer",
+                lf2Leaf.getPackageName());
+
+        assertEquals("Lf generated TO has incorrect number of properties", 2, lf2Leaf.getProperties().size());
+        containsAttributes(lf2Leaf, true, true, true, new NameTypePattern("string", "String"));
+        containsAttributes(lf2Leaf, true, true, true, new NameTypePattern("uint64", "BigInteger"));
+    }
+
+    @Test
+    public void testNestedTypesInTypedef() {
+
+        GeneratedTransferObject typeUnionTypedef = null;
+        int typeUnionTypedefCounter = 0;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("TypeUnion") && (genType instanceof GeneratedTransferObject)) {
+                    typeUnionTypedef = (GeneratedTransferObject) genType;
+                    typeUnionTypedefCounter++;
+                }
+            }
+        }
+
+        assertNotNull("TypeUnion TO wasn't found.", typeUnionTypedef);
+        assertEquals("TypeUnion TO has incorrect number of occurences.", 1, typeUnionTypedefCounter);
+
+        assertNotNull("TypeUnion TO wasn't found.", typeUnionTypedef);
+        assertEquals("TypeUnion TO has incorrect number of occurences.", 1, typeUnionTypedefCounter);
+        assertEquals("TypeUnion has incorrect package name.",
+                "org.opendaylight.yang.gen.v1.urn.bit.union.in.leaf.rev130626", typeUnionTypedef.getPackageName());
+
+        assertEquals("TypeUnion generated TO has incorrect number of properties", 3, typeUnionTypedef.getProperties()
+                .size());
+        containsAttributes(typeUnionTypedef, true, true, true, new NameTypePattern("string", "String"));
+        containsAttributes(typeUnionTypedef, true, false, true, new NameTypePattern("typeUnion1", "TypeUnion1"));
+
+        List<GeneratedType> nestedUnions = typeUnionTypedef.getEnclosedTypes();
+        assertEquals("Incorrect number of nested unions", 2, nestedUnions.size());
+
+        GeneratedTransferObject typeUnion1 = null;
+        int typeUnion1Counter = 0;
+        GeneratedTransferObject typeUnion2 = null;
+        int typeUnion2Counter = 0;
+        for (GeneratedType genType : nestedUnions) {
+            if (genType instanceof GeneratedTransferObject) {
+                if (genType.getName().equals("TypeUnion1")) {
+                    typeUnion1 = (GeneratedTransferObject) genType;
+                    typeUnion1Counter++;
+                } else if (genType.getName().equals("TypeUnion2")) {
+                    typeUnion2 = (GeneratedTransferObject) genType;
+                    typeUnion2Counter++;
+                }
+            }
+        }
+
+        assertNotNull("TypeUnion1 TO wasn't found.", typeUnion1);
+        assertEquals("TypeUnion1 TO has incorrect number of occurences.", 1, typeUnion1Counter);
+
+        assertEquals("TypeUnion1 has incorrect package name.",
+                "org.opendaylight.yang.gen.v1.urn.bit.union.in.leaf.rev130626", typeUnion1.getPackageName());
+
+        assertEquals("TypeUnion1 generated TO has incorrect number of properties", 4, typeUnion1.getProperties().size());
+
+        containsAttributes(typeUnion1, true, true, true, new NameTypePattern("uint32", "Long"));
+        containsAttributes(typeUnion1, true, true, true, new NameTypePattern("int8", "Byte"));
+        containsAttributes(typeUnion1, true, true, true, new NameTypePattern("string", "String"));
+        containsAttributes(typeUnion1, true, false, true, new NameTypePattern("typeUnion2", "TypeUnion2"));
+
+        assertNotNull("TypeUnion2 TO wasn't found.", typeUnion2);
+        assertEquals("TypeUnion2 TO has incorrect number of occurences.", 1, typeUnion2Counter);
+
+        assertEquals("TypeUnion2 has incorrect package name.",
+                "org.opendaylight.yang.gen.v1.urn.bit.union.in.leaf.rev130626", typeUnion2.getPackageName());
+
+        assertEquals("TypeUnion2 generated TO has incorrect number of properties", 2, typeUnion2.getProperties().size());
+        containsAttributes(typeUnion2, true, true, true, new NameTypePattern("string", "String"));
+        containsAttributes(typeUnion2, true, true, true, new NameTypePattern("uint64", "BigInteger"));
+
+    }
+
+    @Test
+    public void bitAndUnionEnclosingTest() {
+
+        assertNotNull("Parent container object wasn't found.", parentContainer);
+        containsMethods(parentContainer, new NameTypePattern("getLf", "Lf"));
+
+        GeneratedTransferObject bitLeaf = null;
+        GeneratedTransferObject unionLeaf = null;
+        List<GeneratedType> enclosedTypes = parentContainer.getEnclosedTypes();
+        for (GeneratedType genType : enclosedTypes) {
+            if (genType instanceof GeneratedTransferObject) {
+                if (genType.getName().equals("BitLeaf")) {
+                    bitLeaf = (GeneratedTransferObject) genType;
+                } else if (genType.getName().equals("UnionLeaf")) {
+                    unionLeaf = (GeneratedTransferObject) genType;
+                }
+            }
+        }
+
+        assertNotNull("BitLeaf TO wasn't found.", bitLeaf);
+        assertNotNull("UnionLeaf TO wasn't found.", unionLeaf);
+
+        assertEquals("BitLeaf has incorrect package name.",
+                "org.opendaylight.yang.gen.v1.urn.bit.union.in.leaf.rev130626.ParentContainer",
+                bitLeaf.getPackageName());
+        assertEquals("UnionLeaf has incorrect package name.",
+                "org.opendaylight.yang.gen.v1.urn.bit.union.in.leaf.rev130626.ParentContainer",
+                bitLeaf.getPackageName());
+
+        List<GeneratedProperty> propertiesBitLeaf = bitLeaf.getProperties();
+        GeneratedProperty firstBitProperty = null;
+        GeneratedProperty secondBitProperty = null;
+        GeneratedProperty thirdBitProperty = null;
+
+        for (GeneratedProperty genProperty : propertiesBitLeaf) {
+            if (genProperty.getName().equals("firstBit")) {
+                firstBitProperty = genProperty;
+            } else if (genProperty.getName().equals("secondBit")) {
+                secondBitProperty = genProperty;
+            } else if (genProperty.getName().equals("thirdBit")) {
+                thirdBitProperty = genProperty;
+            }
+        }
+
+        assertNotNull("firstBit property wasn't found", firstBitProperty);
+        assertNotNull("secondBit property wasn't found", secondBitProperty);
+        assertNotNull("thirdBit property wasn't found", thirdBitProperty);
+
+        assertEquals("firstBit property has incorrect type", "Boolean", firstBitProperty.getReturnType().getName());
+        assertEquals("secondBit property has incorrect type", "Boolean", secondBitProperty.getReturnType().getName());
+        assertEquals("thirdBit property has incorrect type", "Boolean", thirdBitProperty.getReturnType().getName());
+
+        GeneratedProperty uint32Property = null;
+        GeneratedProperty stringProperty = null;
+        GeneratedProperty uint8Property = null;
+        List<GeneratedProperty> propertiesUnionLeaf = unionLeaf.getProperties();
+        for (GeneratedProperty genProperty : propertiesUnionLeaf) {
+            if (genProperty.getName().equals("int32")) {
+                uint32Property = genProperty;
+            } else if (genProperty.getName().equals("string")) {
+                stringProperty = genProperty;
+            } else if (genProperty.getName().equals("uint8")) {
+                uint8Property = genProperty;
+            }
+        }
+
+        assertNotNull("uint32 property wasn't found", uint32Property);
+        assertNotNull("string property wasn't found", stringProperty);
+        assertNotNull("uint8 property wasn't found", uint8Property);
+
+        assertEquals("uint32 property has incorrect type", "Integer", uint32Property.getReturnType().getName());
+        assertEquals("string property has incorrect type", "String", stringProperty.getReturnType().getName());
+        assertEquals("uint8 property has incorrect type", "Short", uint8Property.getReturnType().getName());
+
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ChoiceCaseGenTypesTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ChoiceCaseGenTypesTest.java
new file mode 100644 (file)
index 0000000..e7c28d7
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.opendaylight.yangtools.sal.binding.generator.impl.SupportTestUtil.containsInterface;
+import static org.opendaylight.yangtools.sal.binding.generator.impl.SupportTestUtil.containsMethods;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class ChoiceCaseGenTypesTest extends AbstractTypesTest {
+
+    public ChoiceCaseGenTypesTest() {
+        super(ChoiceCaseGenTypesTest.class.getResource("/choice-case-type-test-models"));
+    }
+
+    private GeneratedType checkGeneratedType(final List<Type> genTypes, final String genTypeName, final String packageName, final int occurences) {
+        GeneratedType searchedGenType = null;
+        int searchedGenTypeCounter = 0;
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals(genTypeName) && genType.getPackageName().equals(packageName)) {
+                    searchedGenType = genType;
+                    searchedGenTypeCounter++;
+                }
+            }
+        }
+        assertNotNull("Generated type " + genTypeName + " wasn't found", searchedGenType);
+        assertEquals(genTypeName + " generated type has incorrect number of occurences.", occurences,
+                searchedGenTypeCounter);
+        return searchedGenType;
+
+    }
+
+    private GeneratedType checkGeneratedType(final List<Type> genTypes, final String genTypeName, final String packageName) {
+        return checkGeneratedType(genTypes, genTypeName, packageName, 1);
+    }
+
+    @Test
+    public void choiceCaseResolvingTypeTest() throws IOException {
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull("context is null", context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull("genTypes is null", genTypes);
+        assertFalse("genTypes is empty", genTypes.isEmpty());
+
+        // test for file choice-monitoring
+        String pcgPref = "org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.choice.monitoring.rev130701.netconf.state.datastores.datastore.locks";
+        GeneratedType genType = null;
+
+        checkGeneratedType(genTypes, "LockType", pcgPref); // choice
+
+        genType = checkGeneratedType(genTypes, "GlobalLock", pcgPref + ".lock.type"); // case
+        containsMethods(genType, new NameTypePattern("getGlobalLock", "GlobalLock"));
+        containsInterface("LockType", genType);
+
+        genType = checkGeneratedType(genTypes, "PartialLock", pcgPref + ".lock.type"); // case
+        containsMethods(genType, new NameTypePattern("getPartialLock", "List<PartialLock>"));
+        containsInterface("LockType", genType);
+
+        genType = checkGeneratedType(genTypes, "Fingerprint", pcgPref + ".lock.type"); // case
+        containsMethods(genType, new NameTypePattern("getAlgorithmAndHash", "AlgorithmAndHash"));
+        containsInterface("LockType", genType);
+
+        genType = checkGeneratedType(genTypes, "AlgorithmAndHash", pcgPref + ".lock.type.fingerprint"); // choice
+
+        genType = checkGeneratedType(genTypes, "Md5", pcgPref + ".lock.type.fingerprint.algorithm.and.hash"); // case
+        containsMethods(genType, new NameTypePattern("getMd5", "TlsFingerprintType"));
+        containsInterface("AlgorithmAndHash", genType);
+
+        genType = checkGeneratedType(genTypes, "Sha1", pcgPref + ".lock.type.fingerprint.algorithm.and.hash"); // case
+        containsMethods(genType, new NameTypePattern("getSha1", "TlsFingerprintType"));
+        containsInterface("AlgorithmAndHash", genType);
+
+        genType = checkGeneratedType(genTypes, "Sha224", pcgPref + ".lock.type.fingerprint.algorithm.and.hash"); // case
+        containsMethods(genType, new NameTypePattern("getSha224", "TlsFingerprintType"));
+        containsInterface("AlgorithmAndHash", genType);
+
+        genType = checkGeneratedType(genTypes, "Sha256", pcgPref + ".lock.type.fingerprint.algorithm.and.hash"); // case
+        containsMethods(genType, new NameTypePattern("getSha256", "TlsFingerprintType"));
+        containsInterface("AlgorithmAndHash", genType);
+
+        genType = checkGeneratedType(genTypes, "Sha384", pcgPref + ".lock.type.fingerprint.algorithm.and.hash"); // case
+        containsMethods(genType, new NameTypePattern("getSha384", "TlsFingerprintType"));
+        containsInterface("AlgorithmAndHash", genType);
+
+        genType = checkGeneratedType(genTypes, "Sha512", pcgPref + ".lock.type.fingerprint.algorithm.and.hash"); // case
+        containsMethods(genType, new NameTypePattern("getSha512", "TlsFingerprintType"));
+        containsInterface("AlgorithmAndHash", genType);
+
+        // test for file augment-monitoring
+        // augment
+        // "/nm:netconf-state/nm:datastores/nm:datastore/nm:locks/nm:lock-type"
+        pcgPref = "org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.augment.monitoring.rev130701";
+        genType = null;
+
+        genType = checkGeneratedType(genTypes, "AutonomousLock", pcgPref
+                + ".netconf.state.datastores.datastore.locks.lock.type"); // choice
+        containsMethods(genType, new NameTypePattern("getAutonomousDef", "AutonomousDef"));
+        containsInterface("LockType", genType);
+
+        genType = checkGeneratedType(genTypes, "AnonymousLock", pcgPref
+                + ".netconf.state.datastores.datastore.locks.lock.type"); // choice
+        containsMethods(genType, new NameTypePattern("getLockTime", "Long"));
+        containsInterface("LockType", genType);
+
+        genType = checkGeneratedType(genTypes, "LeafAugCase", pcgPref
+                + ".netconf.state.datastores.datastore.locks.lock.type"); // choice
+        containsMethods(genType, new NameTypePattern("getLeafAugCase", "String"));
+        containsInterface("LockType", genType);
+
+        // augment
+        // "/nm:netconf-state/nm:datastores/nm:datastore/nm:locks/nm:lock-type/nm:partial-lock"
+        // {
+        genType = checkGeneratedType(genTypes, "PartialLock1", pcgPref); // case
+        containsMethods(genType, new NameTypePattern("getAugCaseByChoice", "AugCaseByChoice"));
+        containsInterface("Augmentation<PartialLock>", genType);
+
+        genType = checkGeneratedType(genTypes, "AugCaseByChoice", pcgPref
+                + ".netconf.state.datastores.datastore.locks.lock.type.partial.lock"); // choice
+
+        genType = checkGeneratedType(genTypes, "Foo", pcgPref
+                + ".netconf.state.datastores.datastore.locks.lock.type.partial.lock.aug._case.by.choice"); // case
+        containsMethods(genType, new NameTypePattern("getFoo", "String"));
+        containsInterface("AugCaseByChoice", genType);
+
+        genType = checkGeneratedType(genTypes, "Bar", pcgPref
+                + ".netconf.state.datastores.datastore.locks.lock.type.partial.lock.aug._case.by.choice"); // case
+        containsMethods(genType, new NameTypePattern("isBar", "Boolean"));
+        containsInterface("AugCaseByChoice", genType);
+
+        // augment "/nm:netconf-state/nm:datastores/nm:datastore" {
+        genType = checkGeneratedType(genTypes, "Datastore1", pcgPref);
+        containsMethods(genType, new NameTypePattern("getStorageFormat", "StorageFormat"));
+        containsInterface("Augmentation<Datastore>", genType);
+
+        genType = checkGeneratedType(genTypes, "StorageFormat", pcgPref + ".netconf.state.datastores.datastore"); // choice
+
+        genType = checkGeneratedType(genTypes, "UnknownFiles", pcgPref
+                + ".netconf.state.datastores.datastore.storage.format"); // case
+        containsMethods(genType, new NameTypePattern("getFiles", "List<Files>"));
+        containsInterface("StorageFormat", genType);
+
+        genType = checkGeneratedType(genTypes, "Xml", pcgPref + ".netconf.state.datastores.datastore.storage.format"); // case
+        containsMethods(genType, new NameTypePattern("getXmlDef", "XmlDef"));
+        containsInterface("StorageFormat", genType);
+
+        genType = checkGeneratedType(genTypes, "Yang", pcgPref + ".netconf.state.datastores.datastore.storage.format"); // case
+        containsMethods(genType, new NameTypePattern("getYangFileName", "String"));
+        containsInterface("StorageFormat", genType);
+
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ControllerTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ControllerTest.java
new file mode 100644 (file)
index 0000000..0fde632
--- /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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class ControllerTest {
+
+    @Test
+    public void controllerAugmentationTest() throws Exception {
+        File cn = new File(getClass().getResource("/controller-models/controller-network.yang").toURI());
+        File co = new File(getClass().getResource("/controller-models/controller-openflow.yang").toURI());
+        File ietfInetTypes = new File(getClass().getResource("/ietf/ietf-inet-types.yang").toURI());
+
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(cn, co, ietfInetTypes));
+        assertNotNull("Schema Context is null", context);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull(genTypes);
+        assertTrue(!genTypes.isEmpty());
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/DefinedTypesProviderTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/DefinedTypesProviderTest.java
new file mode 100644 (file)
index 0000000..6a69c1e
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+public class DefinedTypesProviderTest {
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ExtendedTypedefTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ExtendedTypedefTest.java
new file mode 100644 (file)
index 0000000..329934f
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.yang.types.BaseYangTypes;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class ExtendedTypedefTest {
+
+    @Test
+    public void constantGenerationTest() throws Exception {
+        File abstractTopology = new File(getClass().getResource("/typedef-of-typedef/typedef_of_typedef.yang").toURI());
+        File ietfInetTypes = new File(getClass().getResource("/ietf/ietf-inet-types.yang").toURI());
+
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(abstractTopology, ietfInetTypes));
+        assertNotNull("Schema Context is null", context);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        GeneratedTransferObject simpleTypedef4 = null;
+        GeneratedTransferObject extendedTypedefUnion = null;
+        GeneratedTransferObject unionTypedef = null;
+        GeneratedTransferObject typedefFromImport = null;
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedTransferObject) {
+                if (type.getName().equals("SimpleTypedef4")) {
+                    simpleTypedef4 = (GeneratedTransferObject) type;
+                } else if (type.getName().equals("ExtendedTypedefUnion")) {
+                    extendedTypedefUnion = (GeneratedTransferObject) type;
+                } else if (type.getName().equals("UnionTypedef")) {
+                    unionTypedef = (GeneratedTransferObject) type;
+                } else if (type.getName().equals("TypedefFromImport")) {
+                    typedefFromImport = (GeneratedTransferObject) type;
+                }
+            }
+        }
+
+        // typedef-from-import
+        assertNotNull("TypedefFromImport not found", typedefFromImport);
+        List<GeneratedProperty> properties = typedefFromImport.getProperties();
+        assertTrue("Properties of TypedefFromImport should be empty", properties.isEmpty());
+        assertEquals("TypedefFromImport should be extended", "Ipv4Address", typedefFromImport.getSuperType().getName());
+
+        // simple-typedef4
+        assertNotNull("SimpleTypedef4 not found", simpleTypedef4);
+        assertNotNull("ExtendedTypedefUnion not found", extendedTypedefUnion);
+        assertNotNull("UnionTypedef", unionTypedef);
+
+        properties = simpleTypedef4.getProperties();
+        assertTrue("SimpleTypedef4 shouldn't have properties.", properties.isEmpty());
+
+        GeneratedTransferObject extendTO = simpleTypedef4.getSuperType();
+        assertNotNull("SimpleTypedef4 should have extend.", extendTO);
+        assertEquals("Incorrect extension for SimpleTypedef4.", "SimpleTypedef3", extendTO.getName());
+        properties = extendTO.getProperties();
+        assertTrue("SimpleTypedef3 shouldn't have properties.", properties.isEmpty());
+
+        extendTO = extendTO.getSuperType();
+        assertNotNull("SimpleTypedef3 should have extend.", extendTO);
+        assertEquals("Incorrect extension for SimpleTypedef3.", "SimpleTypedef2", extendTO.getName());
+        properties = extendTO.getProperties();
+        assertTrue("SimpleTypedef2 shouldn't have properties.", properties.isEmpty());
+
+        extendTO = extendTO.getSuperType();
+        assertNotNull("SimpleTypedef2 should have extend.", extendTO);
+        assertEquals("SimpleTypedef2 should be extended with SimpleTypedef1.", "SimpleTypedef1", extendTO.getName());
+        properties = extendTO.getProperties();
+        assertEquals("Incorrect number of properties in class SimpleTypedef1.", 1, properties.size());
+
+        assertEquals("Incorrect property's name", "value", properties.get(0).getName());
+        assertEquals("Property's incorrect type", BaseYangTypes.UINT8_TYPE, properties.get(0).getReturnType());
+
+        extendTO = extendTO.getSuperType();
+        assertNull("SimpleTypedef1 shouldn't have extend.", extendTO);
+
+        // extended-typedef-union
+        assertNotNull("ExtendedTypedefUnion object not found", extendedTypedefUnion);
+        properties = extendedTypedefUnion.getProperties();
+        assertTrue("ExtendedTypedefUnion shouldn't have any property", properties.isEmpty());
+
+        extendTO = extendedTypedefUnion.getSuperType();
+        assertEquals("Incorrect extension fo ExtendedTypedefUnion.", "UnionTypedef", extendTO.getName());
+        assertNull("UnionTypedef shouldn't be extended", extendTO.getSuperType());
+        assertEquals("Incorrect number of properties for UnionTypedef.", 5, extendTO.getProperties().size());
+
+        GeneratedProperty simpleTypedef4Property = null;
+        GeneratedProperty simpleTypedef1Property = null;
+        GeneratedProperty byteTypeProperty = null;
+        GeneratedProperty typedefEnumFruitProperty = null;
+        for (GeneratedProperty genProperty : extendTO.getProperties()) {
+            if (genProperty.getName().equals("simpleTypedef1")) {
+                simpleTypedef1Property = genProperty;
+            } else if (genProperty.getName().equals("simpleTypedef4")) {
+                simpleTypedef4Property = genProperty;
+            } else if (genProperty.getName().equals("byteType")) {
+                byteTypeProperty = genProperty;
+            } else if (genProperty.getName().equals("typedefEnumFruit")) {
+                typedefEnumFruitProperty = genProperty;
+            }
+        }
+
+        assertNotNull("simpleTypedef4 property not found in UnionTypedef", simpleTypedef4Property);
+        assertNotNull("simpleTypedef1 property not found in UnionTypedef", simpleTypedef1Property);
+        assertNotNull("byteType property not found in UnionTypedef", byteTypeProperty);
+        assertNotNull("typedefEnumFruit property not found in UnionTypedef", typedefEnumFruitProperty);
+
+        assertEquals("Incorrect type for property simpleTypedef4.", "SimpleTypedef4", simpleTypedef4Property
+                .getReturnType().getName());
+        assertEquals("Incorrect type for property simpleTypedef1.", "SimpleTypedef1", simpleTypedef1Property
+                .getReturnType().getName());
+        assertEquals("Incorrect type for property byteType.", "ByteType", byteTypeProperty.getReturnType().getName());
+        assertEquals("Incorrect type for property typedefEnumFruit.", "TypedefEnumFruit", typedefEnumFruitProperty
+                .getReturnType().getName());
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GenEnumResolvingTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GenEnumResolvingTest.java
new file mode 100644 (file)
index 0000000..1227d70
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class GenEnumResolvingTest {
+
+    @Test
+    public void testLeafEnumResolving() throws URISyntaxException, IOException {
+        File ietfInterfaces = new File(getClass().getResource("/enum-test-models/ietf-interfaces@2012-11-15.yang")
+                .toURI());
+        File ianaIfTypeModel = new File(getClass().getResource("/ietf/iana-if-type.yang").toURI());
+
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(ietfInterfaces, ianaIfTypeModel));
+        assertTrue(context != null);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+        assertTrue(genTypes != null);
+
+        assertEquals("Expected count of all Generated Types", 6, genTypes.size());
+
+        GeneratedType genInterface = null;
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedType) {
+                if (type.getName().equals("Interface")) {
+                    genInterface = (GeneratedType) type;
+                }
+            }
+        }
+        assertNotNull("Generated Type Interface is not present in list of Generated Types", genInterface);
+
+        Enumeration linkUpDownTrapEnable = null;
+        Enumeration operStatus = null;
+        final List<Enumeration> enums = genInterface.getEnumerations();
+        assertNotNull("Generated Type Interface cannot contain NULL reference to Enumeration types!", enums);
+        assertEquals("Generated Type Interface MUST contain 2 Enumeration Types", 2, enums.size());
+        for (final Enumeration e : enums) {
+            if (e.getName().equals("LinkUpDownTrapEnable")) {
+                linkUpDownTrapEnable = e;
+            } else if (e.getName().equals("OperStatus")) {
+                operStatus = e;
+            }
+        }
+
+        assertNotNull("Expected Enum LinkUpDownTrapEnable, but was NULL!", linkUpDownTrapEnable);
+        assertNotNull("Expected Enum OperStatus, but was NULL!", operStatus);
+
+        assertNotNull("Enum LinkUpDownTrapEnable MUST contain Values definition not NULL reference!",
+                linkUpDownTrapEnable.getValues());
+        assertNotNull("Enum OperStatus MUST contain Values definition not NULL reference!", operStatus.getValues());
+        assertEquals("Enum LinkUpDownTrapEnable MUST contain 2 values!", 2, linkUpDownTrapEnable.getValues().size());
+        assertEquals("Enum OperStatus MUST contain 7 values!", 7, operStatus.getValues().size());
+
+        final List<MethodSignature> methods = genInterface.getMethodDefinitions();
+
+        assertNotNull("Generated Interface cannot contain NULL reference for Method Signature Definitions!", methods);
+
+        assertEquals("Expected count of method signature definitions is 15", 15, methods.size());
+        Enumeration ianaIfType = null;
+        for (final MethodSignature method : methods) {
+            if (method.getName().equals("getType")) {
+                if (method.getReturnType() instanceof Enumeration) {
+                    ianaIfType = (Enumeration) method.getReturnType();
+                }
+            }
+        }
+
+        assertNotNull("Method getType MUST return Enumeration Type not NULL reference!", ianaIfType);
+        assertEquals("Enumeration getType MUST contain 272 values!", 272, ianaIfType.getValues().size());
+    }
+
+    @Test
+    public void testTypedefEnumResolving() throws URISyntaxException, IOException {
+        File ianaIfType = new File(getClass().getResource("/ietf/iana-if-type.yang").toURI());
+        final SchemaContext context = new YangParserImpl().parseFiles(Collections.singleton(ianaIfType));
+        assertTrue(context != null);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+        assertTrue(genTypes != null);
+        assertEquals(1, genTypes.size());
+
+        final Type type = genTypes.get(0);
+        assertTrue(type instanceof Enumeration);
+
+        final Enumeration enumer = (Enumeration) type;
+        assertEquals("Enumeration type MUST contain 272 values!", 272, enumer.getValues().size());
+    }
+
+    @Test
+    public void testLeafrefEnumResolving() throws URISyntaxException, IOException {
+        File abstractTopology = new File(getClass().getResource("/enum-test-models/abstract-topology@2013-02-08.yang")
+                .toURI());
+        File ietfInterfaces = new File(getClass().getResource("/enum-test-models/ietf-interfaces@2012-11-15.yang")
+                .toURI());
+        File ianaIfType = new File(getClass().getResource("/ietf/iana-if-type.yang").toURI());
+
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(abstractTopology, ietfInterfaces,
+                ianaIfType));
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+        assertNotNull(genTypes);
+        assertTrue(!genTypes.isEmpty());
+
+        GeneratedType genInterface = null;
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedType) {
+                if (type.getPackageName().equals(
+                        "org.opendaylight.yang.gen.v1.urn.model._abstract.topology.rev130208.topology.interfaces")
+                        && type.getName().equals("Interface")) {
+                    genInterface = (GeneratedType) type;
+                }
+            }
+        }
+        assertNotNull("Generated Type Interface is not present in list of Generated Types", genInterface);
+
+        Type linkUpDownTrapEnable = null;
+        Type operStatus = null;
+        final List<MethodSignature> methods = genInterface.getMethodDefinitions();
+        assertNotNull("Generated Type Interface cannot contain NULL reference to Enumeration types!", methods);
+        assertEquals("Generated Type Interface MUST contain 5 Methods ", 5, methods.size());
+        for (final MethodSignature method : methods) {
+            if (method.getName().equals("getLinkUpDownTrapEnable")) {
+                linkUpDownTrapEnable = method.getReturnType();
+            } else if (method.getName().equals("getOperStatus")) {
+                operStatus = method.getReturnType();
+            }
+        }
+
+        assertNotNull("Expected Referenced Enum LinkUpDownTrapEnable, but was NULL!", linkUpDownTrapEnable);
+        assertTrue("Expected LinkUpDownTrapEnable of type Enumeration", linkUpDownTrapEnable instanceof Enumeration);
+        assertEquals(linkUpDownTrapEnable.getPackageName(),
+                "org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev121115.interfaces.Interface");
+
+        assertNotNull("Expected Referenced Enum OperStatus, but was NULL!", operStatus);
+        assertTrue("Expected OperStatus of type Enumeration", operStatus instanceof Enumeration);
+        assertEquals(operStatus.getPackageName(),
+                "org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev121115.interfaces.Interface");
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GenTypesSubSetTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GenTypesSubSetTest.java
new file mode 100644 (file)
index 0000000..5f3988a
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class GenTypesSubSetTest {
+
+    @Test
+    public void genTypesFromSubsetOfTwoModulesTest() throws Exception {
+        File abstractTopology = new File(getClass().getResource(
+                "/leafref-test-models/abstract-topology@2013-02-08.yang").toURI());
+        File ietfInterfaces = new File(getClass().getResource("/ietf/ietf-interfaces.yang").toURI());
+        File ietfInetTypes = new File(getClass().getResource("/ietf/ietf-inet-types.yang").toURI());
+        File ietfYangTypes = new File(getClass().getResource("/ietf/ietf-yang-types.yang").toURI());
+
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(abstractTopology, ietfInterfaces,
+                ietfInetTypes, ietfYangTypes));
+        Set<Module> modules = context.getModules();
+
+        final Set<Module> toGenModules = new HashSet<>();
+        for (final Module module : modules) {
+            if (module.getName().equals("abstract-topology")) {
+                toGenModules.add(module);
+            } else if (module.getName().equals("ietf-interfaces")) {
+                toGenModules.add(module);
+            }
+        }
+
+        assertEquals("Set of to Generate Modules must contain 2 modules", 2, toGenModules.size());
+        assertNotNull("Schema Context is null", context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context, toGenModules);
+        assertNotNull("genTypes is null", genTypes);
+        assertFalse("genTypes is empty", genTypes.isEmpty());
+        assertEquals("Expected Generated Types from provided sub set of " + "modules should be 23!", 23,
+                genTypes.size());
+    }
+
+    @Test
+    public void genTypesFromSubsetOfThreeModulesTest() throws Exception {
+        File abstractTopology = new File(getClass().getResource(
+                "/leafref-test-models/abstract-topology@2013-02-08.yang").toURI());
+        File ietfInterfaces = new File(getClass().getResource("/ietf/ietf-interfaces.yang").toURI());
+        File ietfInetTypes = new File(getClass().getResource("/ietf/ietf-inet-types.yang").toURI());
+        File ietfYangTypes = new File(getClass().getResource("/ietf/ietf-yang-types.yang").toURI());
+        File ianaIfType = new File(getClass().getResource("/ietf/iana-if-type.yang").toURI());
+
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(abstractTopology, ietfInterfaces,
+                ietfInetTypes, ietfYangTypes, ianaIfType));
+        assertNotNull("Schema Context is null", context);
+        final Set<Module> modules = context.getModules();
+
+        final Set<Module> toGenModules = new HashSet<>();
+        for (final Module module : modules) {
+            if (module.getName().equals("abstract-topology")) {
+                toGenModules.add(module);
+            } else if (module.getName().equals("ietf-interfaces")) {
+                toGenModules.add(module);
+            } else if (module.getName().equals("iana-if-type")) {
+                toGenModules.add(module);
+            }
+        }
+        assertEquals("Set of to Generate Modules must contain 3 modules", 3, toGenModules.size());
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context, toGenModules);
+        assertNotNull("genTypes is null", genTypes);
+        assertFalse("genTypes is empty", genTypes.isEmpty());
+        assertEquals("Expected Generated Types", 24, genTypes.size());
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GenerateInnerClassForBitsAndUnionInLeavesTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GenerateInnerClassForBitsAndUnionInLeavesTest.java
new file mode 100644 (file)
index 0000000..d48f736
--- /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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class GenerateInnerClassForBitsAndUnionInLeavesTest {
+
+    private SchemaContext resolveSchemaContextFromFiles(final URI... yangFiles) throws Exception {
+        final YangContextParser parser = new YangParserImpl();
+
+        final List<File> inputFiles = new ArrayList<File>();
+        for (URI yangFile : yangFiles) {
+            inputFiles.add(new File(yangFile));
+        }
+
+        return parser.parseFiles(inputFiles);
+    }
+
+    @Test
+    public void testInnerClassCreationForBitsAndUnionsInLeafes() throws Exception {
+        final URI yangTypesPath = getClass().getResource("/bit_and_union_in_leaf.yang").toURI();
+
+        final SchemaContext context = resolveSchemaContextFromFiles(yangTypesPath);
+        assertTrue(context != null);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+        assertTrue(genTypes != null);
+
+        boolean parentContainerFound = false;
+        boolean bitLeafTOFound = false;
+        boolean unionLeafTOFound = false;
+
+        boolean firstBitPropertyFound = false;
+        boolean secondBitPropertyFound = false;
+        boolean thirdBitPropertyFound = false;
+
+        boolean firstBitPropertyTypeOK = false;
+        boolean secondBitPropertyTypeOK = false;
+        boolean thirdBitPropertyTypeOK = false;
+
+        boolean int32UnionPropertyFound = false;
+        boolean int32UnionPropertyTypeOK = false;
+        boolean stringUnionPropertyFound = false;
+        boolean stringUnionPropertyTypeOK = false;
+        boolean uint8UnionPropertyFound = false;
+        boolean uint8UnionPropertyTypeOK = false;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                if (type.getName().equals("ParentContainer")) {
+                    parentContainerFound = true;
+                    GeneratedType parentContainer = (GeneratedType) type;
+                    List<GeneratedType> enclosedTypes = parentContainer.getEnclosedTypes();
+                    for (GeneratedType genType : enclosedTypes) {
+                        if (genType instanceof GeneratedTransferObject) {
+                            if (genType.getName().equals("BitLeaf")) {
+                                bitLeafTOFound = true;
+                                GeneratedTransferObject bitLeafTO = (GeneratedTransferObject) genType;
+
+                                List<GeneratedProperty> bitLeafProperties = bitLeafTO.getProperties();
+                                for (GeneratedProperty bitLeafProperty : bitLeafProperties) {
+                                    String bitLeafPropertyType = bitLeafProperty.getReturnType().getName();
+                                    if (bitLeafProperty.getName().equals("firstBit")) {
+                                        firstBitPropertyFound = true;
+                                        if (bitLeafPropertyType.equals("Boolean")) {
+                                            firstBitPropertyTypeOK = true;
+                                        }
+                                    } else if (bitLeafProperty.getName().equals("secondBit")) {
+                                        secondBitPropertyFound = true;
+                                        if (bitLeafPropertyType.equals("Boolean")) {
+                                            secondBitPropertyTypeOK = true;
+                                        }
+                                    } else if (bitLeafProperty.getName().equals("thirdBit")) {
+                                        thirdBitPropertyFound = true;
+                                        if (bitLeafPropertyType.equals("Boolean")) {
+                                            thirdBitPropertyTypeOK = true;
+                                        }
+                                    }
+
+                                }
+
+                            } else if (genType.getName().equals("UnionLeaf")) {
+                                unionLeafTOFound = true;
+                                GeneratedTransferObject unionLeafTO = (GeneratedTransferObject) genType;
+
+                                List<GeneratedProperty> unionLeafProperties = unionLeafTO.getProperties();
+                                for (GeneratedProperty unionLeafProperty : unionLeafProperties) {
+                                    String unionLeafPropertyType = unionLeafProperty.getReturnType().getName();
+                                    if (unionLeafProperty.getName().equals("int32")) {
+                                        int32UnionPropertyFound = true;
+                                        if (unionLeafPropertyType.equals("Integer")) {
+                                            int32UnionPropertyTypeOK = true;
+                                        }
+                                    } else if (unionLeafProperty.getName().equals("string")) {
+                                        stringUnionPropertyFound = true;
+                                        if (unionLeafPropertyType.equals("String")) {
+                                            stringUnionPropertyTypeOK = true;
+                                        }
+                                    } else if (unionLeafProperty.getName().equals("uint8")) {
+                                        uint8UnionPropertyFound = true;
+                                        if (unionLeafPropertyType.equals("Short")) {
+                                            uint8UnionPropertyTypeOK = true;
+                                        }
+                                    }
+
+                                }
+
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        assertTrue(parentContainerFound);
+
+        assertTrue(bitLeafTOFound);
+        assertTrue(firstBitPropertyFound);
+        assertTrue(secondBitPropertyFound);
+        assertTrue(thirdBitPropertyFound);
+
+        assertTrue(firstBitPropertyTypeOK);
+        assertTrue(secondBitPropertyTypeOK);
+        assertTrue(thirdBitPropertyTypeOK);
+
+        assertTrue(unionLeafTOFound);
+        assertTrue(int32UnionPropertyFound);
+        assertTrue(int32UnionPropertyTypeOK);
+        assertTrue(stringUnionPropertyFound);
+        assertTrue(stringUnionPropertyTypeOK);
+        assertTrue(uint8UnionPropertyFound);
+        assertTrue(uint8UnionPropertyTypeOK);
+
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesBitsTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesBitsTest.java
new file mode 100644 (file)
index 0000000..16abfd7
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+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 java.net.URI;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature.Parameter;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class GeneratedTypesBitsTest {
+
+
+    @Test
+    public void testGeneretedTypesBitsTest() throws Exception {
+        final URI yangTypesPath = getClass().getResource("/simple-bits-demo.yang").toURI();
+
+        final SchemaContext context = SupportTestUtil.resolveSchemaContextFromFiles(yangTypesPath);
+        assertTrue(context != null);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+        assertTrue(genTypes != null);
+
+        List<MethodSignature> methodSignaturesList = null;
+
+        boolean leafParentFound = false;
+
+        boolean byteTypeFound = false;
+        int classPropertiesNumb = 0;
+        int toStringPropertiesNum = 0;
+        int equalPropertiesNum = 0;
+        int hashPropertiesNum = 0;
+
+        String nameReturnParamType = "";
+        boolean getByteLeafMethodFound = false;
+        boolean setByteLeafMethodFound = false;
+        int setByteLeafMethodParamNum = 0;
+
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedTransferObject) { // searching for
+                                                           // ByteType
+                final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
+                if (genTO.getName().equals("ByteType")) {
+                    byteTypeFound = true;
+                    List<GeneratedProperty> genProperties = genTO.getProperties();
+                    classPropertiesNumb = genProperties.size();
+
+                    genProperties = null;
+                    genProperties = genTO.getToStringIdentifiers();
+                    toStringPropertiesNum = genProperties.size();
+
+                    genProperties = null;
+                    genProperties = genTO.getEqualsIdentifiers();
+                    equalPropertiesNum = genProperties.size();
+
+                    genProperties = null;
+                    genProperties = genTO.getHashCodeIdentifiers();
+                    hashPropertiesNum = genProperties.size();
+
+                }
+            } else if (type instanceof GeneratedType) { // searching for
+                                                        // interface
+                                                        // LeafParameterContainer
+                final GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("LeafParentContainer")) {
+                    leafParentFound = true;
+                    // check of methods
+                    methodSignaturesList = genType.getMethodDefinitions();
+                    if (methodSignaturesList != null) {
+                        for (MethodSignature methodSignature : methodSignaturesList) { // loop
+                                                                                       // through
+                                                                                       // all
+                                                                                       // methods
+                            if (methodSignature.getName().equals("getByteLeaf")) {
+                                getByteLeafMethodFound = true;
+
+                                nameReturnParamType = methodSignature.getReturnType().getName();
+                            } else if (methodSignature.getName().equals("setByteLeaf")) {
+                                setByteLeafMethodFound = true;
+
+                                List<Parameter> parameters = methodSignature.getParameters();
+                                setByteLeafMethodParamNum = parameters.size();
+                            }
+
+                        }
+                    }
+                }
+            }
+
+        }
+
+        assertTrue(byteTypeFound);
+
+        assertEquals(classPropertiesNumb,8);
+
+        assertEquals(toStringPropertiesNum,8);
+        assertEquals(equalPropertiesNum,8);
+        assertEquals(hashPropertiesNum,8);
+        assertTrue(leafParentFound);
+
+        assertNotNull(methodSignaturesList);
+
+        assertTrue(getByteLeafMethodFound);
+        assertEquals(nameReturnParamType,"ByteType");
+
+        assertFalse(setByteLeafMethodFound);
+        assertEquals(0, setByteLeafMethodParamNum);
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesLeafrefTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesLeafrefTest.java
new file mode 100644 (file)
index 0000000..70d242e
--- /dev/null
@@ -0,0 +1,267 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.fail;
+
+import com.google.common.io.ByteSource;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class GeneratedTypesLeafrefTest {
+
+    public static Set<Module> loadModules(final Collection<InputStream> input) throws IOException,
+            YangSyntaxErrorException {
+        Collection<ByteSource> sources = BuilderUtils.streamsToByteSources(input);
+        final YangContextParser parser = new YangParserImpl();
+        SchemaContext ctx = parser.parseSources(sources);
+        return ctx.getModules();
+    }
+
+    private SchemaContext resolveSchemaContextFromFiles(final URI... yangFiles) throws IOException {
+        final YangContextParser parser = new YangParserImpl();
+
+        final List<File> inputFiles = new ArrayList<File>();
+        for (URI yangFile : yangFiles) {
+            inputFiles.add(new File(yangFile));
+        }
+
+        return parser.parseFiles(inputFiles);
+    }
+
+    @Test
+    public void testLeafrefResolving() throws URISyntaxException, IOException {
+        File abstractTopology = new File(getClass().getResource(
+                "/leafref-test-models/abstract-topology@2013-02-08.yang").toURI());
+        File ietfInterfaces = new File(getClass().getResource("/ietf/ietf-interfaces.yang").toURI());
+        File ietfInetTypes = new File(getClass().getResource("/ietf/ietf-inet-types.yang").toURI());
+        File ietfYangTypes = new File(getClass().getResource("/ietf/ietf-yang-types.yang").toURI());
+
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(abstractTopology, ietfInterfaces,
+                ietfInetTypes, ietfYangTypes));
+        assertNotNull(context);
+        assertEquals(4, context.getModules().size());
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertEquals(54, genTypes.size());
+        assertNotNull(genTypes);
+
+        GeneratedTransferObject gtIfcKey = null;
+        GeneratedType gtIfc = null;
+        GeneratedType gtNetworkLink = null;
+        GeneratedType gtSource = null;
+        GeneratedType gtDest = null;
+        GeneratedType gtTunnel = null;
+        GeneratedTransferObject gtTunnelKey = null;
+        GeneratedType gtTopology = null;
+        for (final Type type : genTypes) {
+            String name = type.getName();
+            if ("InterfaceKey".equals(name)) {
+                gtIfcKey = (GeneratedTransferObject) type;
+            } else if ("Interface".equals(name)) {
+                gtIfc = (GeneratedType) type;
+            } else if ("NetworkLink".equals(name)) {
+                gtNetworkLink = (GeneratedType) type;
+            } else if ("SourceNode".equals(name)) {
+                gtSource = (GeneratedType) type;
+            } else if ("DestinationNode".equals(name)) {
+                gtDest = (GeneratedType) type;
+            } else if ("Tunnel".equals(name)) {
+                gtTunnel = (GeneratedType) type;
+            } else if ("TunnelKey".equals(name)) {
+                gtTunnelKey = (GeneratedTransferObject) type;
+            } else if ("Topology".equals(name)) {
+                gtTopology = (GeneratedType) type;
+            }
+        }
+
+        assertNotNull(gtIfcKey);
+        assertNotNull(gtIfc);
+        assertNotNull(gtNetworkLink);
+        assertNotNull(gtSource);
+        assertNotNull(gtDest);
+        assertNotNull(gtTunnel);
+        assertNotNull(gtTunnelKey);
+        assertNotNull(gtTopology);
+
+        // Topology
+        final List<MethodSignature> gtTopoMethods = gtTopology.getMethodDefinitions();
+        assertNotNull(gtTopoMethods);
+        MethodSignature condLeafref = null;
+        for (final MethodSignature method : gtTopoMethods) {
+            if (method.getName().equals("getCondLeafref")) {
+                condLeafref = method;
+            }
+        }
+        assertNotNull(condLeafref);
+        Type condLeafRT = condLeafref.getReturnType();
+        assertNotNull(condLeafRT);
+        assertEquals("java.lang.Object", condLeafRT.getFullyQualifiedName());
+
+        // InterfaceId
+        final List<GeneratedProperty> gtIfcKeyProps = gtIfcKey.getProperties();
+        assertNotNull(gtIfcKeyProps);
+        GeneratedProperty ifcIdProp = null;
+        for (final GeneratedProperty property : gtIfcKeyProps) {
+            if (property.getName().equals("interfaceId")) {
+                ifcIdProp = property;
+            }
+        }
+        assertNotNull(ifcIdProp);
+        Type ifcIdPropType = ifcIdProp.getReturnType();
+        assertNotNull(ifcIdPropType);
+        assertEquals("java.lang.String", ifcIdPropType.getFullyQualifiedName());
+
+        // Interface
+        final List<MethodSignature> gtIfcMethods = gtIfc.getMethodDefinitions();
+        assertNotNull(gtIfcMethods);
+        MethodSignature getIfcKey = null;
+        MethodSignature getHigherLayerIf = null;
+        for (final MethodSignature method : gtIfcMethods) {
+            if (method.getName().equals("getKey")) {
+                getIfcKey = method;
+            } else if (method.getName().equals("getHigherLayerIf")) {
+                getHigherLayerIf = method;
+            }
+        }
+        assertNotNull(getIfcKey);
+        Type getIfcKeyType = getIfcKey.getReturnType();
+        assertNotNull(getIfcKeyType);
+        assertNotSame("java.lang.Void", getIfcKeyType);
+        assertEquals("InterfaceKey", getIfcKeyType.getName());
+
+        assertNotNull(getHigherLayerIf);
+        Type getHigherLayerIfType = getHigherLayerIf.getReturnType();
+        assertNotNull(getHigherLayerIfType);
+        assertNotSame("java.lang.Void", getHigherLayerIfType);
+        assertEquals("List", getHigherLayerIfType.getName());
+
+        // NetworkLink
+        final List<MethodSignature> gtNetworkLinkMethods = gtNetworkLink.getMethodDefinitions();
+        assertNotNull(gtNetworkLinkMethods);
+        MethodSignature getIfc = null;
+        for (MethodSignature method : gtNetworkLinkMethods) {
+            if (method.getName().equals("getInterface")) {
+                getIfc = method;
+            }
+        }
+        assertNotNull(getIfc);
+        Type getIfcType = getIfc.getReturnType();
+        assertNotNull(getIfcType);
+        assertNotSame("java.lang.Void", getIfcType);
+        assertEquals("String", getIfcType.getName());
+
+        // SourceNode
+        final List<MethodSignature> gtSourceMethods = gtSource.getMethodDefinitions();
+        assertNotNull(gtSourceMethods);
+        MethodSignature getIdSource = null;
+        for (MethodSignature method : gtSourceMethods) {
+            if (method.getName().equals("getId")) {
+                getIdSource = method;
+            }
+        }
+        assertNotNull(getIdSource);
+        Type getIdType = getIdSource.getReturnType();
+        assertNotNull(getIdType);
+        assertNotSame("java.lang.Void", getIdType);
+        assertEquals("Uri", getIdType.getName());
+
+        // DestinationNode
+        final List<MethodSignature> gtDestMethods = gtDest.getMethodDefinitions();
+        assertNotNull(gtDestMethods);
+        MethodSignature getIdDest = null;
+        for (MethodSignature method : gtDestMethods) {
+            if (method.getName().equals("getId")) {
+                getIdDest = method;
+            }
+        }
+        assertNotNull(getIdDest);
+        Type getIdDestType = getIdDest.getReturnType();
+        assertNotNull(getIdDestType);
+        assertNotSame("java.lang.Void", getIdDestType);
+        assertEquals("Uri", getIdDestType.getName());
+
+        // Tunnel
+        final List<MethodSignature> gtTunnelMethods = gtTunnel.getMethodDefinitions();
+        assertNotNull(gtTunnelMethods);
+        MethodSignature getTunnelKey = null;
+        for (MethodSignature method : gtTunnelMethods) {
+            if (method.getName().equals("getKey")) {
+                getTunnelKey = method;
+            }
+        }
+        assertNotNull(getTunnelKey);
+        Type getTunnelKeyType = getTunnelKey.getReturnType();
+        assertNotNull(getTunnelKeyType);
+        assertNotSame("java.lang.Void", getTunnelKeyType);
+        assertEquals("TunnelKey", getTunnelKeyType.getName());
+
+        // TunnelKey
+        final List<GeneratedProperty> gtTunnelKeyProps = gtTunnelKey.getProperties();
+        assertNotNull(gtTunnelKeyProps);
+        GeneratedProperty tunnelId = null;
+        for (final GeneratedProperty property : gtTunnelKeyProps) {
+            if (property.getName().equals("tunnelId")) {
+                tunnelId = property;
+            }
+        }
+        assertNotNull(tunnelId);
+        Type tunnelIdType = tunnelId.getReturnType();
+        assertNotNull(tunnelIdType);
+        assertNotSame("java.lang.Void", tunnelIdType);
+        assertEquals("Uri", tunnelIdType.getName());
+    }
+
+    @Test
+    public void testLeafrefInvalidPathResolving() throws URISyntaxException, IOException {
+        final URI resource = getClass().getResource("/leafref-test-invalid-model/foo.yang").toURI();
+        assertNotNull(resource);
+
+        final SchemaContext context = resolveSchemaContextFromFiles(resource);
+        assertNotNull(context);
+        assertEquals(1, context.getModules().size());
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        try {
+            bindingGen.generateTypes(context);
+            fail("Expected IllegalArgumentException caused by invalid leafref path");
+        } catch (IllegalArgumentException e) {
+            String expected = "Failed to find leafref target: ../id";
+            assertEquals(expected, e.getMessage());
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesStringTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesStringTest.java
new file mode 100644 (file)
index 0000000..fa7e0bf
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class GeneratedTypesStringTest {
+
+    private final static List<File> testModels = new ArrayList<File>();
+
+    @BeforeClass
+    public static void loadTestResources() throws URISyntaxException {
+        final File listModelFile = new File(GeneratedTypesStringTest.class.getResource("/simple-string-demo.yang")
+                .toURI());
+        testModels.add(listModelFile);
+    }
+
+    @Test
+    public void constantGenerationTest() throws IOException {
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        boolean typedefStringFound = false;
+        boolean constantRegExListFound = false;
+        boolean constantRegExListTypeGeneric = false;
+        boolean constantRegExListTypeContainer = false;
+        boolean noStringInReqExListFound = false;
+        boolean constantRegExListValueOK = false;
+        boolean constantRegExListTypeOneGeneric = false;
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedTransferObject) {
+                final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
+
+                if (genTO.getName().equals("TypedefString")) {
+                    typedefStringFound = true;
+
+                    List<Constant> constants = genTO.getConstantDefinitions();
+                    for (Constant con : constants) {
+                        if (con.getName().equals("PATTERN_CONSTANTS")) {
+                            constantRegExListFound = true;
+                        } else {
+                            break;
+                        }
+                        ParameterizedType pType;
+                        if (con.getType() instanceof ParameterizedType) {
+                            pType = (ParameterizedType) con.getType();
+                        } else {
+                            break;
+                        }
+
+                        Type[] types;
+                        if (pType.getName().equals("List")) {
+                            constantRegExListTypeContainer = true;
+                            types = pType.getActualTypeArguments();
+                        } else {
+                            break;
+                        }
+
+                        if (types.length == 1) {
+                            constantRegExListTypeOneGeneric = true;
+                        } else {
+                            break;
+                        }
+
+                        if (types[0].getName().equals("String")) {
+                            constantRegExListTypeGeneric = true;
+                        } else {
+                            break;
+                        }
+
+                        if (con.getValue() instanceof List) {
+                            constantRegExListValueOK = true;
+                        } else {
+                            break;
+                        }
+
+                        for (Object obj : (List<?>) con.getValue()) {
+                            if (!(obj instanceof String)) {
+                                noStringInReqExListFound = true;
+                                break;
+                            }
+                        }
+
+                    }
+                }
+            }
+
+        }
+
+        assertTrue("Typedef >>TypedefString<< wasn't found", typedefStringFound);
+        assertTrue("Constant PATTERN_CONSTANTS is missing in TO", constantRegExListFound);
+        assertTrue("Constant PATTERN_CONSTANTS doesn't have correct container type", constantRegExListTypeContainer);
+        assertTrue("Constant PATTERN_CONSTANTS has more than one generic type", constantRegExListTypeOneGeneric);
+        assertTrue("Constant PATTERN_CONSTANTS doesn't have correct generic type", constantRegExListTypeGeneric);
+        assertTrue("Constant PATTERN_CONSTANTS doesn't contain List object", constantRegExListValueOK);
+        assertTrue("In list found other type than String", !noStringInReqExListFound);
+
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/GeneratedTypesTest.java
new file mode 100644 (file)
index 0000000..6ab4536
--- /dev/null
@@ -0,0 +1,416 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class GeneratedTypesTest {
+
+    @Test
+    public void testMultipleModulesResolving() throws URISyntaxException, IOException {
+        File abstractTopology = new File(getClass().getResource("/abstract-topology.yang").toURI());
+        File ietfInetTypes = new File(getClass().getResource("/ietf/ietf-inet-types.yang").toURI());
+
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(abstractTopology, ietfInetTypes));
+        assertNotNull(context);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull(genTypes);
+        assertEquals(29, genTypes.size());
+    }
+
+    @Test
+    public void testContainerResolving() throws URISyntaxException, IOException {
+        final File testFile = new File(getClass().getResource("/simple-container-demo.yang").toURI());
+        final SchemaContext context = new YangParserImpl().parseFiles(Collections.singleton(testFile));
+        assertNotNull(context);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull(genTypes);
+        assertEquals(3, genTypes.size());
+
+        GeneratedType simpleContainer = (GeneratedType) genTypes.get(1);
+        GeneratedType nestedContainer = (GeneratedType) genTypes.get(2);
+        for (Type t : genTypes) {
+            if ("SimpleContainer".equals(t.getName())) {
+                simpleContainer = (GeneratedType) t;
+            } else if ("NestedContainer".equals(t.getName())) {
+                nestedContainer = (GeneratedType) t;
+            }
+        }
+        assertNotNull(simpleContainer);
+        assertNotNull(nestedContainer);
+        assertEquals(3, simpleContainer.getMethodDefinitions().size());
+        assertEquals(2, nestedContainer.getMethodDefinitions().size());
+
+        int getFooMethodCounter = 0;
+        int getBarMethodCounter = 0;
+        int getNestedContainerCounter = 0;
+
+        String getFooMethodReturnTypeName = "";
+        String getBarMethodReturnTypeName = "";
+        String getNestedContainerReturnTypeName = "";
+        for (final MethodSignature method : simpleContainer.getMethodDefinitions()) {
+            if (method.getName().equals("getFoo")) {
+                getFooMethodCounter++;
+                getFooMethodReturnTypeName = method.getReturnType().getName();
+            }
+
+            if (method.getName().equals("getBar")) {
+                getBarMethodCounter++;
+                getBarMethodReturnTypeName = method.getReturnType().getName();
+            }
+
+            if (method.getName().equals("getNestedContainer")) {
+                getNestedContainerCounter++;
+                getNestedContainerReturnTypeName = method.getReturnType().getName();
+            }
+        }
+
+        assertEquals(1, getFooMethodCounter);
+        assertEquals("Integer", getFooMethodReturnTypeName);
+
+        assertEquals(1, getBarMethodCounter);
+        assertEquals("String", getBarMethodReturnTypeName);
+
+        assertEquals(1, getNestedContainerCounter);
+        assertEquals("NestedContainer", getNestedContainerReturnTypeName);
+
+        getFooMethodCounter = 0;
+        getBarMethodCounter = 0;
+
+        getFooMethodReturnTypeName = "";
+        getBarMethodReturnTypeName = "";
+
+        for (final MethodSignature method : nestedContainer.getMethodDefinitions()) {
+
+            if (method.getName().equals("getFoo")) {
+                getFooMethodCounter++;
+                getFooMethodReturnTypeName = method.getReturnType().getName();
+            }
+
+            if (method.getName().equals("getBar")) {
+                getBarMethodCounter++;
+                getBarMethodReturnTypeName = method.getReturnType().getName();
+            }
+        }
+
+        assertEquals(1, getFooMethodCounter);
+        assertEquals("Short", getFooMethodReturnTypeName);
+
+        assertEquals(1, getBarMethodCounter);
+        assertEquals("String", getBarMethodReturnTypeName);
+    }
+
+    @Test
+    public void testLeafListResolving() throws URISyntaxException, IOException {
+        final File testFile = new File(getClass().getResource("/simple-leaf-list-demo.yang").toURI());
+        final SchemaContext context = new YangParserImpl().parseFiles(Collections.singleton(testFile));
+        assertNotNull(context);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull(genTypes);
+        assertEquals(3, genTypes.size());
+
+        GeneratedType simpleContainer = (GeneratedType) genTypes.get(1);
+        GeneratedType nestedContainer = (GeneratedType) genTypes.get(2);
+        for (Type t : genTypes) {
+            if ("SimpleContainer".equals(t.getName())) {
+                simpleContainer = (GeneratedType) t;
+            } else if ("NestedContainer".equals(t.getName())) {
+                nestedContainer = (GeneratedType) t;
+            }
+        }
+        assertNotNull(simpleContainer);
+        assertNotNull(nestedContainer);
+        assertEquals(3, simpleContainer.getMethodDefinitions().size());
+        assertEquals(2, nestedContainer.getMethodDefinitions().size());
+
+        int getFooMethodCounter = 0;
+        int getBarMethodCounter = 0;
+        int getNestedContainerCounter = 0;
+
+        String getFooMethodReturnTypeName = "";
+        String getBarMethodReturnTypeName = "";
+        String getNestedContainerReturnTypeName = "";
+        for (final MethodSignature method : simpleContainer.getMethodDefinitions()) {
+            if (method.getName().equals("getFoo")) {
+                getFooMethodCounter++;
+                getFooMethodReturnTypeName = method.getReturnType().getName();
+            }
+
+            if (method.getName().equals("getBar")) {
+                getBarMethodCounter++;
+                getBarMethodReturnTypeName = method.getReturnType().getName();
+            }
+
+            if (method.getName().equals("getNestedContainer")) {
+                getNestedContainerCounter++;
+                getNestedContainerReturnTypeName = method.getReturnType().getName();
+            }
+        }
+
+        assertEquals(1, getFooMethodCounter);
+        assertEquals("List", getFooMethodReturnTypeName);
+
+        assertEquals(1, getBarMethodCounter);
+        assertEquals("String", getBarMethodReturnTypeName);
+
+        assertEquals(1, getNestedContainerCounter);
+        assertEquals("NestedContainer", getNestedContainerReturnTypeName);
+
+        getFooMethodCounter = 0;
+        getBarMethodCounter = 0;
+
+        getFooMethodReturnTypeName = "";
+        getBarMethodReturnTypeName = "";
+
+        for (final MethodSignature method : nestedContainer.getMethodDefinitions()) {
+            if (method.getName().equals("getFoo")) {
+                getFooMethodCounter++;
+                getFooMethodReturnTypeName = method.getReturnType().getName();
+            }
+
+            if (method.getName().equals("getBar")) {
+                getBarMethodCounter++;
+                getBarMethodReturnTypeName = method.getReturnType().getName();
+            }
+        }
+
+        assertEquals(1, getFooMethodCounter);
+        assertEquals("Short", getFooMethodReturnTypeName);
+
+        assertEquals(1, getBarMethodCounter);
+        assertEquals("List", getBarMethodReturnTypeName);
+    }
+
+    @Test
+    public void testListResolving() throws URISyntaxException, IOException {
+        final File testFile = new File(getClass().getResource("/simple-list-demo.yang").toURI());
+        final SchemaContext context = new YangParserImpl().parseFiles(Collections.singleton(testFile));
+        assertNotNull(context);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull(genTypes);
+        assertEquals(5, genTypes.size());
+
+        int listParentContainerMethodsCount = 0;
+        int simpleListMethodsCount = 0;
+        int listChildContainerMethodsCount = 0;
+        int listKeyClassCount = 0;
+
+        int getSimpleListKeyMethodCount = 0;
+        int getListChildContainerMethodCount = 0;
+        int getFooMethodCount = 0;
+        int setFooMethodCount = 0;
+        int getSimpleLeafListMethodCount = 0;
+        int setSimpleLeafListMethodCount = 0;
+        int getBarMethodCount = 0;
+
+        String getSimpleListKeyMethodReturnTypeName = "";
+        String getListChildContainerMethodReturnTypeName = "";
+
+        int listKeyClassPropertyCount = 0;
+        String listKeyClassPropertyName = "";
+        String listKeyClassPropertyTypeName = "";
+        boolean listKeyClassPropertyReadOnly = false;
+
+        int hashMethodParameterCount = 0;
+        String hashMethodParameterName = "";
+        String hashMethodParameterReturnTypeName = "";
+
+        int equalMethodParameterCount = 0;
+        String equalMethodParameterName = "";
+        String equalMethodParameterReturnTypeName = "";
+
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                final GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("ListParentContainer")) {
+                    listParentContainerMethodsCount = genType.getMethodDefinitions().size();
+                } else if (genType.getName().equals("SimpleList")) {
+                    simpleListMethodsCount = genType.getMethodDefinitions().size();
+                    final List<MethodSignature> methods = genType.getMethodDefinitions();
+                    for (final MethodSignature method : methods) {
+                        if (method.getName().equals("getKey")) {
+                            getSimpleListKeyMethodCount++;
+                            getSimpleListKeyMethodReturnTypeName = method.getReturnType().getName();
+                        } else if (method.getName().equals("getListChildContainer")) {
+                            getListChildContainerMethodCount++;
+                            getListChildContainerMethodReturnTypeName = method.getReturnType().getName();
+                        } else if (method.getName().equals("getFoo")) {
+                            getFooMethodCount++;
+                        } else if (method.getName().equals("setFoo")) {
+                            setFooMethodCount++;
+                        } else if (method.getName().equals("getSimpleLeafList")) {
+                            getSimpleLeafListMethodCount++;
+                        } else if (method.getName().equals("setSimpleLeafList")) {
+                            setSimpleLeafListMethodCount++;
+                        } else if (method.getName().equals("getBar")) {
+                            getBarMethodCount++;
+                        }
+                    }
+                } else if (genType.getName().equals("ListChildContainer")) {
+                    listChildContainerMethodsCount = genType.getMethodDefinitions().size();
+                }
+            } else if (type instanceof GeneratedTransferObject) {
+                final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
+                final List<GeneratedProperty> properties = genTO.getProperties();
+                final List<GeneratedProperty> hashProps = genTO.getHashCodeIdentifiers();
+                final List<GeneratedProperty> equalProps = genTO.getEqualsIdentifiers();
+
+                listKeyClassCount++;
+                listKeyClassPropertyCount = properties.size();
+                listKeyClassPropertyName = properties.get(0).getName();
+                listKeyClassPropertyTypeName = properties.get(0).getReturnType().getName();
+                listKeyClassPropertyReadOnly = properties.get(0).isReadOnly();
+
+                hashMethodParameterCount = hashProps.size();
+                hashMethodParameterName = hashProps.get(0).getName();
+                hashMethodParameterReturnTypeName = hashProps.get(0).getReturnType().getName();
+
+                equalMethodParameterCount = equalProps.size();
+                equalMethodParameterName = equalProps.get(0).getName();
+                equalMethodParameterReturnTypeName = equalProps.get(0).getReturnType().getName();
+
+            }
+        }
+
+        assertEquals(1, listParentContainerMethodsCount);
+        assertEquals(1, listChildContainerMethodsCount);
+        assertEquals(1, getSimpleListKeyMethodCount);
+        assertEquals(1, listKeyClassCount);
+
+        assertEquals(1, listKeyClassPropertyCount);
+        assertEquals("listKey", listKeyClassPropertyName);
+        assertEquals("Byte", listKeyClassPropertyTypeName);
+        assertEquals(true, listKeyClassPropertyReadOnly);
+        assertEquals(1, hashMethodParameterCount);
+        assertEquals("listKey", hashMethodParameterName);
+        assertEquals("Byte", hashMethodParameterReturnTypeName);
+        assertEquals(1, equalMethodParameterCount);
+        assertEquals("listKey", equalMethodParameterName);
+        assertEquals("Byte", equalMethodParameterReturnTypeName);
+
+        assertEquals("SimpleListKey", getSimpleListKeyMethodReturnTypeName);
+
+        assertEquals(1, getListChildContainerMethodCount);
+        assertEquals("ListChildContainer", getListChildContainerMethodReturnTypeName);
+        assertEquals(1, getFooMethodCount);
+        assertEquals(0, setFooMethodCount);
+        assertEquals(1, getSimpleLeafListMethodCount);
+        assertEquals(0, setSimpleLeafListMethodCount);
+        assertEquals(1, getBarMethodCount);
+
+        assertEquals(6, simpleListMethodsCount);
+    }
+
+    @Test
+    public void testListCompositeKeyResolving() throws URISyntaxException, IOException {
+        final File testFile = new File(getClass().getResource("/list-composite-key.yang").toURI());
+        final SchemaContext context = new YangParserImpl().parseFiles(Collections.singleton(testFile));
+        assertNotNull(context);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull(genTypes);
+        assertEquals(7, genTypes.size());
+
+        int genTypesCount = 0;
+        int genTOsCount = 0;
+
+        int compositeKeyListKeyPropertyCount = 0;
+        int compositeKeyListKeyCount = 0;
+        int innerListKeyPropertyCount = 0;
+
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                genTypesCount++;
+            } else if (type instanceof GeneratedTransferObject) {
+                final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
+
+                if (genTO.getName().equals("CompositeKeyListKey")) {
+                    compositeKeyListKeyCount++;
+                    final List<GeneratedProperty> properties = genTO.getProperties();
+                    for (final GeneratedProperty prop : properties) {
+                        if (prop.getName().equals("key1")) {
+                            compositeKeyListKeyPropertyCount++;
+                        } else if (prop.getName().equals("key2")) {
+                            compositeKeyListKeyPropertyCount++;
+                        }
+                    }
+                    genTOsCount++;
+                } else if (genTO.getName().equals("InnerListKey")) {
+                    final List<GeneratedProperty> properties = genTO.getProperties();
+                    innerListKeyPropertyCount = properties.size();
+                    genTOsCount++;
+                }
+            }
+        }
+        assertEquals(1, compositeKeyListKeyCount);
+        assertEquals(2, compositeKeyListKeyPropertyCount);
+
+        assertEquals(1, innerListKeyPropertyCount);
+
+        assertEquals(5, genTypesCount);
+        assertEquals(2, genTOsCount);
+    }
+
+    @Test
+    public void testGeneratedTypes() throws URISyntaxException, IOException {
+        final File testFile = new File(getClass().getResource("/demo-topology.yang").toURI());
+        final SchemaContext context = new YangParserImpl().parseFiles(Collections.singleton(testFile));
+        assertNotNull(context);
+
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull(genTypes);
+        assertEquals(14, genTypes.size());
+
+        int genTypesCount = 0;
+        int genTOsCount = 0;
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                genTypesCount++;
+            } else if (type instanceof GeneratedTransferObject) {
+                genTOsCount++;
+            }
+        }
+
+        assertEquals(11, genTypesCount);
+        assertEquals(3, genTOsCount);
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/IdentityrefTypeTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/IdentityrefTypeTest.java
new file mode 100644 (file)
index 0000000..0c20b91
--- /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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class IdentityrefTypeTest {
+
+    private static List<File> testModels = null;
+
+    @Before
+    public void loadTestResources() throws URISyntaxException {
+        URI folderPath = IdentityrefTypeTest.class.getResource("/identityref.yang").toURI();
+        File folderFile = new File(folderPath);
+        testModels = new ArrayList<File>();
+
+        if (folderFile.isFile()) {
+            testModels.add(folderFile);
+        } else {
+            for (File file : folderFile.listFiles()) {
+                if (file.isFile()) {
+                    testModels.add(file);
+                }
+            }
+        }
+    }
+
+    /**
+     * Test mainly for the method
+     * {@link TypeProviderImpl#provideTypeForIdentityref()
+     * provideTypeForIdentityref}
+     */
+    @Test
+    public void testIdentityrefYangBuiltInType() throws IOException {
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        GeneratedType moduleGenType = null;
+        for (Type type : genTypes) {
+            if (type.getName().equals("ModuleIdentityrefData")) {
+                if (type instanceof GeneratedType) {
+                    moduleGenType = (GeneratedType) type;
+                }
+            }
+        }
+
+        assertNotNull("Generated type for whole module wasn't found", moduleGenType);
+
+        String typeName = null;
+        String actualTypeName = "";
+        int numOfActualTypes = 0;
+        List<MethodSignature> methodSignatures = moduleGenType.getMethodDefinitions();
+        for (MethodSignature methodSignature : methodSignatures) {
+            if (methodSignature.getName().equals("getLf")) {
+                Type returnType = methodSignature.getReturnType();
+                if (returnType instanceof ParameterizedType) {
+                    typeName = returnType.getName();
+                    Type[] actualTypes = ((ParameterizedType) returnType).getActualTypeArguments();
+                    numOfActualTypes = actualTypes.length;
+                    actualTypeName = actualTypes[0].getName();
+                }
+            }
+        }
+        assertNotNull("The method 'getLf' wasn't found", typeName);
+        assertEquals("Return type has incorrect name", "Class", typeName);
+        assertEquals("Incorrect number of type parameters", 1, numOfActualTypes);
+        assertEquals("Return type has incorrect actual parameter", "SomeIdentity", actualTypeName);
+
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/NameTypePattern.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/NameTypePattern.java
new file mode 100644 (file)
index 0000000..acf940e
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+public class NameTypePattern {
+    final String name;
+    final String type;
+
+    public NameTypePattern(String name, String type) {
+        this.name = name;
+        this.type = type;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public String getType() {
+        return this.type;
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ReplaceAllIllegalCharsTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/ReplaceAllIllegalCharsTest.java
new file mode 100644 (file)
index 0000000..85b9ac0
--- /dev/null
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2015 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class ReplaceAllIllegalCharsTest {
+
+    @Test
+    public void unicodeCharReplaceTest() {
+        String inputString = "abcu\\uuuuu\\uuua\\u\\\\uabc\\\\uuuu\\\\\\uuuu\\\\\\\\uuuu///uu/u/u/u/u/u/u";
+
+        StringBuilder sb = new StringBuilder(inputString);
+        String resultString = BindingGeneratorImpl.replaceAllIllegalChars(sb);
+
+        String expectedString = "abcu\\\\uuuuu\\\\uuua\\\\u\\\\uabc\\\\uuuu\\\\uuuu\\\\uuuu///uu/u/u/u/u/u/u";
+        assertEquals(expectedString, resultString);
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/SupportTestUtil.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/SupportTestUtil.java
new file mode 100644 (file)
index 0000000..59a04ff
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class SupportTestUtil {
+
+    public static SchemaContext resolveSchemaContextFromFiles(final URI... yangFiles) throws IOException {
+        final YangContextParser parser = new YangParserImpl();
+
+        final List<File> inputFiles = new ArrayList<File>();
+        for (int i = 0; i < yangFiles.length; ++i) {
+            inputFiles.add(new File(yangFiles[i]));
+        }
+
+        return parser.parseFiles(inputFiles);
+    }
+
+    public static void containsMethods(final GeneratedType genType, final NameTypePattern... searchedSignsWhat) {
+        final List<MethodSignature> searchedSignsIn = genType.getMethodDefinitions();
+        containsMethods(searchedSignsIn, searchedSignsWhat);
+    }
+
+    public static void containsMethods(final List<MethodSignature> searchedSignsIn,
+            final NameTypePattern... searchedSignsWhat) {
+        if (searchedSignsIn == null) {
+            throw new IllegalArgumentException("List of method signatures in which should be searched can't be null");
+        }
+        if (searchedSignsWhat == null) {
+            throw new IllegalArgumentException("Array of method signatures which should be searched can't be null");
+        }
+
+        for (NameTypePattern searchedSignWhat : searchedSignsWhat) {
+            boolean nameMatchFound = false;
+            String typeNameFound = "";
+            for (MethodSignature searchedSignIn : searchedSignsIn) {
+                if (searchedSignWhat.getName().equals(searchedSignIn.getName())) {
+                    nameMatchFound = true;
+                    typeNameFound = resolveFullNameOfReturnType(searchedSignIn.getReturnType());
+                    if (searchedSignWhat.getType().equals(typeNameFound)) {
+                        break;
+                    }
+                }
+            }
+            assertTrue("Method " + searchedSignWhat.getName() + " wasn't found.", nameMatchFound);
+            assertEquals("Return type in method " + searchedSignWhat.getName() + " doesn't match expected type ",
+                    searchedSignWhat.getType(), typeNameFound);
+
+        }
+    }
+
+    public static void containsAttributes(final GeneratedTransferObject genTO, boolean equal, boolean hash,
+            boolean toString, final NameTypePattern... searchedSignsWhat) {
+        List<GeneratedProperty> searchedPropertiesIn = genTO.getProperties();
+        containsAttributes(searchedPropertiesIn, "", searchedSignsWhat);
+        if (equal) {
+            searchedPropertiesIn = genTO.getEqualsIdentifiers();
+            containsAttributes(searchedPropertiesIn, "equal", searchedSignsWhat);
+        }
+        if (hash) {
+            searchedPropertiesIn = genTO.getHashCodeIdentifiers();
+            containsAttributes(searchedPropertiesIn, "hash", searchedSignsWhat);
+        }
+        if (toString) {
+            searchedPropertiesIn = genTO.getToStringIdentifiers();
+            containsAttributes(searchedPropertiesIn, "toString", searchedSignsWhat);
+        }
+
+    }
+
+    public static void containsAttributes(final List<GeneratedProperty> searchedPropertiesIn, final String listType,
+            final NameTypePattern... searchedPropertiesWhat) {
+
+        for (NameTypePattern searchedPropertyWhat : searchedPropertiesWhat) {
+            boolean nameMatchFound = false;
+            String typeNameFound = "";
+            for (GeneratedProperty searchedPropertyIn : searchedPropertiesIn) {
+                if (searchedPropertyWhat.getName().equals(searchedPropertyIn.getName())) {
+                    nameMatchFound = true;
+                    typeNameFound = resolveFullNameOfReturnType(searchedPropertyIn.getReturnType());
+                    if (searchedPropertyWhat.getType().equals(typeNameFound)) {
+                        break;
+                    }
+                }
+            }
+            assertTrue("Property " + searchedPropertyWhat.getName() + " wasn't found in " + listType
+                    + " property list.", nameMatchFound);
+            assertEquals("The type of property " + searchedPropertyWhat.getName() + " in " + listType
+                    + " property list doesn't match expected type.", searchedPropertyWhat.getType(), typeNameFound);
+
+        }
+    }
+
+    public static String resolveFullNameOfReturnType(final Type type) {
+        final StringBuilder nameBuilder = new StringBuilder();
+        if (type instanceof ParameterizedType) {
+            nameBuilder.append(type.getName() + "<");
+            ParameterizedType parametrizedTypes = (ParameterizedType) type;
+            for (Type parametrizedType : parametrizedTypes.getActualTypeArguments()) {
+                nameBuilder.append(parametrizedType.getName() + ",");
+            }
+            if (nameBuilder.charAt(nameBuilder.length() - 1) == ',') {
+                nameBuilder.deleteCharAt(nameBuilder.length() - 1);
+            }
+            nameBuilder.append(">");
+        } else {
+            nameBuilder.append(type.getName());
+        }
+        return nameBuilder.toString();
+    }
+
+    public static void containsInterface(String interfaceNameSearched, GeneratedType genType) {
+        List<Type> caseCImplements = genType.getImplements();
+        boolean interfaceFound = false;
+        for (Type caseCImplement : caseCImplements) {
+            String interfaceName = resolveFullNameOfReturnType(caseCImplement);
+            if (interfaceName.equals(interfaceNameSearched)) {
+                interfaceFound = true;
+                break;
+            }
+        }
+        assertTrue("Generated type " + genType.getName() + " doesn't implement interface " + interfaceNameSearched,
+                interfaceFound);
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/TypeProviderIntegrationTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/TypeProviderIntegrationTest.java
new file mode 100644 (file)
index 0000000..d34f7c5
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class TypeProviderIntegrationTest {
+    private final String PKG = "org.opendaylight.yang.gen.v1.urn.opendaylight.test.rev131008.";
+    private static SchemaContext context;
+    private TypeProviderImpl provider;
+    private Module m;
+
+    @BeforeClass
+    public static void setup() throws Exception {
+        File abstractTopology = new File(TypeProviderIntegrationTest.class.getResource("/type-provider/test.yang")
+                .toURI());
+        File ietfInetTypes = new File(TypeProviderIntegrationTest.class.getResource("/ietf/ietf-inet-types.yang")
+                .toURI());
+        context = new YangParserImpl().parseFiles(Arrays.asList(abstractTopology, ietfInetTypes));
+        assertNotNull(context);
+    }
+
+    @Before
+    public void init() throws ParseException {
+        provider = new TypeProviderImpl(context);
+        m = context.findModuleByName("test", new SimpleDateFormat("yyyy-MM-dd").parse("2013-10-08"));
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionBinary() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-binary");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new byte[] {77, 97, 110}", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-binary");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyBinary(new byte[] {77, 97, 110})", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionBits() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-bits");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "TestData.LeafBits(false, false, true)", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-bits");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyBits(false, false, true)", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionBoolean() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-boolean");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.lang.Boolean(\"true\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-boolean");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyBoolean(new java.lang.Boolean(\"true\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionDecimal() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-decimal64");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.math.BigDecimal(\"3.14\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-decimal64");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyDecimal64(new java.math.BigDecimal(\"3.14\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionEmpty() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-empty");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.lang.Boolean(\"false\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-empty");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyEmpty(new java.lang.Boolean(\"false\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionEnumeration() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-enumeration");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("org.opendaylight.yang.gen.v1.urn.opendaylight.test.rev131008.LeafEnumeration.Seven", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-enumeration");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals(PKG + "MyEnumeration.Seven", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionInt8() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-int8");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.lang.Byte(\"11\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-int8");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyInt8(new java.lang.Byte(\"11\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionInt16() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-int16");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.lang.Short(\"111\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-int16");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyInt16(new java.lang.Short(\"111\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionInt32() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-int32");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.lang.Integer(\"1111\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-int32");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyInt32(new java.lang.Integer(\"1111\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionInt64() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-int64");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.lang.Long(\"11111\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-int64");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyInt64(new java.lang.Long(\"11111\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionLeafref1() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-leafref");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.math.BigDecimal(\"1.234\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-leafref");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.math.BigDecimal(\"1.234\")", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionLeafref2() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-leafref1");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyBinary(new byte[] {77, 97, 110})", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-leafref1");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyBinary(new byte[] {77, 97, 110})", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionString() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-string");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("\"name\"", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-string");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyString(\"name\")", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionUint8() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-uint8");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.lang.Short(\"11\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-uint8");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyUint8(new java.lang.Short(\"11\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionUint16() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-uint16");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.lang.Integer(\"111\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-uint16");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyUint16(new java.lang.Integer(\"111\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionUint32() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-uint32");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.lang.Long(\"1111\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-uint32");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyUint32(new java.lang.Long(\"1111\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionUint64() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-uint64");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new java.math.BigInteger(\"11111\")", actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-uint64");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        assertEquals("new " + PKG + "MyUint64(new java.math.BigInteger(\"11111\"))", actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstruction() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("ip-leaf");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        String exp = "new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address(\"0.0.0.1\")";
+        assertEquals(exp, actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionUnion() throws ParseException {
+        LeafSchemaNode leaf = (LeafSchemaNode) m.getDataChildByName("leaf-union");
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        String expected = "new " + PKG + "TestData.LeafUnion(\"111\".toCharArray())";
+        assertEquals(expected, actual);
+
+        leaf = (LeafSchemaNode) m.getDataChildByName("ext-union");
+        actual = provider.getTypeDefaultConstruction(leaf);
+        expected = "new " + PKG + "MyUnion(\"111\".toCharArray())";
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testGetTypeDefaultConstructionUnionNested() throws ParseException {
+        ContainerSchemaNode c1 = (ContainerSchemaNode) m.getDataChildByName("c1");
+        ContainerSchemaNode c2 = (ContainerSchemaNode) c1.getDataChildByName("c2");
+        ContainerSchemaNode c3 = (ContainerSchemaNode) c2.getDataChildByName("c3");
+        LeafSchemaNode leaf = (LeafSchemaNode) c3.getDataChildByName("id");
+
+        String actual = provider.getTypeDefaultConstruction(leaf);
+        String expected = "new " + PKG + "NestedUnion(\"111\".toCharArray())";
+        assertEquals(expected, actual);
+    }
+
+    @Test
+    public void testGetParamNameFromType() throws ParseException {
+        m = context.findModuleByName("ietf-inet-types", new SimpleDateFormat("yyyy-MM-dd").parse("2010-09-24"));
+        Set<TypeDefinition<?>> types = m.getTypeDefinitions();
+        TypeDefinition<?> ipv4 = null;
+        TypeDefinition<?> ipv6 = null;
+        TypeDefinition<?> ipv4Pref = null;
+        TypeDefinition<?> ipv6Pref = null;
+        for (TypeDefinition<?> type : types) {
+            if ("ipv4-address".equals(type.getQName().getLocalName())) {
+                ipv4 = type;
+            } else if ("ipv6-address".equals(type.getQName().getLocalName())) {
+                ipv6 = type;
+            } else if ("ipv4-prefix".equals(type.getQName().getLocalName())) {
+                ipv4Pref = type;
+            } else if ("ipv6-prefix".equals(type.getQName().getLocalName())) {
+                ipv6Pref = type;
+            }
+        }
+
+        assertNotNull(ipv4);
+        assertNotNull(ipv6);
+        assertNotNull(ipv4Pref);
+        assertNotNull(ipv6Pref);
+        assertEquals("ipv4Address", provider.getParamNameFromType(ipv4));
+        assertEquals("ipv6Address", provider.getParamNameFromType(ipv6));
+        assertEquals("ipv4Prefix", provider.getParamNameFromType(ipv4Pref));
+        assertEquals("ipv6Prefix", provider.getParamNameFromType(ipv6Pref));
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/UnionTypeDefTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/UnionTypeDefTest.java
new file mode 100644 (file)
index 0000000..ae8a3eb
--- /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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class UnionTypeDefTest {
+
+    @Test
+    public void unionTypeResolvingTest() throws Exception {
+        File abstractTopology = new File(getClass().getResource("/union-test-models/abstract-topology.yang").toURI());
+        File ietfInetTypes = new File(getClass().getResource("/ietf/ietf-inet-types.yang").toURI());
+        final SchemaContext context = new YangParserImpl().parseFiles(Arrays.asList(abstractTopology, ietfInetTypes));
+
+        assertNotNull("context is null", context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertNotNull("genTypes is null", genTypes);
+        assertFalse("genTypes is empty", genTypes.isEmpty());
+
+        // TODO: implement test
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/UsesTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/generator/impl/UsesTest.java
new file mode 100644 (file)
index 0000000..524ef51
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ * 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.sal.binding.generator.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.binding.generator.impl.SupportTestUtil.containsInterface;
+import static org.opendaylight.yangtools.sal.binding.generator.impl.SupportTestUtil.containsMethods;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class UsesTest {
+
+    private static List<File> loadTestResources(final String testFile) {
+        try {
+        final List<File> testModels = new ArrayList<File>();
+        final File listModelFile = new File(UsesTest.class.getResource(testFile).toURI());
+        testModels.add(listModelFile);
+        return testModels;
+        } catch (URISyntaxException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Test
+    public void usesInGroupingDependenciesTest() throws IOException {
+        List<File> testModels = loadTestResources("/uses-of-grouping/uses-of-grouping-dependencies.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+        GeneratedType groupingU = null;
+        GeneratedType groupingX = null;
+        GeneratedType groupingV = null;
+
+        int groupingUCounter = 0;
+        int groupingXCounter = 0;
+        int groupingVCounter = 0;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("GroupingU")) {
+                    groupingU = genType;
+                    groupingUCounter++;
+                } else if (genType.getName().equals("GroupingV")) {
+                    groupingV = genType;
+                    groupingVCounter++;
+                } else if (genType.getName().equals("GroupingX")) {
+                    groupingX = genType;
+                    groupingXCounter++;
+                }
+            }
+        }
+
+        assertNotNull("Generated type for grouping-U wasn't generated.", groupingU);
+        assertEquals("GroupingU interface generated more than one time.", 1, groupingUCounter);
+        assertEquals("GroupingU is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.dependencies.rev130718", groupingU.getPackageName());
+
+        assertNotNull("Generated type for grouping-V wasn't generated.", groupingV);
+        assertEquals("GroupingV interface generated more than one time.", 1, groupingVCounter);
+        assertEquals("GroupingV is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.dependencies.rev130718", groupingV.getPackageName());
+
+        assertNotNull("Generated type for grouping-X wasn't generated.", groupingX);
+        assertEquals("GroupingX interface generated more than one time.", 1, groupingXCounter);
+        assertEquals("GroupingX is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.dependencies.rev130718", groupingX.getPackageName());
+
+        containsInterface("GroupingV", groupingU);
+        containsInterface("GroupingX", groupingU);
+        containsInterface("GroupingZ", groupingV);
+        containsInterface("GroupingZZ", groupingV);
+        containsInterface("GroupingY", groupingX);
+    }
+
+    @Test
+    public void usesInCaseTest() throws IOException {
+        List<File> testModels = loadTestResources("/uses-of-grouping/uses-of-grouping-case.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        GeneratedType groupingCaseTest = null;
+        int groupingCaseTestCounter = 0;
+        GeneratedType caseC = null;
+        int caseCCounter = 0;
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("C")) {
+                    caseC = genType;
+                    caseCCounter++;
+                } else if (genType.getName().equals("GroupingCaseTest")) {
+                    groupingCaseTest = genType;
+                    groupingCaseTestCounter++;
+                }
+            }
+        }
+
+        assertNotNull("Generated type for case C wasn't generated.", caseC);
+        assertEquals("Case C interface generated more than one time.", 1, caseCCounter);
+        assertEquals(
+                "Case C is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses._case.rev130718.container.with.choicetest.choice.test",
+                caseC.getPackageName());
+
+        assertNotNull("Generated type for grouping-case-test wasn't generated.", groupingCaseTest);
+        assertEquals("GroupingCaseTest interface generated more than one time.", 1, groupingCaseTestCounter);
+        assertEquals("GroupingCaseTest is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses._case.rev130718", groupingCaseTest.getPackageName());
+
+        containsInterface("GroupingCaseTest", caseC);
+        assertTrue("Case C shouldn't contain any method.", caseC.getMethodDefinitions().isEmpty());
+
+        assertEquals("Number of method in GroupingCaseTest is incorrect", 1, groupingCaseTest.getMethodDefinitions()
+                .size());
+        containsMethods(groupingCaseTest.getMethodDefinitions(), new NameTypePattern("getLeafGroupingCaseTest1",
+                "String"));
+    }
+
+    @Test
+    public void usesInContainerTest() throws IOException {
+        List<File> testModels = loadTestResources("/uses-of-grouping/uses-of-grouping-container.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        int containerTestCount = 0;
+        int groupingContainerTestCounter = 0;
+        GeneratedType containerTest = null;
+        GeneratedType groupingContainerTest = null;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("GroupingContainerTest")) {
+                    groupingContainerTest = genType;
+                    groupingContainerTestCounter++;
+                } else if (genType.getName().equals("ContainerTest")) {
+                    containerTest = genType;
+                    containerTestCount++;
+                }
+            }
+        }
+
+        assertNotNull("Generated type for grouping-container-test wasn't generated", groupingContainerTest);
+        assertEquals("GroupingContainerTest interface - incorrect number of occurences", 1,
+                groupingContainerTestCounter);
+        assertEquals("GroupingContainerTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.container.rev130718",
+                groupingContainerTest.getPackageName());
+
+        assertNotNull("Generated type for container-test wasn't generated", containerTest);
+        assertEquals("ContainerTest interface - incorrect number of occurences", 1, containerTestCount);
+        assertEquals("ContainerTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.container.rev130718", containerTest.getPackageName());
+
+        containsInterface("GroupingContainerTest", containerTest);
+
+        assertEquals("Number of method in GroupingContainerTestis incorrect", 2, groupingContainerTest
+                .getMethodDefinitions().size());
+        assertEquals("Number of method in ContainerTest is incorrect", 1, containerTest.getMethodDefinitions().size());
+
+        containsMethods(groupingContainerTest.getMethodDefinitions(), new NameTypePattern(
+                "getLeafGroupingContainerTest1", "String"), new NameTypePattern("getLeafGroupingContainerTest2",
+                "Short"));
+
+        containsMethods(containerTest.getMethodDefinitions(), new NameTypePattern("getContainerLeafTest", "String"));
+    }
+
+    @Test
+    public void usesInGroupingTest() throws IOException {
+        List<File> testModels = loadTestResources("/uses-of-grouping/uses-of-grouping-grouping.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        int groupingTestCount = 0;
+        int groupingGroupingTestCounter = 0;
+        GeneratedType groupingTest = null;
+        GeneratedType groupingGroupingTest = null;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("GroupingGroupingTest")) {
+                    groupingGroupingTest = genType;
+                    groupingGroupingTestCounter++;
+                } else if (genType.getName().equals("GroupingTest")) {
+                    groupingTest = genType;
+                    groupingTestCount++;
+                }
+            }
+        }
+
+        assertNotNull("Generated type for grouping-grouping-test wasn't generated", groupingGroupingTest);
+        assertEquals("GroupingGroupingTest interface - incorrect number of occurences", 1, groupingGroupingTestCounter);
+        assertEquals("GroupingGroupingTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.grouping.rev130718",
+                groupingGroupingTest.getPackageName());
+
+        assertNotNull("Generated type for grouping-test wasn't generated", groupingTest);
+        assertEquals("GroupingTest interface - incorrect number of occurences", 1, groupingTestCount);
+        assertEquals("GroupingTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.grouping.rev130718", groupingTest.getPackageName());
+
+        containsInterface("GroupingGroupingTest", groupingTest);
+
+        assertEquals("Number of method in GroupingGroupingTest is incorrect", 1, groupingGroupingTest
+                .getMethodDefinitions().size());
+        assertEquals("Number of method in GroupingTest is incorrect", 1, groupingTest.getMethodDefinitions().size());
+
+        containsMethods(groupingGroupingTest.getMethodDefinitions(), new NameTypePattern("getLeafGroupingGrouping",
+                "String"));
+
+        containsMethods(groupingTest.getMethodDefinitions(), new NameTypePattern("getLeafGroupingTest", "Byte"));
+    }
+
+    @Test
+    public void usesInListTest() throws IOException {
+        List<File> testModels = loadTestResources("/uses-of-grouping/uses-of-grouping-list.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        int listTestCounter = 0;
+        int groupingListTestCounter = 0;
+        int containerGroupingListTestCounter = 0;
+        int listGroupingListTestCounter = 0;
+        GeneratedType listTest = null;
+        GeneratedType groupingListTest = null;
+        GeneratedType containerGroupingListTest = null;
+        GeneratedType listGroupingListTest = null;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("GroupingListTest")) {
+                    groupingListTest = genType;
+                    groupingListTestCounter++;
+                } else if (genType.getName().equals("ListTest")) {
+                    listTest = genType;
+                    listTestCounter++;
+                } else if (genType.getName().equals("ContainerGroupingListTest")) {
+                    containerGroupingListTest = genType;
+                    containerGroupingListTestCounter++;
+                } else if (genType.getName().equals("ListGroupingListTest")) {
+                    listGroupingListTest = genType;
+                    listGroupingListTestCounter++;
+                }
+            }
+        }
+
+        assertNotNull("Generated type for grouping-list-test wasn't generated", groupingListTest);
+        assertEquals("GroupingListTest interface - incorrect number of occurences", 1, groupingListTestCounter);
+        assertEquals("GroupingListTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.list.rev130718", groupingListTest.getPackageName());
+
+        assertNotNull("Generated type for list-test wasn't generated", listTest);
+        assertEquals("ListTest interface - incorrect number of occurences", 1, listTestCounter);
+        assertEquals("ListTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.list.rev130718", listTest.getPackageName());
+
+        assertNotNull("Generated type for container-grouping-list-test wasn't generated", containerGroupingListTest);
+        assertEquals("ContainerGroupingListTest interface - incorrect number of occurences", 1,
+                containerGroupingListTestCounter);
+        assertEquals("ContainerGroupingListTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.list.rev130718.grouping.list.test",
+                containerGroupingListTest.getPackageName());
+
+        assertNotNull("Generated type for list-grouping-list-test wasn't generated", listGroupingListTest);
+        assertEquals("ListGroupingListTest interface - incorrect number of occurences", 1, listGroupingListTestCounter);
+        assertEquals("ListGroupingListTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.list.rev130718.grouping.list.test",
+                listGroupingListTest.getPackageName());
+
+        containsInterface("GroupingListTest", listTest);
+
+        assertEquals("Number of method in GroupingListTest is incorrect", 4, groupingListTest.getMethodDefinitions()
+                .size());
+        assertEquals("Number of method in ListTest is incorrect", 1, listTest.getMethodDefinitions().size());
+        assertEquals("Number of method in ContainerGroupingListTest is incorrect", 1, containerGroupingListTest
+                .getMethodDefinitions().size());
+        assertEquals("Number of method in ListGroupingListTest is incorrect", 1, listGroupingListTest
+                .getMethodDefinitions().size());
+
+        containsMethods(groupingListTest.getMethodDefinitions(), new NameTypePattern("getContainerGroupingListTest",
+                "ContainerGroupingListTest"), new NameTypePattern("getLeafGroupingListTest", "String"),
+                new NameTypePattern("getLeaffllistGroupingListTest", "List<String>"), new NameTypePattern(
+                        "getListGroupingListTest", "List<ListGroupingListTest>"));
+        containsMethods(listTest.getMethodDefinitions(), new NameTypePattern("getListLeafTest", "String"));
+        containsMethods(containerGroupingListTest.getMethodDefinitions(), new NameTypePattern(
+                "getLeafContainerGroupingListTest", "Short"));
+        containsMethods(listGroupingListTest.getMethodDefinitions(), new NameTypePattern("getLeafListGroupingListTest",
+                "Integer"));
+    }
+
+    @Test
+    public void usesInModulTest() throws IOException {
+        List<File> testModels = loadTestResources("/uses-of-grouping/uses-of-grouping-modul.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        int groupingModulTestCounter = 0;
+        int groupingUsesModulDataCounter = 0;
+        GeneratedType groupingModulTest = null;
+        GeneratedType groupingUsesModulData = null;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("GroupingModulTest")) {
+                    groupingModulTest = genType;
+                    groupingModulTestCounter++;
+                } else if (genType.getName().equals("GroupingUsesModulData")) {
+                    groupingUsesModulData = genType;
+                    groupingUsesModulDataCounter++;
+                }
+            }
+        }
+
+        assertNotNull("Generated type for grouping-list-test wasn't generated", groupingModulTest);
+        assertEquals("GroupingModulTest interface - incorrect number of occurences", 1, groupingModulTestCounter);
+        assertEquals("GroupingModulTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.modul.rev130718", groupingModulTest.getPackageName());
+
+        assertNotNull("Generated type for modul wasn't generated", groupingUsesModulData);
+        assertEquals("GroupingUsesModulData interface - incorrect number of occurences", 1,
+                groupingUsesModulDataCounter);
+        assertEquals("GroupingUsesModulData isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.modul.rev130718",
+                groupingUsesModulData.getPackageName());
+
+        containsInterface("GroupingModulTest", groupingUsesModulData);
+
+        assertEquals("Number of method in GroupingUsesModulData is incorrect", 0, groupingUsesModulData
+                .getMethodDefinitions().size());
+        assertEquals("Number of method in GroupingModulTest is incorrect", 2, groupingModulTest.getMethodDefinitions()
+                .size());
+
+        containsMethods(groupingModulTest.getMethodDefinitions(), new NameTypePattern("getLeafGroupingModulTest",
+                "String"), new NameTypePattern("getLeafGroupingModulTest2", "Short"));
+    }
+
+    @Test
+    public void usesInRpcTest() throws IOException {
+        List<File> testModels = loadTestResources("/uses-of-grouping/uses-of-grouping-rpc.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        int rpcTestInputCounter = 0;
+        int rpcTestOutputCounter = 0;
+        int groupingRpcInputTestCounter = 0;
+        int groupingRpcOutputTestCounter = 0;
+        int containerGroupingRpcInputTestCounter = 0;
+        GeneratedType rpcTestInput = null;
+        GeneratedType rpcTestOutput = null;
+        GeneratedType groupingRpcInputTest = null;
+        GeneratedType groupingRpcOutputTest = null;
+        GeneratedType containerGroupingRpcInputTest = null;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("RpcTestInput")) {
+                    rpcTestInput = genType;
+                    rpcTestInputCounter++;
+                } else if (genType.getName().equals("RpcTestOutput")) {
+                    rpcTestOutput = genType;
+                    rpcTestOutputCounter++;
+                } else if (genType.getName().equals("GroupingRpcInputTest")) {
+                    groupingRpcInputTest = genType;
+                    groupingRpcInputTestCounter++;
+                } else if (genType.getName().equals("GroupingRpcOutputTest")) {
+                    groupingRpcOutputTest = genType;
+                    groupingRpcOutputTestCounter++;
+                } else if (genType.getName().equals("ContainerGroupingRpcInputTest")) {
+                    containerGroupingRpcInputTest = genType;
+                    containerGroupingRpcInputTestCounter++;
+                }
+
+            }
+        }
+
+        assertNotNull("Generated type for RPC test input wasn't generated", rpcTestInput);
+        assertEquals("RpcTestInput interface - incorrect number of occurences", 1, rpcTestInputCounter);
+        assertEquals("RpcTestInput isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.rpc.rev130718", rpcTestInput.getPackageName());
+
+        assertNotNull("Generated type for RPC test output wasn't generated", rpcTestOutput);
+        assertEquals("RpcTestOutput interface - incorrect number of occurences", 1, rpcTestOutputCounter);
+        assertEquals("RpcTestOutput isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.rpc.rev130718", rpcTestOutput.getPackageName());
+
+        assertNotNull("Generated type for grouping-rpc-input-test wasn't generated", groupingRpcInputTest);
+        assertEquals("RpcTestOutput interface - incorrect number of occurences", 1, groupingRpcInputTestCounter);
+        assertEquals("GroupingRpcInputTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.rpc.rev130718", groupingRpcInputTest.getPackageName());
+
+        assertNotNull("Generated type for grouping-rpc-output-test wasn't generated", groupingRpcOutputTest);
+        assertEquals("RpcTestOutput interface - incorrect number of occurences", 1, groupingRpcOutputTestCounter);
+        assertEquals("GroupingRpcOutputTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.rpc.rev130718", groupingRpcOutputTest.getPackageName());
+
+        assertNotNull("Generated type for container-grouping-rpc-input-test wasn't generated",
+                containerGroupingRpcInputTest);
+        assertEquals("ContainerGroupingRpcInputTest interface - incorrect number of occurences", 1,
+                containerGroupingRpcInputTestCounter);
+        assertEquals("ContainerGroupingRpcInputTest isn't in correct package",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.rpc.rev130718.grouping.rpc.input.test",
+                containerGroupingRpcInputTest.getPackageName());
+
+        containsInterface("GroupingRpcInputTest", rpcTestInput);
+        containsInterface("GroupingRpcOutputTest", rpcTestOutput);
+
+        assertEquals("Number of method in RpcTestInput is incorrect", 0, rpcTestInput.getMethodDefinitions().size());
+        assertEquals("Number of method in RpcTestOutput is incorrect", 0, rpcTestOutput.getMethodDefinitions().size());
+        assertEquals("Number of method in GroupingRpcInputTest is incorrect", 2, groupingRpcInputTest
+                .getMethodDefinitions().size());
+        assertEquals("Number of method in GroupingRpcOutputTest is incorrect", 1, groupingRpcOutputTest
+                .getMethodDefinitions().size());
+        assertEquals("Number of method in ContainerGroupingRpcInputTest is incorrect", 1, containerGroupingRpcInputTest
+                .getMethodDefinitions().size());
+
+        containsMethods(groupingRpcInputTest.getMethodDefinitions(), new NameTypePattern(
+                "getContainerGroupingRpcInputTest", "ContainerGroupingRpcInputTest"), new NameTypePattern(
+                "getLeaflistGroupingRpcInputTest", "List<Short>"));
+        containsMethods(groupingRpcOutputTest.getMethodDefinitions(), new NameTypePattern(
+                "getLeafGroupingRpcOutputTest", "Byte"));
+        containsMethods(containerGroupingRpcInputTest.getMethodDefinitions(), new NameTypePattern(
+                "getLeafContainerGroupingRpcInputTest", "String"));
+    }
+
+    @Test
+    public void usesInAugmentTest() throws IOException {
+        List<File> testModels = loadTestResources("/uses-of-grouping/uses-of-grouping-augment.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        GeneratedType containerAugment1 = null;
+        GeneratedType groupingAugmentTest = null;
+        int containerAugment1Counter = 0;
+        int groupingAugmentTestCounter = 0;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("ContainerAugment1")) {
+                    containerAugment1 = genType;
+                    containerAugment1Counter++;
+                } else if (genType.getName().equals("GroupingAugmentTest")) {
+                    groupingAugmentTest = genType;
+                    groupingAugmentTestCounter++;
+                }
+            }
+        }
+
+        assertNotNull("Generated type for augment /container-augment wasn't generated.", containerAugment1);
+        assertEquals("ContainerAugment1 interface generated more than one time.", 1, containerAugment1Counter);
+        assertEquals("ContainerAugment1 is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.augment.rev130718", containerAugment1.getPackageName());
+
+        assertNotNull("Generated type for grouping-augment-test wasn't generated.", groupingAugmentTest);
+        assertEquals("GroupingAugmentTest interface generated more than one time.", 1, groupingAugmentTestCounter);
+        assertEquals("groupingAugmentTest is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.augment.rev130718",
+                groupingAugmentTest.getPackageName());
+
+        containsInterface("GroupingAugmentTest", containerAugment1);
+
+        assertEquals("Number of method in GroupingCaseTest is incorrect", 0, containerAugment1.getMethodDefinitions()
+                .size());
+
+        assertEquals("Number of method in ContainerAugment1 is incorrect", 0, containerAugment1.getMethodDefinitions()
+                .size());
+        assertEquals("Number of method in GroupingCaseTest is incorrect", 1, groupingAugmentTest.getMethodDefinitions()
+                .size());
+
+        containsMethods(groupingAugmentTest.getMethodDefinitions(), new NameTypePattern("getLeafGroupingAugmentTest",
+                "String"));
+    }
+
+    @Test
+    public void usesInNotification() throws IOException {
+        List<File> testModels = loadTestResources("/uses-of-grouping/uses-of-grouping-notification.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl(true);
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        GeneratedType notificationTest = null;
+        GeneratedType groupingNotificationTest = null;
+        GeneratedType containerGroupingNotificationTest = null;
+        int notificationTestCounter = 0;
+        int groupingNotificationTestCounter = 0;
+        int containerGroupingNotificationTestCounter = 0;
+
+        for (Type type : genTypes) {
+            if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+                GeneratedType genType = (GeneratedType) type;
+                if (genType.getName().equals("NotificationTest")) {
+                    notificationTest = genType;
+                    notificationTestCounter++;
+                } else if (genType.getName().equals("GroupingNotificationTest")) {
+                    groupingNotificationTest = genType;
+                    groupingNotificationTestCounter++;
+                } else if (genType.getName().equals("ContainerGroupingNotificationTest")) {
+                    containerGroupingNotificationTest = genType;
+                    containerGroupingNotificationTestCounter++;
+                }
+            }
+        }
+
+        assertNotNull("Generated type for notification-test wasn't generated.", notificationTest);
+        assertEquals("NotificationTest interface generated more than one time.", 1, notificationTestCounter);
+        assertEquals("NotificationTest is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.notification.rev130718",
+                notificationTest.getPackageName());
+
+        assertNotNull("Generated type for grouping-notification-test wasn't generated.", groupingNotificationTest);
+        assertEquals("GroupingNotificationTest interface generated more than one time.", 1,
+                groupingNotificationTestCounter);
+        assertEquals("groupingNotificationTest is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.notification.rev130718",
+                groupingNotificationTest.getPackageName());
+
+        assertNotNull("Generated type for container-grouping-notification-test wasn't generated.",
+                containerGroupingNotificationTest);
+        assertEquals("ContainerGroupingNotificationTest interface generated more than one time.", 1,
+                containerGroupingNotificationTestCounter);
+        assertEquals("ContainerGroupingNotificationTest is in wrong package.",
+                "org.opendaylight.yang.gen.v1.urn.grouping.uses.notification.rev130718.grouping.notification.test",
+                containerGroupingNotificationTest.getPackageName());
+
+        containsInterface("GroupingNotificationTest", notificationTest);
+
+        assertEquals("Number of method in NotificationTest is incorrect", 1, notificationTest.getMethodDefinitions()
+                .size());
+        assertEquals("Number of method in GroupingNotificationTest is incorrect", 2, groupingNotificationTest
+                .getMethodDefinitions().size());
+        assertEquals("Number of method in ContainerGroupingNotificationTest is incorrect", 1,
+                containerGroupingNotificationTest.getMethodDefinitions().size());
+
+        containsMethods(notificationTest.getMethodDefinitions(), new NameTypePattern("getLeafNotificationTest",
+                "String"));
+        containsMethods(groupingNotificationTest.getMethodDefinitions(), new NameTypePattern(
+                "getContainerGroupingNotificationTest", "ContainerGroupingNotificationTest"), new NameTypePattern(
+                "getLeaffllistGroupingNotificationTest", "List<String>"));
+        containsMethods(containerGroupingNotificationTest.getMethodDefinitions(), new NameTypePattern(
+                "getLeafContainerGroupingNotificationTest", "Long"));
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/NodeWrappedTypeTest.java b/code-generator/binding-generator-impl/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/NodeWrappedTypeTest.java
new file mode 100644 (file)
index 0000000..e6d895d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class NodeWrappedTypeTest {
+
+    @Test
+    public void test() {
+        NodeWrappedType nwt1 = new NodeWrappedType("obj1");
+        NodeWrappedType nwt2 = new NodeWrappedType("obj2");
+        NodeWrappedType nwt3 = new NodeWrappedType("obj1");
+        String str = "obj3";
+
+        assertTrue("Node nwt1 should equal to itself.", nwt1.equals(nwt1));
+        assertFalse("It can't be possible to compare nwt with string.", nwt1.equals(str));
+        assertFalse("nwt1 shouldn't equal to nwt2.", nwt1.equals(nwt2));
+        assertTrue("Node nwt1 should equal to nwt3.", nwt1.equals(nwt3));
+
+        assertEquals("toString method is returning incorrect value.", "NodeWrappedType{wrappedType=obj1}",
+                nwt1.toString());
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/abstract-topology.yang b/code-generator/binding-generator-impl/src/test/resources/abstract-topology.yang
new file mode 100644 (file)
index 0000000..863b223
--- /dev/null
@@ -0,0 +1,96 @@
+module abstract-topology {
+    yang-version 1;
+    namespace "urn:model:abstract:topology";
+    prefix "tp";
+
+    import ietf-inet-types { 
+        prefix "inet"; 
+        revision-date 2010-09-24;
+    }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description
+        "This module contains the definitions of elements that creates network 
+    topology i.e. definition of network nodes and links. This module is not designed to be used solely for network representation. This module SHOULD be used as base module in defining the network topology.";
+
+    revision "2013-02-08" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+    
+    revision "2013-01-01" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+    
+    typedef node-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id";
+        }
+        description "This type is used for leafs that reference network node instance.";
+    }
+
+    typedef link-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-links/tp:network-link/tp:link-id";
+        }
+        description "This type is used for leafs that reference network link instance.";
+    }
+
+    container topology {
+        description "This is the model of abstract topology which contains only Network Nodes and Network Links. Each topology MUST be identified by unique topology-id for reason that the store could contain many topologies.";
+
+        leaf topology-id {
+            type inet:uri;
+            description "It is presumed that datastore will contain many topologies. To distinguish between topologies it is vital to have
+            UNIQUE topology identifier.";
+        }
+
+        container network-nodes {
+            list network-node {
+                key "node-id";
+
+                leaf node-id {
+                    type inet:uri;
+                    description "The Topology identifier of network-node.";
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Node contains.";
+                }
+                description "The list of network nodes defined for topology.";
+            }
+        }
+        
+        container network-links {
+            list network-link {
+                key "link-id";
+
+                leaf link-id {
+                    type inet:uri;
+                    description "";
+                }
+
+                container source-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Source node identifier.";
+                    }
+                }
+
+                container destination-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Destination node identifier.";
+                    }
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Link contains.";
+                }
+                description "The Network Link which is defined by Local (Source) and Remote (Destination) Network Nodes. Every link MUST be defined either by identifier and
+                his local and remote Network Nodes (In real applications it is common that many links are originated from one node and end up in same remote node). To ensure that we would always know to distinguish between links, every link SHOULD have identifier.";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/augment-relative-xpath-models/abstract-topology@2013-02-08.yang b/code-generator/binding-generator-impl/src/test/resources/augment-relative-xpath-models/abstract-topology@2013-02-08.yang
new file mode 100644 (file)
index 0000000..7fe9e74
--- /dev/null
@@ -0,0 +1,71 @@
+module abstract-topology {
+    yang-version 1;
+    namespace "urn:model:abstract:topology";
+    prefix "tp";
+
+    revision "2013-02-08" {
+    }
+
+    typedef node-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id";
+        }
+    }
+
+    typedef link-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-links/tp:network-link/tp:link-id";
+        }
+    }
+
+    typedef uri {
+        type string;
+    }
+
+    container topology {
+
+        leaf topology-id {
+            type uri;
+        }
+
+        container network-nodes {
+            list network-node {
+                key "node-id";
+
+                leaf node-id {
+                    type uri;
+                }
+
+                container attributes {
+                }
+            }
+        }
+
+        container network-links {
+            list network-link {
+                key "link-id";
+
+                leaf link-id {
+                    type uri;
+                    description "";
+                }
+
+                container source-node {
+                    leaf id {
+                        type node-id-ref;
+                    }
+                }
+
+                container destination-node {
+                    leaf id {
+                        type node-id-ref;
+                    }
+                }
+
+                container attributes {
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/augment-relative-xpath-models/augment-abstract-topology@2013-05-03.yang b/code-generator/binding-generator-impl/src/test/resources/augment-relative-xpath-models/augment-abstract-topology@2013-05-03.yang
new file mode 100644 (file)
index 0000000..6e6aec1
--- /dev/null
@@ -0,0 +1,60 @@
+module augment-abstract-topology {
+    yang-version 1;
+    namespace "urn:model:augment:abstract:topology";
+    prefix "atp";
+
+    import ietf-interfaces {
+        prefix "if";
+        revision-date 2012-11-15;
+    }
+
+    import abstract-topology {
+        prefix "at";
+        revision-date 2013-02-08;
+    }
+
+    revision "2013-05-03" {
+    }
+
+    augment "/at:topology" {
+        container interfaces {
+            list interface {
+                key "interface-id";
+
+                leaf interface-id {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:name";
+                    }
+                }
+
+                leaf-list higher-layer-if {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:higher-layer-if";
+                    }
+                }
+            }
+        }
+    }
+
+    augment "/at:topology/at:network-links/at:network-link" {
+        container tunnels {
+            list tunnel {
+                key "tunnel-id";
+
+                leaf tunnel-id {
+                    type leafref {
+                        path "../../../at:link-id";
+                    }
+                }
+            }
+        }
+    }
+
+    augment "/at:topology/at:network-links/at:network-link" {
+        leaf interface {
+            type leafref {
+                path "../../../atp:interfaces/atp:interface/atp:interface-id";
+            }
+        }
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/augment-relative-xpath-models/ietf-interfaces@2012-11-15.yang b/code-generator/binding-generator-impl/src/test/resources/augment-relative-xpath-models/ietf-interfaces@2012-11-15.yang
new file mode 100644 (file)
index 0000000..4518e0e
--- /dev/null
@@ -0,0 +1,33 @@
+module ietf-interfaces {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+  prefix if;
+
+  revision 2012-11-15 {
+  }
+
+  typedef interface-ref {
+    type leafref {
+      path "/if:interfaces/if:interface/if:name";
+    }
+  }
+
+
+  container interfaces {
+
+    list interface {
+      key "name";
+      unique "type location";
+
+      leaf name {
+        type string;
+      }
+
+      leaf-list higher-layer-if {
+        type interface-ref;
+        config false;
+      }
+
+    }
+  }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/augment-test-models/abstract-topology@2013-02-08.yang b/code-generator/binding-generator-impl/src/test/resources/augment-test-models/abstract-topology@2013-02-08.yang
new file mode 100644 (file)
index 0000000..249e1f6
--- /dev/null
@@ -0,0 +1,87 @@
+module abstract-topology {
+    yang-version 1;
+    namespace "urn:model:abstract:topology";
+    prefix "tp";
+
+    revision "2013-02-08" {
+        reference "http://www.opendaylight.org/";
+    }
+    
+    typedef node-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id";
+        }
+        description "This type is used for leafs that reference network node instance.";
+    }
+
+    typedef link-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-links/tp:network-link/tp:link-id";
+        }
+        description "This type is used for leafs that reference network link instance.";
+    }
+
+    container topology {
+        description "This is the model of abstract topology which contains 
+        only Network Nodes and Network Links. Each topology MUST be identified by unique 
+        topology-id for reason that the store could contain many topologies.";
+
+        leaf topology-id {
+            type string;
+            description "It is presumed that datastore will contain many topologies. 
+            To distinguish between topologies it is vital to have
+            UNIQUE topology identifier.";
+        }
+
+        container network-nodes {
+            list network-node {
+                key "node-id";
+
+                leaf node-id {
+                    type string;
+                    description "The Topology identifier of network-node.";
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Node contains.";
+                }
+                description "The list of network nodes defined for topology.";
+            }
+        }
+        
+        container network-links {
+            list network-link {
+                key "link-id";
+
+                leaf link-id {
+                    type string;
+                    description "";
+                }
+
+                container source-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Source node identifier.";
+                    }
+                }
+
+                container destination-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Destination node identifier.";
+                    }
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Link contains.";
+                }
+                description "The Network Link which is defined by Local (Source) and Remote (Destination) 
+                Network Nodes. Every link MUST be defined either by identifier and
+                his local and remote Network Nodes (In real applications it is common that 
+                many links are originated from one node and end up in same remote node). 
+                To ensure that we would always know to distinguish between links, every link 
+                SHOULD have identifier.";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/augment-test-models/augment-abstract-topology@2013-05-03.yang b/code-generator/binding-generator-impl/src/test/resources/augment-test-models/augment-abstract-topology@2013-05-03.yang
new file mode 100644 (file)
index 0000000..5d5eee7
--- /dev/null
@@ -0,0 +1,68 @@
+module augment-abstract-topology {
+    yang-version 1;
+    namespace "urn:model:augment:abstract:topology";
+    prefix "atp";
+
+    import ietf-interfaces {
+        prefix "if";
+        revision-date 2012-11-15;
+    }
+
+    import abstract-topology {
+        prefix "at";
+        revision-date 2013-02-08;
+    }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-05-03" {
+        reference "http://www.opendaylight.org/";
+    }
+
+    augment "/at:topology" {
+        container interfaces {
+            list interface {
+                key "interface-id";
+
+                leaf interface-id {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:name";
+                    }
+                }
+
+                leaf-list higher-layer-if {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:higher-layer-if";
+                    }
+                }
+            }
+        }
+    }
+
+    augment "/at:topology/at:network-links/at:network-link" {
+        container tunnels {
+            list tunnel {
+                key "tunnel-id";
+
+                leaf tunnel-id {
+                    type int32;
+                }
+                
+                container foo {
+                    leaf bar {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+    augment "/at:topology/at:network-links/at:network-link" {
+        leaf interface {
+            type leafref {
+                path "/at:topology/atp:interfaces/atp:interface/atp:interface-id";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/augment-test-models/augment-network-link-attributes@2013-05-03.yang b/code-generator/binding-generator-impl/src/test/resources/augment-test-models/augment-network-link-attributes@2013-05-03.yang
new file mode 100644 (file)
index 0000000..2f0fe0f
--- /dev/null
@@ -0,0 +1,31 @@
+module augment-network-link-attributes {
+    yang-version 1;
+    namespace "urn:model:augment:network:link:attributes";
+    prefix "tp";
+
+    import abstract-topology {
+        prefix "at";
+        revision-date 2013-02-08;
+    }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-05-03" {
+        reference "http://www.opendaylight.org/";
+    }
+
+    augment "/at:topology/at:network-links/at:network-link/at:attributes" {
+        leaf longitude {
+            type decimal64 {    
+                fraction-digits 2;
+            }
+        }
+
+        leaf latitude {
+            type decimal64 {    
+                fraction-digits 2;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/augment-test-models/augment-topology-tunnels@2013-05-03.yang b/code-generator/binding-generator-impl/src/test/resources/augment-test-models/augment-topology-tunnels@2013-05-03.yang
new file mode 100644 (file)
index 0000000..caa7072
--- /dev/null
@@ -0,0 +1,28 @@
+module augment-topology-tunnels {
+    yang-version 1;
+    namespace "urn:model:augment:topology:tunnels";
+    prefix "tp";
+
+    import abstract-topology {
+        prefix "at";
+        revision-date 2013-02-08;
+    }
+
+    import augment-abstract-topology {
+        prefix "aug-at";
+        revision-date 2013-05-03;
+    }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-05-03" {
+        reference "http://www.opendaylight.org/";
+    }
+
+    augment "/at:topology/at:network-links/at:network-link/aug-at:tunnels/aug-at:tunnel" {
+        leaf tunnel-name {
+            type string;
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/augment-test-models/ietf-interfaces@2012-11-15.yang b/code-generator/binding-generator-impl/src/test/resources/augment-test-models/ietf-interfaces@2012-11-15.yang
new file mode 100644 (file)
index 0000000..4518e0e
--- /dev/null
@@ -0,0 +1,33 @@
+module ietf-interfaces {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+  prefix if;
+
+  revision 2012-11-15 {
+  }
+
+  typedef interface-ref {
+    type leafref {
+      path "/if:interfaces/if:interface/if:name";
+    }
+  }
+
+
+  container interfaces {
+
+    list interface {
+      key "name";
+      unique "type location";
+
+      leaf name {
+        type string;
+      }
+
+      leaf-list higher-layer-if {
+        type interface-ref;
+        config false;
+      }
+
+    }
+  }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/binary-type-test-models/binary-type-test.yang b/code-generator/binding-generator-impl/src/test/resources/binary-type-test-models/binary-type-test.yang
new file mode 100644 (file)
index 0000000..14735c3
--- /dev/null
@@ -0,0 +1,57 @@
+module binary-type-test {
+    yang-version 1;
+    namespace "urn:binary:types:model";
+    prefix "btt";
+
+    import binary-types {
+        prefix "bin";
+        revision-date 2013-06-13;
+    }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description
+        "Simple test to test imported binary types and resolving of binary
+        type in leaf statement.";
+
+    revision "2013-06-13" {
+        reference "NO REF";
+    }
+
+    typedef binary-type {
+        type binary {
+            length 128;
+        }
+    }
+
+    container container-foo {
+        leaf binary-leaf {
+            type binary {
+                length 128;
+            }
+        }
+
+        list binary-list {
+            key "binary-key";
+
+            leaf binary-key {
+                type btt:binary-type;
+            }
+
+            leaf imported-simple-binary {
+                type bin:simple-binary;
+            }
+        }
+
+        leaf imported-restrict-binary {
+            type bin:restricted-binary;
+        }
+
+        leaf-list binary-leaf-list {
+            type binary {
+                length 256;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/binary-type-test-models/binary-types@2013-06-13.yang b/code-generator/binding-generator-impl/src/test/resources/binary-type-test-models/binary-types@2013-06-13.yang
new file mode 100644 (file)
index 0000000..df55441
--- /dev/null
@@ -0,0 +1,38 @@
+ module binary-types {
+
+   namespace "urn:binary:types";
+   prefix "bin";
+
+   organization "OPEN DAYLIGHT";
+
+   contact "http://www.opendaylight.org/";
+
+   description "Stand alone binary types declaration file for testing
+   purposes only.";
+
+   revision 2013-06-13 {
+     description
+      "Initial revision.";
+     reference
+      "NO REFERENCE";
+   }
+
+   /*** collection of protocol field related types ***/
+
+   typedef simple-binary {
+     type binary;
+   }
+
+   typedef restricted-binary {
+     type binary {
+        length 24;
+     }
+   }
+
+   typedef composite-binary {
+     type union {
+        type bin:simple-binary;
+        type bin:restricted-binary;
+     }
+   }
+ }
diff --git a/code-generator/binding-generator-impl/src/test/resources/binding-generator-impl-test/choice-test.yang b/code-generator/binding-generator-impl/src/test/resources/binding-generator-impl-test/choice-test.yang
new file mode 100644 (file)
index 0000000..6b8ff93
--- /dev/null
@@ -0,0 +1,47 @@
+module choice-test {
+    yang-version 1;
+    namespace "uri:choice-test";
+    prefix tst;
+
+    revision 2014-10-07 {
+        description
+                "Choice test.";
+    }
+
+    choice mychoice {
+        case one {
+            container mycontainer {
+                leaf mychoiceleafone {
+                    type string;
+                }
+            }
+        }
+        case two {
+            list mylist {
+                leaf mychoiceleaftwo {
+                    type int16;
+                }
+            }
+        }
+    }
+
+    container myrootcontainer {
+        choice mychoice2 {
+            case one2 {
+                container mycontainer2 {
+                    leaf mychoiceleafone2 {
+                        type string;
+                    }
+                }
+            }
+            case two2 {
+                list mylist2 {
+                    leaf mychoiceleaftwo2 {
+                        type int16;
+                    }
+                }
+            }
+        }
+    }
+}
+
diff --git a/code-generator/binding-generator-impl/src/test/resources/binding-generator-impl-test/notification-test.yang b/code-generator/binding-generator-impl/src/test/resources/binding-generator-impl-test/notification-test.yang
new file mode 100644 (file)
index 0000000..e014af0
--- /dev/null
@@ -0,0 +1,7 @@
+module notification-test {
+    namespace "notification-test";
+    prefix test;
+
+    notification foo {
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/bit_and_union.yang b/code-generator/binding-generator-impl/src/test/resources/bit_and_union.yang
new file mode 100644 (file)
index 0000000..6f76222
--- /dev/null
@@ -0,0 +1,90 @@
+module bit-and-union-in-leaf {
+
+    namespace "urn:bit:union:in:leaf";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-06-26 {
+
+    }
+
+    typedef union-typedef {
+        type union {
+            type string {
+                pattern "[a-g]";
+            }
+            type int16;
+        }
+    }
+
+    typedef union-typedef2 {
+        type union {
+            type string; 
+            type int16;
+        }
+    }    
+
+    container parent-container {
+        leaf bit-leaf {
+            type bits {
+                bit first-bit;
+                bit second-bit;
+                bit third-bit;
+            }
+        }
+
+        leaf union-leaf {
+            type union {
+                type int32;
+                type string {
+                    pattern "[a-z]";
+                }
+                type string {
+                    pattern "[0-9]*";
+                }
+                type string {
+                    pattern "[a-d]*";
+                    pattern "[0-5]*";
+                }
+                type uint8;
+            }
+        }
+        
+// nested union in leaf   
+        leaf lf {
+            type union {
+                               type string;
+                               type union {
+                                       type uint32;
+                                       type int8;
+                                       type string;
+                                       type union {
+                                               type string;
+                                               type uint64;
+                                       }       
+                               }
+                       }               
+               }        
+    }
+    
+
+
+// nested union in typedef     
+       typedef type-union {
+               type union {
+                       type string;
+                       type union {
+                               type uint32;
+                               type int8;
+                               type string;    
+                               type union {
+                                       type string;
+                                       type uint64;
+                               }                               
+                       }
+               }       
+               
+       }    
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/bit_and_union_in_leaf.yang b/code-generator/binding-generator-impl/src/test/resources/bit_and_union_in_leaf.yang
new file mode 100644 (file)
index 0000000..4146b13
--- /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
+ */
+module bit-and-union-in-leaf {
+    
+    namespace "urn:bit:union:in:leaf";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-06-26 {
+        
+    }
+    
+    typedef union-typedef {
+        type union {
+            type string {
+                pattern "[a-g]";
+            }
+            type int16;
+        }
+    }
+    
+    typedef union-typedef2 {
+        type union {
+            type string; 
+            type int16;
+        }
+    }    
+    
+    container parent-container {
+        leaf bit-leaf {
+            type bits {
+                bit first-bit;
+                bit second-bit;
+                bit third-bit;
+            }
+        }
+        
+        leaf union-leaf {
+            type union {
+                type int32;
+                type string {
+                    pattern "[a-z]";
+                }
+                type string {
+                    pattern "[0-9]*";
+                }
+                type string {
+                    pattern "[a-d]*";
+                    pattern "[0-5]*";
+                }
+                type uint8;
+            }
+        }
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/augment-monitoring@2013-07-01.yang b/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/augment-monitoring@2013-07-01.yang
new file mode 100644 (file)
index 0000000..a9c357a
--- /dev/null
@@ -0,0 +1,88 @@
+module augment-monitoring {
+    yang-version 1;
+    namespace "urn:ietf:params:xml:ns:yang:augment-monitoring";
+    prefix "amon";
+
+    import choice-monitoring { prefix nm; }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-07-01" {
+            reference "NO REF";
+    }
+
+    augment "/nm:netconf-state/nm:datastores/nm:datastore/nm:locks/nm:lock-type" {
+        case autonomous-lock {
+            container autonomous-def {
+                leaf lock-id {
+                    type int32;
+                }
+
+                leaf lock-time {
+                    type uint32;
+                }
+            }
+        }
+
+        case anonymous-lock {
+            leaf lock-time {
+                type uint32;
+            }
+        }
+
+        leaf leaf-aug-case {
+            type string;
+        }
+    }
+
+    augment "/nm:netconf-state/nm:datastores/nm:datastore/nm:locks/nm:lock-type/nm:partial-lock" {
+        choice aug-case-by-choice {
+            case foo {
+                leaf foo {
+                    type string;
+                }
+            }
+
+            case bar {
+                leaf bar {
+                    type boolean;
+                }
+            }
+        }
+    }
+
+    augment "/nm:netconf-state/nm:datastores/nm:datastore" {
+        choice storage-format {
+            case _xml {
+                container _xml-def {
+                    leaf file-name {
+                        type string;
+                    }
+                }
+            }
+
+            case yang {
+                leaf yang-file-name {
+                    type string;
+                }
+            }
+
+            case unknown-files {
+                list files {
+                    key "file-name";
+
+                    leaf file-name {
+                        type string;
+                    }
+
+                    container file-data {
+                        leaf utf8-data {
+                            type string;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/choice-monitoring@2013-07-01.yang b/code-generator/binding-generator-impl/src/test/resources/choice-case-type-test-models/choice-monitoring@2013-07-01.yang
new file mode 100644 (file)
index 0000000..230b329
--- /dev/null
@@ -0,0 +1,119 @@
+module choice-monitoring {
+  yang-version 1;
+  namespace "urn:ietf:params:xml:ns:yang:choice-monitoring";
+  prefix "ncm";
+
+  revision 2013-07-01 {
+  }
+
+  typedef tls-fingerprint-type {
+    type string {
+      pattern '([0-9a-fA-F]){2}(:([0-9a-fA-F]){2})*';
+    }
+  }
+
+  typedef netconf-datastore-type {
+    type enumeration {
+      enum running;
+      enum candidate;
+      enum startup;
+    }
+  }
+
+  container netconf-state {
+    config false;
+
+    container datastores {
+      list datastore {
+        key name;
+
+        leaf name {
+          type netconf-datastore-type;
+        }
+        container locks {
+          choice lock-type {
+
+            case global-lock {
+                container global-lock {
+
+                leaf locked-by-session {
+                  type uint32;
+                  mandatory true;
+                }
+
+                leaf locked-time {
+                  type string;
+                  mandatory true;
+                }
+
+                container capabilities {
+                  leaf-list capability {
+                      type string;
+                  }
+                }
+              }
+            }
+
+            case partial-lock {
+              list partial-lock {
+                  key lock-id;
+
+                  leaf lock-id {
+                    type uint32;
+                  }
+                  leaf-list select {
+                    type string;
+                    min-elements 1;
+                  }
+                  leaf-list locked-node {
+                    type string;
+                  }
+              }
+            }
+
+            case fingerprint {
+              choice algorithm-and-hash {
+                  mandatory true;
+                  case md5 {
+                    leaf md5 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+
+                  case sha1 {
+                    leaf sha1 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+                  
+                  case sha224 {
+                    leaf sha224 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+                  
+                  case sha256 {
+                    leaf sha256 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+                  
+                  case sha384 {
+                    leaf sha384 {
+                      type tls-fingerprint-type;
+                    }
+                  }                
+                  
+                  case sha512 {
+                    leaf sha512 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/controller-models/controller-network.yang b/code-generator/binding-generator-impl/src/test/resources/controller-models/controller-network.yang
new file mode 100644 (file)
index 0000000..357e6ba
--- /dev/null
@@ -0,0 +1,172 @@
+module controller-network {
+       yang-version 1;
+       namespace "urn:opendaylight:controller:network";
+       prefix "topos";
+       
+       import ietf-inet-types { prefix "inet"; }
+       
+       revision 2013-05-20 {
+          description "Initial demo";
+       }
+       
+
+       
+       
+       typedef topology-id {
+               type string;
+       }
+
+       typedef node-id {
+               type string;
+       }
+
+       typedef link-id {
+               type string;
+       }
+
+       typedef tp-id {
+               type string;
+               description "identifier for termination points on a port";
+       }
+
+       typedef tp-ref {
+               type leafref {
+                       path "/network/topologies/topology/nodes/node/termination-points/termination-point/tp-id";
+               }
+       }
+       typedef topology-ref {
+               type leafref {
+                       path "/network/topologies/topology/topology-id";
+               }
+               description "This type is used for leafs that reference topology identifier instance.";
+               // currently not used
+       }
+
+       typedef node-ref {
+               type leafref {
+                       path "/network/topologies/topology/nodes/node/node-id";
+               }
+               description "This type is used for leafs that reference a node instance.";
+       }
+
+       typedef link-ref {
+               type leafref {
+                       path "/network/topologies/topology/links/link/link-id";
+               }
+               description "This type is used for leafs that reference a link instance.";
+               // currently not used
+       }
+       
+       typedef network-element-ref {
+               type leafref {
+                       path "/network/network-elements/network-element/element-id";
+               }
+       }
+
+
+       typedef element-id {
+               type string;
+       }
+       
+       container network {
+               container topologies {
+                       list topology {
+                               description "
+                                       This is the model of abstract topology which contains only Network
+                                       Nodes and Network Links. Each topology MUST be identified by
+                                       unique topology-id for reason that the store could contain many
+                                       topologies.
+                               ";
+                               key "topology-id";
+                               leaf topology-id {
+                                       type topology-id; 
+                                       description "
+                                               It is presumed that datastore will contain many topologies. To
+                                               distinguish between topologies it is vital to have UNIQUE
+                                               topology identifier.
+                                       ";
+                               }
+
+                               container types {
+                                       description "
+                                               The container for definition of topology types.
+                                               The augmenting modules should add empty optional leaf 
+                                               to this container to signalize topology type.
+                                       ";
+                               }
+
+                               container nodes {
+                                       list node {
+                                               description "The list of network nodes defined for topology.";
+
+                                               key "node-id";
+                                               leaf node-id {
+                                                       type node-id;
+                                                       description "The Topology identifier of network-node.";
+                                               }
+
+                                               leaf supporting-ne {
+                                                       type network-element-ref;
+                                               }
+                                               
+                                               container termination-points {
+                                                       list termination-point {
+                                                               key "tp-id";
+                                                               leaf tp-id {
+                                                                       type tp-id;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+               
+                               container links {
+                                       list link {
+                                               description "
+                                                       The Network Link which is defined by Local (Source) and
+                                                       Remote (Destination) Network Nodes. Every link MUST be
+                                                       defined either by identifier and his local and remote
+                                                       Network Nodes (in real applications it is common that many
+                                                       links are originated from one node and end up in same
+                                                       remote node). To ensure that we would always know to
+                                                       distinguish between links, every link SHOULD have
+                                                       identifier.
+                                               ";
+                                               key "link-id";
+               
+                                               leaf link-id {
+                                                       type link-id;
+                                               }
+                                               container source { 
+                                                       leaf source-node {
+                                                               type node-ref;
+                                                               description "Source node identifier.";
+                                                       }
+                                                       leaf source-tp {
+                                                               type tp-ref;
+                                                       }
+                                               }
+                                               container destination { 
+                                                       leaf dest-node {
+                                                               type node-ref;
+                                                               description "Destination node identifier.";
+                                                       }
+                                                       leaf dest-tp {
+                                                               type tp-ref;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               container network-elements {
+                       config true;
+                       list network-element {
+                               key "element-id";
+                               leaf element-id {
+                                       type element-id;
+                               }
+                       }
+               }
+       }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/controller-models/controller-openflow.yang b/code-generator/binding-generator-impl/src/test/resources/controller-models/controller-openflow.yang
new file mode 100644 (file)
index 0000000..f2cdd09
--- /dev/null
@@ -0,0 +1,79 @@
+module controller-openflow {
+
+    namespace "urn:opendaylight:controller:openflow";
+    prefix "of";
+    import controller-network {prefix cn;}
+    
+    
+    revision 2013-05-20 {
+       description "Initial demo";
+    }
+
+   
+
+
+
+    typedef datapath-id {
+        type string {
+            length 16;
+        }
+    }
+
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:types" {
+        leaf openflow {type string;}
+    }
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:links/cn:link/cn:source" {
+        when "../../../cn:types/of:openflow";
+
+        leaf logical-port {
+            type int32;
+        }
+    }
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:links/cn:link/cn:destination" {
+        when "../../../cn:types/of:openflow";
+
+        leaf logical-port {
+            type int32;
+        }
+    }
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:nodes/cn:node" {
+        when "../../../cn:types/of:openflow";
+        leaf datapath-id {
+            type datapath-id;
+        }
+    }
+    
+    augment "/cn:network/cn:network-elements/cn:network-element" {
+        leaf datapath-id {
+            type datapath-id;
+        }
+
+        container ports {
+            list port {
+                key "logical-port-id";
+                
+                leaf logical-port-id {
+                    type int32;
+                }
+
+                // Should be replaced with ref to interface
+                leaf physical-name {
+                    type string;
+                }
+            }
+        }
+        container flow-tables {
+            list flow-table {
+                key "flow-table-id";
+                leaf flow-table-id {
+                    type string;
+                }
+
+            }
+        }
+    }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/demo-topology.yang b/code-generator/binding-generator-impl/src/test/resources/demo-topology.yang
new file mode 100644 (file)
index 0000000..4fef1cd
--- /dev/null
@@ -0,0 +1,121 @@
+module demo-topology {
+       yang-version 1;
+    namespace "urn:model.1demo-275topology.4.5.my";
+    prefix "tp";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+               This module contains the definitions of elements that creates network 
+               topology i.e. definition of network nodes and links. This module is
+               not designed to be used solely for network representation. This module
+               SHOULD be used as base module in defining the network topology.
+       ";
+
+    revision "2013-02-08"{
+               reference " WILL BE DEFINED LATER";
+       }
+
+       container topology {
+        description "
+                       This is the model of abstract topology which contains only Network
+                       Nodes and Network Links. Each topology MUST be identified by
+                       unique topology-id for reason that the store could contain many
+                       topologies.
+               ";
+
+        leaf topology-id {
+            type string;
+            description "
+                               It is presumed that datastore will contain many topologies. To
+                               distinguish between topologies it is vital to have UNIQUE
+                               topology identifier.
+                       ";
+        }
+
+        container network-nodes {
+               list network-node {
+                   description "The list of network nodes defined for topology.";
+
+                       key "node-id";
+
+                       leaf node-id {
+                               type string;
+                               description "The Topology identifier of network-node.";
+                       }
+                
+                list network-interface {
+                    key "interface-id";
+                    
+                    leaf interface-id {
+                        type uint8;
+                    }
+                    
+                    leaf interface-address {
+                        type string;
+                    }
+                }
+                
+                   container node-attributes {
+                                       description "
+                                               Additional attributes that can Network Node contains.
+                                       ";
+
+                                       leaf geo-latitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
+
+                                       leaf geo-longitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
+                               }
+               }
+        }
+        
+        container network-links {
+               list network-link {
+                   description "
+                                       The Network Link which is defined by Local (Source) and
+                                       Remote (Destination) Network Nodes. Every link MUST be
+                                       defined either by identifier and his local and remote
+                                       Network Nodes (in real applications it is common that many
+                                       links are originated from one node and end up in same
+                                       remote node). To ensure that we would always know to
+                                       distinguish between links, every link SHOULD have
+                                       identifier.
+                               ";
+                       key "link-id";
+
+                       leaf link-id {
+                               type string;
+                               description "";
+                       }
+
+                   container source {
+                                       leaf node-id {
+                                               type string;
+                                               description "Source node identifier.";
+                                       }
+                               }
+
+                               container destination {
+                                       leaf node-id {
+                                               type string;
+                                               description "Destination node identifier.";
+                                       }
+                               }
+
+                               container link-attributes {
+                                       description "Aditional attributes that can Network Link contains.";
+                               }
+                   }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/enum-test-models/abstract-topology@2013-02-08.yang b/code-generator/binding-generator-impl/src/test/resources/enum-test-models/abstract-topology@2013-02-08.yang
new file mode 100644 (file)
index 0000000..80e23b9
--- /dev/null
@@ -0,0 +1,148 @@
+module abstract-topology {
+    yang-version 1;
+    namespace "urn:model:abstract:topology";
+    prefix "tp";
+
+    import ietf-interfaces {
+        prefix "if";
+        revision-date 2012-11-15;
+    }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description
+        "This module contains the definitions of elements that creates network 
+    topology i.e. definition of network nodes and links. This module is not designed to be used solely for network representation. This module SHOULD be used as base module in defining the network topology.";
+
+    revision "2013-02-08" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+    
+    revision "2013-01-01" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+    
+    typedef node-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id";
+        }
+        description "This type is used for leafs that reference network node instance.";
+    }
+
+    typedef link-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-links/tp:network-link/tp:link-id";
+        }
+        description "This type is used for leafs that reference network link instance.";
+    }
+
+    typedef interface-id-ref {
+        type leafref {
+            path "/tp:topology/tp:interfaces/tp:interface/tp:interface-id";
+        }
+    }
+
+    container topology {
+        description "This is the model of abstract topology which contains only Network Nodes and Network Links. Each topology MUST be identified by unique topology-id for reason that the store could contain many topologies.";
+
+        leaf topology-id {
+            type string;
+            description "It is presumed that datastore will contain many topologies. To distinguish between topologies it is vital to have
+            UNIQUE topology identifier.";
+        }
+
+        container network-nodes {
+            list network-node {
+                key "node-id";
+
+                leaf node-id {
+                    type string;
+                    description "The Topology identifier of network-node.";
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Node contains.";
+                }
+                description "The list of network nodes defined for topology.";
+            }
+        }
+
+        container interfaces {
+            list interface {
+                key "interface-id";
+
+                leaf interface-id {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:name";
+                    }
+                }
+
+                leaf-list higher-layer-if {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:higher-layer-if";
+                    }
+                }
+
+                leaf oper-status {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:oper-status";
+                    }
+                }
+
+                leaf link-up-down-trap-enable {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:link-up-down-trap-enable";
+                    }
+                }
+            }
+        }
+        
+        container network-links {
+            list network-link {
+                key "link-id";
+
+                leaf link-id {
+                    type string;
+                    description "";
+                }
+
+                container source-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Source node identifier.";
+                    }
+                }
+
+                container destination-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Destination node identifier.";
+                    }
+                }
+
+                container tunnels {
+                    list tunnel {
+                        key "tunnel-id";
+
+                        leaf tunnel-id {
+                            type leafref {
+                                path "../../../link-id";
+                            }
+                        }
+                    }
+                }
+
+                leaf interface {
+                    type interface-id-ref;
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Link contains.";
+                }
+                description "The Network Link which is defined by Local (Source) and Remote (Destination) Network Nodes. Every link MUST be defined either by identifier and
+                his local and remote Network Nodes (In real applications it is common that many links are originated from one node and end up in same remote node). To ensure that we would always know to distinguish between links, every link SHOULD have identifier.";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/enum-test-models/ietf-interfaces@2012-11-15.yang b/code-generator/binding-generator-impl/src/test/resources/enum-test-models/ietf-interfaces@2012-11-15.yang
new file mode 100644 (file)
index 0000000..4cea378
--- /dev/null
@@ -0,0 +1,184 @@
+module ietf-interfaces {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+  prefix if;
+
+  import iana-if-type {
+    prefix ianaift;
+  }
+
+
+  revision 2012-11-15 {
+  }
+
+  /* Typedefs */
+
+  typedef interface-ref {
+    type leafref {
+      path "/if:interfaces/if:interface/if:name";
+    }
+    description
+      "This type is used by data models that need to reference
+       interfaces.";
+  }
+
+  /* Features */
+
+  feature arbitrary-names {
+    description
+      "This feature indicates that the server allows interfaces to
+       be named arbitrarily.";
+  }
+
+  feature if-mib {
+    description
+      "This feature indicates that the server implements IF-MIB.";
+    reference
+      "RFC 2863: The Interfaces Group MIB";
+  }
+
+  /* Data nodes */
+
+  container interfaces {
+    description
+      "Interface parameters.";
+
+    list interface {
+      key "name";
+      unique "type location";
+
+      description
+        "The list of interfaces on the device.";
+
+      leaf name {
+        type string;
+      }
+
+      leaf description {
+        type string;
+      }
+
+      leaf type {
+        type ianaift:iana-if-type;
+        mandatory true;
+      }
+
+      leaf location {
+        type string;
+      }
+
+      leaf enabled {
+        type boolean;
+        default "true";
+      }
+
+      leaf oper-status {
+        type enumeration {
+          enum up {
+            value 1;
+            description
+              "Ready to pass packets.";
+          }
+          enum down {
+            value 2;
+            description
+              "The interface does not pass any packets.";
+          }
+          enum testing {
+            value 3;
+            description
+              "In some test mode.  No operational packets can
+               be passed.";
+          }
+          enum unknown {
+            value 4;
+            description
+              "Status cannot be determined for some reason.";
+          }
+          enum dormant {
+            value 5;
+            description
+              "Waiting for some external event.";
+          }
+          enum not-present {
+            value 6;
+            description
+              "Some component is missing.";
+          }
+          enum lower-layer-down {
+            value 7;
+            description
+              "Down due to state of lower-layer interface(s).";
+          }
+        }
+        config false;
+        description
+          "The current operational state of the interface.
+
+           If 'enabled' is 'false' then 'oper-status'
+           should be 'down'.  If 'enabled' is changed to 'true'
+           then 'oper-status' should change to 'up' if the interface
+           is ready to transmit and receive network traffic; it
+           should change to 'dormant' if the interface is waiting for
+           external actions (such as a serial line waiting for an
+           incoming connection); it should remain in the 'down' state
+           if and only if there is a fault that prevents it from
+           going to the 'up' state; it should remain in the
+           'not-present' state if the interface has missing
+           (typically, hardware) components.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifOperStatus";
+      }
+
+      leaf last-change {
+        type string;
+        config false;
+      }
+
+      leaf if-index {
+        if-feature if-mib;
+        type int32 {
+          range "1..2147483647";
+        }
+        config false;
+      }
+
+      leaf link-up-down-trap-enable {
+        if-feature if-mib;
+        type enumeration {
+          enum enabled {
+            value 1;
+          }
+          enum disabled {
+            value 2;
+          }
+        }
+      }
+
+      leaf phys-address {
+        type string;
+        config false;
+      }
+
+      leaf-list higher-layer-if {
+        type interface-ref;
+        config false;
+      }
+
+      leaf-list lower-layer-if {
+        type interface-ref;
+        config false;
+      }
+
+      leaf speed {
+        type uint64;
+        units "bits / second";
+        config false;
+      }
+
+      container statistics {
+        config false;
+      }
+    }
+  }
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/identityref.yang b/code-generator/binding-generator-impl/src/test/resources/identityref.yang
new file mode 100644 (file)
index 0000000..1255185
--- /dev/null
@@ -0,0 +1,20 @@
+module module-identityref {
+
+    namespace "urn:identityref:module";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-11-09 {
+    }
+
+    identity some-identity {
+    }
+
+    leaf lf {
+        type identityref {
+            base "some-identity";
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/ietf/iana-if-type.yang b/code-generator/binding-generator-impl/src/test/resources/ietf/iana-if-type.yang
new file mode 100644 (file)
index 0000000..a7fa137
--- /dev/null
@@ -0,0 +1,1516 @@
+module iana-if-type {
+  namespace "urn:ietf:params:xml:ns:yang:iana-if-type";
+  prefix ianaift;
+
+  organization "IANA";
+  contact
+    "        Internet Assigned Numbers Authority
+
+     Postal: ICANN
+             4676 Admiralty Way, Suite 330
+             Marina del Rey, CA 90292
+
+     Tel:    +1 310 823 9358
+     E-Mail: iana&iana.org";
+  description
+    "This YANG module defines the iana-if-type typedef, which
+     contains YANG definitions for IANA-registered interface types.
+
+     This YANG module is maintained by IANA, and reflects the
+     'ifType definitions' registry.
+
+     The latest revision of this YANG module can be obtained from
+     the IANA web site.
+
+     Copyright (c) 2011 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see
+     the RFC itself for full legal notices.";
+  // RFC Ed.: replace XXXX with actual RFC number and remove this
+  // note.
+
+  // RFC Ed.: update the date below with the date of RFC publication
+  // and remove this note.
+  revision 2012-06-05 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: TITLE";
+  }
+
+  typedef iana-if-type {
+    type enumeration {
+      enum "other" {
+        value 1;
+        description
+          "None of the following";
+      }
+      enum "regular1822" {
+        value 2;
+      }
+      enum "hdh1822" {
+        value 3;
+      }
+      enum "ddnX25" {
+        value 4;
+      }
+      enum "rfc877x25" {
+        value 5;
+        reference
+          "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer";
+      }
+      enum "ethernetCsmacd" {
+        value 6;
+        description
+          "For all ethernet-like interfaces, regardless of speed,
+           as per RFC3635.";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "iso88023Csmacd" {
+        value 7;
+        status deprecated;
+        description
+          "Deprecated via RFC3635.
+           Use ethernetCsmacd(6) instead.";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "iso88024TokenBus" {
+        value 8;
+      }
+      enum "iso88025TokenRing" {
+        value 9;
+      }
+      enum "iso88026Man" {
+        value 10;
+      }
+      enum "starLan" {
+        value 11;
+        status deprecated;
+        description
+          "Deprecated via RFC3635.
+           Use ethernetCsmacd(6) instead.";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "proteon10Mbit" {
+        value 12;
+      }
+      enum "proteon80Mbit" {
+        value 13;
+      }
+      enum "hyperchannel" {
+        value 14;
+      }
+      enum "fddi" {
+        value 15;
+        reference
+          "RFC 1512 - FDDI Management Information Base";
+      }
+      enum "lapb" {
+        value 16;
+        reference
+          "RFC 1381 - SNMP MIB Extension for X.25 LAPB";
+      }
+      enum "sdlc" {
+        value 17;
+      }
+      enum "ds1" {
+        value 18;
+        description
+          "DS1-MIB";
+        reference
+          "RFC 4805 - Definitions of Managed Objects for the
+                      DS1, J1, E1, DS2, and E2 Interface Types";
+      }
+      enum "e1" {
+        value 19;
+        status obsolete;
+        description
+          "Obsolete see DS1-MIB";
+        reference
+          "RFC 4805 - Definitions of Managed Objects for the
+                      DS1, J1, E1, DS2, and E2 Interface Types";
+      }
+      enum "basicISDN" {
+        value 20;
+        description
+          "see also RFC2127";
+      }
+      enum "primaryISDN" {
+        value 21;
+      }
+      enum "propPointToPointSerial" {
+        value 22;
+        description
+          "proprietary serial";
+      }
+      enum "ppp" {
+        value 23;
+      }
+      enum "softwareLoopback" {
+        value 24;
+      }
+      enum "eon" {
+        value 25;
+        description
+          "CLNP over IP";
+      }
+      enum "ethernet3Mbit" {
+        value 26;
+      }
+      enum "nsip" {
+        value 27;
+        description
+          "XNS over IP";
+      }
+      enum "slip" {
+        value 28;
+        description
+          "generic SLIP";
+      }
+      enum "ultra" {
+        value 29;
+        description
+          "ULTRA technologies";
+      }
+      enum "ds3" {
+        value 30;
+        description
+          "DS3-MIB";
+        reference
+          "RFC 3896 - Definitions of Managed Objects for the
+                      DS3/E3 Interface Type";
+      }
+      enum "sip" {
+        value 31;
+        description
+          "SMDS, coffee";
+        reference
+          "RFC 1694 - Definitions of Managed Objects for SMDS
+                      Interfaces using SMIv2";
+      }
+      enum "frameRelay" {
+        value 32;
+        description
+          "DTE only.";
+        reference
+          "RFC 2115 - Management Information Base for Frame Relay
+                      DTEs Using SMIv2";
+      }
+      enum "rs232" {
+        value 33;
+        reference
+          "RFC 1659 - Definitions of Managed Objects for RS-232-like
+                      Hardware Devices using SMIv2";
+      }
+      enum "para" {
+        value 34;
+        description
+          "parallel-port";
+        reference
+          "RFC 1660 - Definitions of Managed Objects for
+                      Parallel-printer-like Hardware Devices using
+                      SMIv2";
+      }
+      enum "arcnet" {
+        value 35;
+        description
+          "arcnet";
+      }
+      enum "arcnetPlus" {
+        value 36;
+        description
+          "arcnet plus";
+      }
+      enum "atm" {
+        value 37;
+        description
+          "ATM cells";
+      }
+      enum "miox25" {
+        value 38;
+        reference
+          "RFC 1461 - SNMP MIB extension for Multiprotocol
+                      Interconnect over X.25";
+      }
+      enum "sonet" {
+        value 39;
+        description
+          "SONET or SDH";
+      }
+      enum "x25ple" {
+        value 40;
+        reference
+          "RFC 2127 - ISDN Management Information Base using SMIv2";
+      }
+      enum "iso88022llc" {
+        value 41;
+      }
+      enum "localTalk" {
+        value 42;
+      }
+      enum "smdsDxi" {
+        value 43;
+      }
+      enum "frameRelayService" {
+        value 44;
+        description
+          "FRNETSERV-MIB";
+        reference
+          "RFC 2954 - Definitions of Managed Objects for Frame
+                      Relay Service";
+      }
+      enum "v35" {
+        value 45;
+      }
+      enum "hssi" {
+        value 46;
+      }
+      enum "hippi" {
+        value 47;
+      }
+      enum "modem" {
+        value 48;
+        description
+          "Generic modem";
+      }
+      enum "aal5" {
+        value 49;
+        description
+          "AAL5 over ATM";
+      }
+      enum "sonetPath" {
+        value 50;
+      }
+      enum "sonetVT" {
+        value 51;
+      }
+      enum "smdsIcip" {
+        value 52;
+        description
+          "SMDS InterCarrier Interface";
+      }
+      enum "propVirtual" {
+        value 53;
+        description
+          "proprietary virtual/internal";
+        reference
+          "RFC 2863 - The Interfaces Group MIB";
+      }
+      enum "propMultiplexor" {
+        value 54;
+        description
+          "proprietary multiplexing";
+        reference
+          "RFC 2863 - The Interfaces Group MIB";
+      }
+      enum "ieee80212" {
+        value 55;
+        description
+          "100BaseVG";
+      }
+      enum "fibreChannel" {
+        value 56;
+        description
+          "Fibre Channel";
+      }
+      enum "hippiInterface" {
+        value 57;
+        description
+          "HIPPI interfaces";
+      }
+      enum "frameRelayInterconnect" {
+        value 58;
+        status obsolete;
+        description
+          "Obsolete use either
+           frameRelay(32) or frameRelayService(44).";
+      }
+      enum "aflane8023" {
+        value 59;
+        description
+          "ATM Emulated LAN for 802.3";
+      }
+      enum "aflane8025" {
+        value 60;
+        description
+          "ATM Emulated LAN for 802.5";
+      }
+      enum "cctEmul" {
+        value 61;
+        description
+         "ATM Emulated circuit";
+      }
+      enum "fastEther" {
+        value 62;
+        status deprecated;
+        description
+          "Obsoleted via RFC3635.
+          ethernetCsmacd(6) should be used instead";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "isdn" {
+        value 63;
+        description
+          "ISDN and X.25";
+        reference
+          "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN
+                      in the Packet Mode";
+      }
+      enum "v11" {
+        value 64;
+        description
+         "CCITT V.11/X.21";
+      }
+      enum "v36" {
+        value 65;
+        description
+          "CCITT V.36";
+      }
+      enum "g703at64k" {
+        value 66;
+        description
+          "CCITT G703 at 64Kbps";
+      }
+      enum "g703at2mb" {
+        value 67;
+        status obsolete;
+        description
+          "Obsolete see DS1-MIB";
+      }
+      enum "qllc" {
+        value 68;
+        description
+          "SNA QLLC";
+      }
+      enum "fastEtherFX" {
+        value 69;
+        status deprecated;
+        description
+          "Obsoleted via RFC3635
+          ethernetCsmacd(6) should be used instead";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "channel" {
+        value 70;
+        description
+          "channel";
+      }
+      enum "ieee80211" {
+        value 71;
+        description
+          "radio spread spectrum";
+      }
+      enum "ibm370parChan" {
+        value 72;
+        description
+          "IBM System 360/370 OEMI Channel";
+      }
+      enum "escon" {
+        value 73;
+        description
+          "IBM Enterprise Systems Connection";
+      }
+      enum "dlsw" {
+        value 74;
+        description
+          "Data Link Switching";
+      }
+      enum "isdns" {
+        value 75;
+        description
+          "ISDN S/T interface";
+      }
+      enum "isdnu" {
+        value 76;
+        description
+          "ISDN U interface";
+      }
+      enum "lapd" {
+        value 77;
+        description
+          "Link Access Protocol D";
+      }
+      enum "ipSwitch" {
+        value 78;
+        description
+          "IP Switching Objects";
+      }
+      enum "rsrb" {
+        value 79;
+        description
+          "Remote Source Route Bridging";
+      }
+      enum "atmLogical" {
+        value 80;
+        description
+          "ATM Logical Port";
+        reference
+          "RFC 3606 - Definitions of Supplemental Managed Objects
+                      for ATM Interface";
+      }
+      enum "ds0" {
+        value 81;
+        description
+          "Digital Signal Level 0";
+        reference
+          "RFC 2494 - Definitions of Managed Objects for the DS0
+                      and DS0 Bundle Interface Type";
+      }
+      enum "ds0Bundle" {
+        value 82;
+        description
+          "group of ds0s on the same ds1";
+        reference
+          "RFC 2494 - Definitions of Managed Objects for the DS0
+                      and DS0 Bundle Interface Type";
+      }
+      enum "bsc" {
+        value 83;
+        description
+          "Bisynchronous Protocol";
+      }
+      enum "async" {
+        value 84;
+        description
+          "Asynchronous Protocol";
+      }
+      enum "cnr" {
+        value 85;
+        description
+          "Combat Net Radio";
+      }
+      enum "iso88025Dtr" {
+        value 86;
+        description
+          "ISO 802.5r DTR";
+      }
+      enum "eplrs" {
+        value 87;
+        description
+          "Ext Pos Loc Report Sys";
+      }
+      enum "arap" {
+        value 88;
+        description
+          "Appletalk Remote Access Protocol";
+      }
+      enum "propCnls" {
+        value 89;
+        description
+          "Proprietary Connectionless Protocol";
+      }
+      enum "hostPad" {
+        value 90;
+        description
+          "CCITT-ITU X.29 PAD Protocol";
+      }
+      enum "termPad" {
+        value 91;
+        description
+          "CCITT-ITU X.3 PAD Facility";
+      }
+      enum "frameRelayMPI" {
+        value 92;
+        description
+          "Multiproto Interconnect over FR";
+      }
+      enum "x213" {
+        value 93;
+        description
+          "CCITT-ITU X213";
+      }
+      enum "adsl" {
+        value 94;
+        description
+          "Asymmetric Digital Subscriber Loop";
+      }
+      enum "radsl" {
+        value 95;
+        description
+          "Rate-Adapt. Digital Subscriber Loop";
+      }
+      enum "sdsl" {
+        value 96;
+        description
+          "Symmetric Digital Subscriber Loop";
+      }
+      enum "vdsl" {
+        value 97;
+        description
+          "Very H-Speed Digital Subscrib. Loop";
+      }
+      enum "iso88025CRFPInt" {
+        value 98;
+        description
+          "ISO 802.5 CRFP";
+      }
+      enum "myrinet" {
+        value 99;
+        description
+          "Myricom Myrinet";
+      }
+      enum "voiceEM" {
+        value 100;
+        description
+          "voice recEive and transMit";
+      }
+      enum "voiceFXO" {
+        value 101;
+        description
+          "voice Foreign Exchange Office";
+      }
+      enum "voiceFXS" {
+        value 102;
+        description
+          "voice Foreign Exchange Station";
+      }
+      enum "voiceEncap" {
+        value 103;
+        description
+          "voice encapsulation";
+      }
+      enum "voiceOverIp" {
+        value 104;
+        description
+          "voice over IP encapsulation";
+      }
+      enum "atmDxi" {
+        value 105;
+        description
+          "ATM DXI";
+      }
+      enum "atmFuni" {
+        value 106;
+        description
+          "ATM FUNI";
+      }
+      enum "atmIma" {
+        value 107;
+        description
+          "ATM IMA";
+      }
+      enum "pppMultilinkBundle" {
+        value 108;
+        description
+          "PPP Multilink Bundle";
+      }
+      enum "ipOverCdlc" {
+        value 109;
+        description
+          "IBM ipOverCdlc";
+      }
+      enum "ipOverClaw" {
+        value 110;
+        description
+          "IBM Common Link Access to Workstn";
+      }
+      enum "stackToStack" {
+        value 111;
+        description
+          "IBM stackToStack";
+      }
+      enum "virtualIpAddress" {
+        value 112;
+        description
+          "IBM VIPA";
+      }
+      enum "mpc" {
+        value 113;
+        description
+          "IBM multi-protocol channel support";
+      }
+      enum "ipOverAtm" {
+        value 114;
+        description
+          "IBM ipOverAtm";
+        reference
+          "RFC 2320 - Definitions of Managed Objects for Classical IP
+                      and ARP Over ATM Using SMIv2 (IPOA-MIB)";
+      }
+      enum "iso88025Fiber" {
+        value 115;
+        description
+          "ISO 802.5j Fiber Token Ring";
+      }
+      enum "tdlc" {
+        value 116;
+        description
+          "IBM twinaxial data link control";
+      }
+      enum "gigabitEthernet" {
+        value 117;
+        status deprecated;
+        description
+          "Obsoleted via RFC3635
+           ethernetCsmacd(6) should be used instead";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "hdlc" {
+        value 118;
+        description
+          "HDLC";
+      }
+      enum "lapf" {
+        value 119;
+        description
+          "LAP F";
+      }
+      enum "v37" {
+        value 120;
+        description
+          "V.37";
+      }
+      enum "x25mlp" {
+        value 121;
+        description
+          "Multi-Link Protocol";
+      }
+      enum "x25huntGroup" {
+        value 122;
+        description
+          "X25 Hunt Group";
+      }
+      enum "transpHdlc" {
+        value 123;
+        description
+          "Transp HDLC";
+      }
+      enum "interleave" {
+        value 124;
+        description
+          "Interleave channel";
+      }
+      enum "fast" {
+        value 125;
+        description
+          "Fast channel";
+      }
+      enum "ip" {
+        value 126;
+        description
+          "IP (for APPN HPR in IP networks)";
+      }
+      enum "docsCableMaclayer" {
+        value 127;
+        description
+          "CATV Mac Layer";
+      }
+      enum "docsCableDownstream" {
+        value 128;
+        description
+          "CATV Downstream interface";
+      }
+      enum "docsCableUpstream" {
+        value 129;
+        description
+          "CATV Upstream interface";
+      }
+      enum "a12MppSwitch" {
+        value 130;
+        description
+          "Avalon Parallel Processor";
+      }
+      enum "tunnel" {
+        value 131;
+        description
+          "Encapsulation interface";
+      }
+      enum "coffee" {
+        value 132;
+        description
+          "coffee pot";
+        reference
+          "RFC 2325 - Coffee MIB";
+      }
+      enum "ces" {
+        value 133;
+        description
+          "Circuit Emulation Service";
+      }
+      enum "atmSubInterface" {
+        value 134;
+        description
+          "ATM Sub Interface";
+      }
+      enum "l2vlan" {
+        value 135;
+        description
+          "Layer 2 Virtual LAN using 802.1Q";
+      }
+      enum "l3ipvlan" {
+        value 136;
+        description
+          "Layer 3 Virtual LAN using IP";
+      }
+      enum "l3ipxvlan" {
+        value 137;
+        description
+          "Layer 3 Virtual LAN using IPX";
+      }
+      enum "digitalPowerline" {
+        value 138;
+        description
+          "IP over Power Lines";
+      }
+      enum "mediaMailOverIp" {
+        value 139;
+        description
+          "Multimedia Mail over IP";
+      }
+      enum "dtm" {
+        value 140;
+        description
+          "Dynamic syncronous Transfer Mode";
+      }
+      enum "dcn" {
+        value 141;
+        description
+          "Data Communications Network";
+      }
+      enum "ipForward" {
+        value 142;
+        description
+          "IP Forwarding Interface";
+      }
+      enum "msdsl" {
+        value 143;
+        description
+          "Multi-rate Symmetric DSL";
+      }
+      enum "ieee1394" {
+        value 144;
+        description
+          "IEEE1394 High Performance Serial Bus";
+      }
+      enum "if-gsn" {
+        value 145;
+        description
+          "HIPPI-6400";
+      }
+      enum "dvbRccMacLayer" {
+        value 146;
+        description
+          "DVB-RCC MAC Layer";
+      }
+      enum "dvbRccDownstream" {
+        value 147;
+        description
+          "DVB-RCC Downstream Channel";
+      }
+      enum "dvbRccUpstream" {
+        value 148;
+        description
+          "DVB-RCC Upstream Channel";
+      }
+      enum "atmVirtual" {
+        value 149;
+        description
+          "ATM Virtual Interface";
+      }
+      enum "mplsTunnel" {
+        value 150;
+        description
+          "MPLS Tunnel Virtual Interface";
+      }
+      enum "srp" {
+        value 151;
+        description
+          "Spatial Reuse Protocol       ";
+      }
+      enum "voiceOverAtm" {
+        value 152;
+        description
+          "Voice Over ATM";
+      }
+      enum "voiceOverFrameRelay" {
+        value 153;
+        description
+          "Voice Over Frame Relay";
+      }
+      enum "idsl" {
+        value 154;
+        description
+          "Digital Subscriber Loop over ISDN";
+      }
+      enum "compositeLink" {
+        value 155;
+        description
+          "Avici Composite Link Interface";
+      }
+      enum "ss7SigLink" {
+        value 156;
+        description
+          "SS7 Signaling Link";
+      }
+      enum "propWirelessP2P" {
+        value 157;
+        description
+          "Prop. P2P wireless interface";
+      }
+      enum "frForward" {
+        value 158;
+        description
+          "Frame Forward Interface";
+      }
+      enum "rfc1483" {
+        value 159;
+        description
+          "Multiprotocol over ATM AAL5";
+        reference
+          "RFC 1483 - Multiprotocol Encapsulation over ATM
+                      Adaptation Layer 5";
+      }
+      enum "usb" {
+        value 160;
+        description
+          "USB Interface";
+      }
+      enum "ieee8023adLag" {
+        value 161;
+        description
+          "IEEE 802.3ad Link Aggregate";
+      }
+      enum "bgppolicyaccounting" {
+        value 162;
+        description
+          "BGP Policy Accounting";
+      }
+      enum "frf16MfrBundle" {
+        value 163;
+        description
+          "FRF .16 Multilink Frame Relay";
+      }
+      enum "h323Gatekeeper" {
+        value 164;
+        description
+          "H323 Gatekeeper";
+      }
+      enum "h323Proxy" {
+        value 165;
+        description
+          "H323 Voice and Video Proxy";
+      }
+      enum "mpls" {
+        value 166;
+        description
+          "MPLS";
+      }
+      enum "mfSigLink" {
+        value 167;
+        description
+          "Multi-frequency signaling link";
+      }
+      enum "hdsl2" {
+        value 168;
+        description
+          "High Bit-Rate DSL - 2nd generation";
+      }
+      enum "shdsl" {
+        value 169;
+        description
+          "Multirate HDSL2";
+      }
+      enum "ds1FDL" {
+        value 170;
+        description
+          "Facility Data Link 4Kbps on a DS1";
+      }
+      enum "pos" {
+        value 171;
+        description
+          "Packet over SONET/SDH Interface";
+      }
+      enum "dvbAsiIn" {
+        value 172;
+        description
+          "DVB-ASI Input";
+      }
+      enum "dvbAsiOut" {
+        value 173;
+        description
+          "DVB-ASI Output";
+      }
+      enum "plc" {
+        value 174;
+        description
+          "Power Line Communtications";
+      }
+      enum "nfas" {
+        value 175;
+        description
+          "Non Facility Associated Signaling";
+      }
+      enum "tr008" {
+        value 176;
+        description
+          "TR008";
+      }
+      enum "gr303RDT" {
+        value 177;
+        description
+          "Remote Digital Terminal";
+      }
+      enum "gr303IDT" {
+        value 178;
+        description
+          "Integrated Digital Terminal";
+      }
+      enum "isup" {
+        value 179;
+        description
+          "ISUP";
+      }
+      enum "propDocsWirelessMaclayer" {
+        value 180;
+        description
+          "Cisco proprietary Maclayer";
+      }
+      enum "propDocsWirelessDownstream" {
+        value 181;
+        description
+          "Cisco proprietary Downstream";
+      }
+      enum "propDocsWirelessUpstream" {
+        value 182;
+        description
+          "Cisco proprietary Upstream";
+      }
+      enum "hiperlan2" {
+        value 183;
+        description
+          "HIPERLAN Type 2 Radio Interface";
+      }
+      enum "propBWAp2Mp" {
+        value 184;
+        description
+          "PropBroadbandWirelessAccesspt2multipt use of this value
+           for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f
+           is deprecated and ieee80216WMAN(237) should be used
+           instead.";
+      }
+      enum "sonetOverheadChannel" {
+        value 185;
+        description
+          "SONET Overhead Channel";
+      }
+      enum "digitalWrapperOverheadChannel" {
+        value 186;
+        description
+          "Digital Wrapper";
+      }
+      enum "aal2" {
+        value 187;
+        description
+          "ATM adaptation layer 2";
+      }
+      enum "radioMAC" {
+        value 188;
+        description
+          "MAC layer over radio links";
+      }
+      enum "atmRadio" {
+        value 189;
+        description
+          "ATM over radio links";
+      }
+      enum "imt" {
+        value 190;
+        description
+          "Inter Machine Trunks";
+      }
+      enum "mvl" {
+        value 191;
+        description
+          "Multiple Virtual Lines DSL";
+      }
+      enum "reachDSL" {
+        value 192;
+        description
+          "Long Reach DSL";
+      }
+      enum "frDlciEndPt" {
+        value 193;
+        description
+          "Frame Relay DLCI End Point";
+      }
+      enum "atmVciEndPt" {
+        value 194;
+        description
+          "ATM VCI End Point";
+      }
+      enum "opticalChannel" {
+        value 195;
+        description
+          "Optical Channel";
+      }
+      enum "opticalTransport" {
+        value 196;
+        description
+          "Optical Transport";
+      }
+      enum "propAtm" {
+        value 197;
+        description
+          "Proprietary ATM";
+      }
+      enum "voiceOverCable" {
+        value 198;
+        description
+          "Voice Over Cable Interface";
+      }
+      enum "infiniband" {
+        value 199;
+        description
+          "Infiniband";
+      }
+      enum "teLink" {
+        value 200;
+        description
+          "TE Link";
+      }
+      enum "q2931" {
+        value 201;
+        description
+          "Q.2931";
+      }
+      enum "virtualTg" {
+        value 202;
+        description
+          "Virtual Trunk Group";
+      }
+      enum "sipTg" {
+        value 203;
+        description
+          "SIP Trunk Group";
+      }
+      enum "sipSig" {
+        value 204;
+        description
+          "SIP Signaling";
+      }
+      enum "docsCableUpstreamChannel" {
+        value 205;
+        description
+          "CATV Upstream Channel";
+      }
+      enum "econet" {
+        value 206;
+        description
+          "Acorn Econet";
+      }
+      enum "pon155" {
+        value 207;
+        description
+          "FSAN 155Mb Symetrical PON interface";
+      }
+      enum "pon622" {
+        value 208;
+        description
+          "FSAN622Mb Symetrical PON interface";
+      }
+      enum "bridge" {
+        value 209;
+        description
+          "Transparent bridge interface";
+      }
+      enum "linegroup" {
+        value 210;
+        description
+          "Interface common to multiple lines";
+      }
+      enum "voiceEMFGD" {
+        value 211;
+        description
+          "voice E&M Feature Group D";
+      }
+      enum "voiceFGDEANA" {
+        value 212;
+        description
+          "voice FGD Exchange Access North American";
+      }
+      enum "voiceDID" {
+        value 213;
+        description
+          "voice Direct Inward Dialing";
+      }
+      enum "mpegTransport" {
+        value 214;
+        description
+          "MPEG transport interface";
+      }
+      enum "sixToFour" {
+        value 215;
+        status deprecated;
+        description
+          "6to4 interface (DEPRECATED)";
+        reference
+          "RFC 4087 - IP Tunnel MIB";
+      }
+      enum "gtp" {
+        value 216;
+        description
+          "GTP (GPRS Tunneling Protocol)";
+      }
+      enum "pdnEtherLoop1" {
+        value 217;
+        description
+          "Paradyne EtherLoop 1";
+      }
+      enum "pdnEtherLoop2" {
+        value 218;
+        description
+          "Paradyne EtherLoop 2";
+      }
+      enum "opticalChannelGroup" {
+        value 219;
+        description
+          "Optical Channel Group";
+      }
+      enum "homepna" {
+        value 220;
+        description
+          "HomePNA ITU-T G.989";
+      }
+      enum "gfp" {
+        value 221;
+        description
+          "Generic Framing Procedure (GFP)";
+      }
+      enum "ciscoISLvlan" {
+        value 222;
+        description
+          "Layer 2 Virtual LAN using Cisco ISL";
+      }
+      enum "actelisMetaLOOP" {
+        value 223;
+        description
+          "Acteleis proprietary MetaLOOP High Speed Link";
+      }
+      enum "fcipLink" {
+        value 224;
+        description
+          "FCIP Link";
+      }
+      enum "rpr" {
+        value 225;
+        description
+          "Resilient Packet Ring Interface Type";
+      }
+      enum "qam" {
+        value 226;
+        description
+          "RF Qam Interface";
+      }
+      enum "lmp" {
+        value 227;
+        description
+          "Link Management Protocol";
+        reference
+          "RFC 4327 - Link Management Protocol (LMP) Management
+                      Information Base (MIB)";
+      }
+      enum "cblVectaStar" {
+        value 228;
+        description
+          "Cambridge Broadband Networks Limited VectaStar";
+      }
+      enum "docsCableMCmtsDownstream" {
+        value 229;
+        description
+          "CATV Modular CMTS Downstream Interface";
+      }
+      enum "adsl2" {
+        value 230;
+        status deprecated;
+        description
+          "Asymmetric Digital Subscriber Loop Version 2
+           (DEPRECATED/OBSOLETED - please use adsl2plus(238)
+           instead)";
+        reference
+          "RFC 4706 - Definitions of Managed Objects for Asymmetric
+                      Digital Subscriber Line 2 (ADSL2)";
+      }
+      enum "macSecControlledIF" {
+        value 231;
+        description
+          "MACSecControlled";
+      }
+      enum "macSecUncontrolledIF" {
+        value 232;
+        description
+          "MACSecUncontrolled";
+      }
+      enum "aviciOpticalEther" {
+        value 233;
+        description
+         "Avici Optical Ethernet Aggregate";
+      }
+      enum "atmbond" {
+        value 234;
+        description
+          "atmbond";
+      }
+      enum "voiceFGDOS" {
+        value 235;
+        description
+          "voice FGD Operator Services";
+      }
+      enum "mocaVersion1" {
+        value 236;
+        description
+          "MultiMedia over Coax Alliance (MoCA) Interface
+           as documented in information provided privately to IANA";
+      }
+      enum "ieee80216WMAN" {
+        value 237;
+        description
+          "IEEE 802.16 WMAN interface";
+      }
+      enum "adsl2plus" {
+        value 238;
+        description
+          "Asymmetric Digital Subscriber Loop Version 2,
+           Version 2 Plus and all variants";
+      }
+      enum "dvbRcsMacLayer" {
+        value 239;
+        description
+          "DVB-RCS MAC Layer";
+        reference
+          "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+      }
+      enum "dvbTdm" {
+        value 240;
+        description
+          "DVB Satellite TDM";
+        reference
+          "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+      }
+      enum "dvbRcsTdma" {
+        value 241;
+        description
+          "DVB-RCS TDMA";
+        reference
+          "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+      }
+      enum "x86Laps" {
+        value 242;
+        description
+          "LAPS based on ITU-T X.86/Y.1323";
+      }
+      enum "wwanPP" {
+        value 243;
+        description
+          "3GPP WWAN";
+      }
+      enum "wwanPP2" {
+        value 244;
+        description
+          "3GPP2 WWAN";
+      }
+      enum "voiceEBS" {
+        value 245;
+        description
+          "voice P-phone EBS physical interface";
+      }
+      enum "ifPwType" {
+        value 246;
+        description
+          "Pseudowire interface type";
+        reference
+          "RFC 5601 - Pseudowire (PW) Management Information Base";
+      }
+      enum "ilan" {
+        value 247;
+        description
+          "Internal LAN on a bridge per IEEE 802.1ap";
+      }
+      enum "pip" {
+        value 248;
+        description
+          "Provider Instance Port on a bridge per IEEE 802.1ah PBB";
+      }
+      enum "aluELP" {
+        value 249;
+        description
+          "Alcatel-Lucent Ethernet Link Protection";
+      }
+      enum "gpon" {
+        value 250;
+        description
+          "Gigabit-capable passive optical networks (G-PON) as per
+           ITU-T G.948";
+      }
+      enum "vdsl2" {
+        value 251;
+        description
+          "Very high speed digital subscriber line Version 2
+           (as per ITU-T Recommendation G.993.2)";
+        reference
+          "RFC 5650 - Definitions of Managed Objects for Very High
+                      Speed Digital Subscriber Line 2 (VDSL2)";
+      }
+      enum "capwapDot11Profile" {
+        value 252;
+        description
+          "WLAN Profile Interface";
+        reference
+          "RFC 5834 - Control and Provisioning of Wireless Access
+                      Points (CAPWAP) Protocol Binding MIB for
+                      IEEE 802.11";
+      }
+      enum "capwapDot11Bss" {
+        value 253;
+        description
+          "WLAN BSS Interface";
+        reference
+          "RFC 5834 - Control and Provisioning of Wireless Access
+                      Points (CAPWAP) Protocol Binding MIB for
+                      IEEE 802.11";
+      }
+      enum "capwapWtpVirtualRadio" {
+        value 254;
+        description
+          "WTP Virtual Radio Interface";
+        reference
+          "RFC 5833 - Control and Provisioning of Wireless Access
+                      Points (CAPWAP) Protocol Base MIB";
+      }
+      enum "bits" {
+        value 255;
+        description
+          "bitsport";
+      }
+      enum "docsCableUpstreamRfPort" {
+        value 256;
+        description
+          "DOCSIS CATV Upstream RF Port";
+      }
+      enum "cableDownstreamRfPort" {
+        value 257;
+        description
+          "CATV downstream RF port";
+      }
+      enum "vmwareVirtualNic" {
+        value 258;
+        description
+          "VMware Virtual Network Interface";
+      }
+      enum "ieee802154" {
+        value 259;
+        description
+          "IEEE 802.15.4 WPAN interface";
+        reference
+          "IEEE 802.15.4-2006";
+      }
+      enum "otnOdu" {
+        value 260;
+        description
+          "OTN Optical Data Unit";
+      }
+      enum "otnOtu" {
+        value 261;
+        description
+          "OTN Optical channel Transport Unit";
+      }
+      enum "ifVfiType" {
+        value 262;
+        description
+          "VPLS Forwarding Instance Interface Type";
+      }
+      enum "g9981" {
+        value 263;
+        description
+          "G.998.1 bonded interface";
+      }
+      enum "g9982" {
+        value 264;
+        description
+          "G.998.2 bonded interface";
+      }
+      enum "g9983" {
+        value 265;
+        description
+          "G.998.3 bonded interface";
+      }
+      enum "aluEpon" {
+        value 266;
+        description
+          "Ethernet Passive Optical Networks (E-PON)";
+      }
+      enum "aluEponOnu" {
+        value 267;
+        description
+          "EPON Optical Network Unit";
+      }
+      enum "aluEponPhysicalUni" {
+        value 268;
+        description
+          "EPON physical User to Network interface";
+      }
+      enum "aluEponLogicalLink" {
+        value 269;
+        description
+          "The emulation of a point-to-point link over the EPON
+           layer";
+      }
+      enum "aluGponOnu" {
+        value 270;
+        description
+          "GPON Optical Network Unit";
+        reference
+          "ITU-T G.984.2";
+      }
+      enum "aluGponPhysicalUni" {
+        value 271;
+        description
+          "GPON physical User to Network interface";
+        reference
+          "ITU-T G.984.2";
+      }
+      enum "vmwareNicTeam" {
+        value 272;
+        description
+          "VMware NIC Team";
+      }
+    }
+    description
+      "This data type is used as the syntax of the 'type'
+       leaf in the 'interface' list in the YANG module
+       ietf-interface.
+
+       The definition of this typedef with the
+       addition of newly assigned values is published
+       periodically by the IANA, in either the Assigned
+       Numbers RFC, or some derivative of it specific to
+       Internet Network Management number assignments.  (The
+       latest arrangements can be obtained by contacting the
+       IANA.)
+
+       Requests for new values should be made to IANA via
+       email (iana&iana.org).";
+    reference
+      "ifType definitions registry.
+       <http://www.iana.org/assignments/smi-numbers>";
+  }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/ietf/ietf-inet-types.yang b/code-generator/binding-generator-impl/src/test/resources/ietf/ietf-inet-types.yang
new file mode 100644 (file)
index 0000000..de20feb
--- /dev/null
@@ -0,0 +1,418 @@
+ module ietf-inet-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+   prefix "inet";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types for Internet addresses and related things.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of protocol field related types ***/
+
+   typedef ip-version {
+     type enumeration {
+       enum unknown {
+         value "0";
+         description
+          "An unknown or unspecified version of the Internet protocol.";
+       }
+       enum ipv4 {
+         value "1";
+         description
+          "The IPv4 protocol as defined in RFC 791.";
+       }
+       enum ipv6 {
+         value "2";
+         description
+          "The IPv6 protocol as defined in RFC 2460.";
+       }
+     }
+     description
+      "This value represents the version of the IP protocol.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetVersion textual convention of the SMIv2.";
+     reference
+      "RFC  791: Internet Protocol
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   typedef dscp {
+     type uint8 {
+       range "0..63";
+     }
+     description
+      "The dscp type represents a Differentiated Services Code-Point
+       that may be used for marking packets in a traffic stream.
+
+       In the value set and its semantics, this type is equivalent
+       to the Dscp textual convention of the SMIv2.";
+     reference
+      "RFC 3289: Management Information Base for the Differentiated
+                 Services Architecture
+       RFC 2474: Definition of the Differentiated Services Field
+                 (DS Field) in the IPv4 and IPv6 Headers
+       RFC 2780: IANA Allocation Guidelines For Values In
+                 the Internet Protocol and Related Headers";
+   }
+
+   typedef ipv6-flow-label {
+     type uint32 {
+       range "0..1048575";
+     }
+     description
+      "The flow-label type represents flow identifier or Flow Label
+       in an IPv6 packet header that may be used to discriminate
+       traffic flows.
+
+       In the value set and its semantics, this type is equivalent
+       to the IPv6FlowLabel textual convention of the SMIv2.";
+     reference
+      "RFC 3595: Textual Conventions for IPv6 Flow Label
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+   }
+
+   typedef port-number {
+     type uint16 {
+       range "0..65535";
+     }
+     description
+      "The port-number type represents a 16-bit port number of an
+       Internet transport layer protocol such as UDP, TCP, DCCP, or
+       SCTP.  Port numbers are assigned by IANA.  A current list of
+       all assignments is available from <http://www.iana.org/>.
+
+       Note that the port number value zero is reserved by IANA.  In
+       situations where the value zero does not make sense, it can
+       be excluded by subtyping the port-number type.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetPortNumber textual convention of the SMIv2.";
+     reference
+      "RFC  768: User Datagram Protocol
+       RFC  793: Transmission Control Protocol
+       RFC 4960: Stream Control Transmission Protocol
+       RFC 4340: Datagram Congestion Control Protocol (DCCP)
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of autonomous system related types ***/
+
+   typedef as-number {
+     type uint32;
+     description
+      "The as-number type represents autonomous system numbers
+       which identify an Autonomous System (AS).  An AS is a set
+       of routers under a single technical administration, using
+       an interior gateway protocol and common metrics to route
+       packets within the AS, and using an exterior gateway
+       protocol to route packets to other ASs'.  IANA maintains
+       the AS number space and has delegated large parts to the
+       regional registries.
+
+       Autonomous system numbers were originally limited to 16
+       bits.  BGP extensions have enlarged the autonomous system
+       number space to 32 bits.  This type therefore uses an uint32
+       base type without a range restriction in order to support
+       a larger autonomous system number space.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetAutonomousSystemNumber textual convention of
+       the SMIv2.";
+     reference
+      "RFC 1930: Guidelines for creation, selection, and registration
+                 of an Autonomous System (AS)
+       RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+       RFC 4893: BGP Support for Four-octet AS Number Space
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of IP address and hostname related types ***/
+
+   typedef ip-address {
+     type union {
+       type inet:ipv4-address;
+       type inet:ipv6-address;
+     }
+     description
+      "The ip-address type represents an IP address and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-address {
+     type string {
+       pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '(%[\p{N}\p{L}]+)?';
+     }
+     description
+       "The ipv4-address type represents an IPv4 address in
+        dotted-quad notation.  The IPv4 address may include a zone
+        index, separated by a % sign.
+
+        The zone index is used to disambiguate identical address
+        values.  For link-local addresses, the zone index will
+        typically be the interface index number or the name of an
+        interface.  If the zone index is not present, the default
+        zone of the device will be used.
+
+        The canonical format for the zone index is the numerical
+        format";
+   }
+
+   typedef ipv6-address {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(%[\p{N}\p{L}]+)?';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(%.+)?';
+     }
+     description
+      "The ipv6-address type represents an IPv6 address in full,
+       mixed, shortened, and shortened-mixed notation.  The IPv6
+       address may include a zone index, separated by a % sign.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format of IPv6 addresses uses the compressed
+       format described in RFC 4291, Section 2.2, item 2 with the
+       following additional rules: the :: substitution must be
+       applied to the longest sequence of all-zero 16-bit chunks
+       in an IPv6 address.  If there is a tie, the first sequence
+       of all-zero 16-bit chunks is replaced by ::.  Single
+       all-zero 16-bit chunks are not compressed.  The canonical
+       format uses lowercase characters and leading zeros are
+       not allowed.  The canonical format for the zone index is
+       the numerical format as described in RFC 4007, Section
+       11.2.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture
+       RFC 4007: IPv6 Scoped Address Architecture
+       RFC 5952: A Recommendation for IPv6 Address Text Representation";
+   }
+
+   typedef ip-prefix {
+     type union {
+       type inet:ipv4-prefix;
+       type inet:ipv6-prefix;
+     }
+     description
+      "The ip-prefix type represents an IP prefix and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-prefix {
+     type string {
+       pattern
+          '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+        +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+        + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+     }
+     description
+      "The ipv4-prefix type represents an IPv4 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal to 32.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The canonical format of an IPv4 prefix has all bits of
+       the IPv4 address set to zero that are not part of the
+       IPv4 prefix.";
+   }
+
+   typedef ipv6-prefix {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(/.+)';
+     }
+     description
+      "The ipv6-prefix type represents an IPv6 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal 128.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The IPv6 address should have all bits that do not belong
+       to the prefix set to zero.
+
+       The canonical format of an IPv6 prefix has all bits of
+       the IPv6 address set to zero that are not part of the
+       IPv6 prefix.  Furthermore, IPv6 address is represented
+       in the compressed format described in RFC 4291, Section
+       2.2, item 2 with the following additional rules: the ::
+       substitution must be applied to the longest sequence of
+       all-zero 16-bit chunks in an IPv6 address.  If there is
+       a tie, the first sequence of all-zero 16-bit chunks is
+       replaced by ::.  Single all-zero 16-bit chunks are not
+       compressed.  The canonical format uses lowercase
+       characters and leading zeros are not allowed.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture";
+   }
+
+   /*** collection of domain name and URI types ***/
+
+   typedef domain-name {
+     type string {
+       pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+            +  '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+            +  '|\.';
+       length "1..253";
+     }
+     description
+      "The domain-name type represents a DNS domain name.  The
+       name SHOULD be fully qualified whenever possible.
+
+       Internet domain names are only loosely specified.  Section
+       3.5 of RFC 1034 recommends a syntax (modified in Section
+       2.1 of RFC 1123).  The pattern above is intended to allow
+       for current practice in domain name use, and some possible
+       future expansion.  It is designed to hold various types of
+       domain names, including names used for A or AAAA records
+       (host names) and other records, such as SRV records.  Note
+       that Internet host names have a stricter syntax (described
+       in RFC 952) than the DNS recommendations in RFCs 1034 and
+       1123, and that systems that want to store host names in
+       schema nodes using the domain-name type are recommended to
+       adhere to this stricter standard to ensure interoperability.
+
+       The encoding of DNS names in the DNS protocol is limited
+       to 255 characters.  Since the encoding consists of labels
+       prefixed by a length bytes and there is a trailing NULL
+       byte, only 253 characters can appear in the textual dotted
+       notation.
+
+       The description clause of schema nodes using the domain-name
+       type MUST describe when and how these names are resolved to
+       IP addresses.  Note that the resolution of a domain-name value
+       may require to query multiple DNS records (e.g., A for IPv4
+       and AAAA for IPv6).  The order of the resolution process and
+       which DNS record takes precedence can either be defined
+       explicitely or it may depend on the configuration of the
+       resolver.
+
+       Domain-name values use the US-ASCII encoding.  Their canonical
+       format uses lowercase US-ASCII characters.  Internationalized
+       domain names MUST be encoded in punycode as described in RFC
+       3492";
+     reference
+      "RFC  952: DoD Internet Host Table Specification
+       RFC 1034: Domain Names - Concepts and Facilities
+       RFC 1123: Requirements for Internet Hosts -- Application
+                 and Support
+       RFC 2782: A DNS RR for specifying the location of services
+                 (DNS SRV)
+       RFC 3492: Punycode: A Bootstring encoding of Unicode for
+                 Internationalized Domain Names in Applications
+                 (IDNA)
+       RFC 5891: Internationalizing Domain Names in Applications
+                 (IDNA): Protocol";
+   }
+
+   typedef host {
+     type union {
+       type inet:ip-address;
+       type inet:domain-name;
+     }
+     description
+      "The host type represents either an IP address or a DNS
+       domain name.";
+   }
+
+   typedef uri {
+     type string;
+     description
+      "The uri type represents a Uniform Resource Identifier
+       (URI) as defined by STD 66.
+
+       Objects using the uri type MUST be in US-ASCII encoding,
+       and MUST be normalized as described by RFC 3986 Sections
+       6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+       percent-encoding is removed, and all case-insensitive
+       characters are set to lowercase except for hexadecimal
+       digits, which are normalized to uppercase as described in
+       Section 6.2.2.1.
+
+       The purpose of this normalization is to help provide
+       unique URIs.  Note that this normalization is not
+       sufficient to provide uniqueness.  Two URIs that are
+       textually distinct after this normalization may still be
+       equivalent.
+
+       Objects using the uri type may restrict the schemes that
+       they permit.  For example, 'data:' and 'urn:' schemes
+       might not be appropriate.
+
+       A zero-length URI is not a valid URI.  This can be used to
+       express 'URI absent' where required.
+
+       In the value set and its semantics, this type is equivalent
+       to the Uri SMIv2 textual convention defined in RFC 5017.";
+     reference
+      "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+       RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                 Group: Uniform Resource Identifiers (URIs), URLs,
+                 and Uniform Resource Names (URNs): Clarifications
+                 and Recommendations
+       RFC 5017: MIB Textual Conventions for Uniform Resource
+                 Identifiers (URIs)";
+   }
+
+ }
diff --git a/code-generator/binding-generator-impl/src/test/resources/ietf/ietf-interfaces.yang b/code-generator/binding-generator-impl/src/test/resources/ietf/ietf-interfaces.yang
new file mode 100644 (file)
index 0000000..481a5d2
--- /dev/null
@@ -0,0 +1,469 @@
+module ietf-interfaces {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+  prefix if;
+
+  import ietf-yang-types {
+    prefix yang;
+    revision-date 2010-09-24;
+  }
+
+  organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+  contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     WG Chair: Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>
+
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+
+  description
+    "This module contains a collection of YANG definitions for
+     managing network interfaces.
+
+     Copyright (c) 2012 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see
+     the RFC itself for full legal notices.";
+
+  // RFC Ed.: replace XXXX with actual RFC number and remove this
+  // note.
+
+  // RFC Ed.: update the date below with the date of RFC publication
+  // and remove this note.
+  revision 2012-11-15 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: A YANG Data Model for Interface Management";
+  }
+
+  /* Typedefs */
+
+  typedef interface-ref {
+    type leafref {
+      path "/if:interfaces/if:interface/if:name";
+    }
+    description
+      "This type is used by data models that need to reference
+       interfaces.";
+  }
+
+  /* Features */
+
+  feature arbitrary-names {
+    description
+      "This feature indicates that the server allows interfaces to
+       be named arbitrarily.";
+  }
+
+  feature if-mib {
+    description
+      "This feature indicates that the server implements IF-MIB.";
+    reference
+      "RFC 2863: The Interfaces Group MIB";
+  }
+
+  /* Data nodes */
+
+  container interfaces {
+    description
+      "Interface parameters.";
+
+    list interface {
+      key "name";
+      unique "type location";
+
+      description
+        "The list of interfaces on the device.";
+
+      leaf name {
+        type string;
+        description
+          "The name of the interface.
+
+           A device MAY restrict the allowed values for this leaf,
+           possibly depending on the type and location.
+
+           If the device allows arbitrarily named interfaces, the
+           feature 'arbitrary-names' is advertised.
+
+           This leaf MAY be mapped to ifName by an implementation.
+           Such an implementation MAY restrict the allowed values for
+           this leaf so that it matches the restrictions of ifName.
+           If a NETCONF server that implements this restriction is
+           sent a value that doesn't match the restriction, it MUST
+           reply with an rpc-error with the error-tag
+           'invalid-value'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifName";
+      }
+
+      leaf description {
+        type string;
+        description
+          "A textual description of the interface.
+
+           This leaf MAY be mapped to ifAlias by an implementation.
+           Such an implementation MAY restrict the allowed values for
+           this leaf so that it matches the restrictions of ifAlias.
+           If a NETCONF server that implements this restriction is
+           sent a value that doesn't match the restriction, it MUST
+           reply with an rpc-error with the error-tag
+           'invalid-value'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifAlias";
+      }
+
+      leaf location {
+        type string;
+        description
+          "The device-specific location of the interface of a
+           particular type.  The format of the location string
+           depends on the interface type and the device.
+
+           If the interface's type represents a physical interface,
+           this leaf MUST be set.
+
+           When an interface entry is created, a server MAY
+           initialize the location leaf with a valid value, e.g., if
+           it is possible to derive the location from the name of
+           the interface.";
+      }
+
+      leaf enabled {
+        type boolean;
+        default "true";
+        description
+          "The desired state of the interface.
+
+           This leaf contains the configured, desired state of the
+           interface.  Systems that implement the IF-MIB use the
+           value of this leaf to set IF-MIB.ifAdminStatus to 'up' or
+           'down' after an ifEntry has been initialized, as described
+           in RFC 2863.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+      }
+
+      leaf last-change {
+        type yang:date-and-time;
+        config false;
+        description
+          "The time the interface entered its current operational
+           state.  If the current state was entered prior to the
+           last re-initialization of the local network management
+           subsystem, then this node is not present.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifLastChange";
+      }
+
+      leaf if-index {
+        if-feature if-mib;
+        type int32 {
+          range "1..2147483647";
+        }
+        config false;
+        description
+          "The ifIndex value for the ifEntry represented by this
+           interface.
+
+           Media-specific modules must specify how the type is
+           mapped to entries in the ifTable.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifIndex";
+      }
+
+      leaf phys-address {
+        type yang:phys-address;
+        config false;
+        description
+          "The interface's address at its protocol sub-layer.  For
+          example, for an 802.x interface, this object normally
+          contains a MAC address.  The interface's media-specific
+          modules must define the bit and byte ordering and the
+          format of the value of this object.  For interfaces that do
+          not have such an address (e.g., a serial line), this node
+          is not present.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifPhysAddress";
+      }
+
+      leaf-list higher-layer-if {
+        type interface-ref;
+        config false;
+        description
+          "A list of references to interfaces layered on top of this
+           interface.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifStackTable";
+      }
+
+      leaf-list lower-layer-if {
+        type interface-ref;
+        config false;
+        description
+          "A list of references to interfaces layered underneath this
+           interface.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifStackTable";
+      }
+
+      leaf speed {
+        type yang:gauge64;
+        units "bits / second";
+        config false;
+        description
+            "An estimate of the interface's current bandwidth in bits
+             per second.  For interfaces which do not vary in
+             bandwidth or for those where no accurate estimation can
+             be made, this node should contain the nominal bandwidth.
+             For interfaces that has no concept of bandwidth, this
+             node is not present.";
+        reference
+          "RFC 2863: The Interfaces Group MIB -
+                     ifSpeed, ifHighSpeed";
+      }
+
+      container statistics {
+        config false;
+        description
+          "A collection of interface-related statistics objects.";
+
+        leaf discontinuity-time {
+          type yang:date-and-time;
+          description
+            "The time on the most recent occasion at which any one or
+             more of this interface's counters suffered a
+             discontinuity.  If no such discontinuities have occurred
+             since the last re-initialization of the local management
+             subsystem, then this node contains the time the local
+             management subsystem re-initialized itself.";
+        }
+
+        leaf in-octets {
+          type yang:counter64;
+          description
+            "The total number of octets received on the interface,
+             including framing characters.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
+        }
+        leaf in-unicast-pkts {
+          type yang:counter64;
+          description
+            "The number of packets, delivered by this sub-layer to a
+             higher (sub-)layer, which were not addressed to a
+             multicast or broadcast address at this sub-layer.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
+        }
+        leaf in-broadcast-pkts {
+          type yang:counter64;
+          description
+            "The number of packets, delivered by this sub-layer to a
+             higher (sub-)layer, which were addressed to a broadcast
+             address at this sub-layer.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCInBroadcastPkts";
+        }
+        leaf in-multicast-pkts {
+          type yang:counter64;
+          description
+            "The number of packets, delivered by this sub-layer to a
+             higher (sub-)layer, which were addressed to a multicast
+             address at this sub-layer.  For a MAC layer protocol,
+             this includes both Group and Functional addresses.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCInMulticastPkts";
+        }
+        leaf in-discards {
+          type yang:counter32;
+          description
+            "The number of inbound packets which were chosen to be
+             discarded even though no errors had been detected to
+             prevent their being deliverable to a higher-layer
+             protocol.  One possible reason for discarding such a
+             packet could be to free up buffer space.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifInDiscards";
+        }
+        leaf in-errors {
+          type yang:counter32;
+          description
+            "For packet-oriented interfaces, the number of inbound
+             packets that contained errors preventing them from being
+             deliverable to a higher-layer protocol.  For character-
+             oriented or fixed-length interfaces, the number of
+             inbound transmission units that contained errors
+             preventing them from being deliverable to a higher-layer
+             protocol.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifInErrors";
+        }
+        leaf in-unknown-protos {
+          type yang:counter32;
+          description
+            "For packet-oriented interfaces, the number of packets
+             received via the interface which were discarded because
+             of an unknown or unsupported protocol.  For
+             character-oriented or fixed-length interfaces that
+             support protocol multiplexing the number of transmission
+             units received via the interface which were discarded
+             because of an unknown or unsupported protocol.  For any
+             interface that does not support protocol multiplexing,
+             this counter is not present.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
+        }
+
+        leaf out-octets {
+          type yang:counter64;
+          description
+            "The total number of octets transmitted out of the
+             interface, including framing characters.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
+        }
+        leaf out-unicast-pkts {
+          type yang:counter64;
+          description
+            "The total number of packets that higher-level protocols
+             requested be transmitted, and which were not addressed
+             to a multicast or broadcast address at this sub-layer,
+             including those that were discarded or not sent.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
+        }
+        leaf out-broadcast-pkts {
+          type yang:counter64;
+          description
+            "The total number of packets that higher-level protocols
+             requested be transmitted, and which were addressed to a
+             broadcast address at this sub-layer, including those
+             that were discarded or not sent.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCOutBroadcastPkts";
+        }
+        leaf out-multicast-pkts {
+          type yang:counter64;
+          description
+            "The total number of packets that higher-level protocols
+             requested be transmitted, and which were addressed to a
+             multicast address at this sub-layer, including those
+             that were discarded or not sent.  For a MAC layer
+             protocol, this includes both Group and Functional
+             addresses.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCOutMulticastPkts";
+        }
+        leaf out-discards {
+          type yang:counter32;
+          description
+            "The number of outbound packets which were chosen to be
+             discarded even though no errors had been detected to
+             prevent their being transmitted.  One possible reason
+             for discarding such a packet could be to free up buffer
+             space.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
+        }
+        leaf out-errors {
+          type yang:counter32;
+          description
+            "For packet-oriented interfaces, the number of outbound
+             packets that could not be transmitted because of errors.
+             For character-oriented or fixed-length interfaces, the
+             number of outbound transmission units that could not be
+             transmitted because of errors.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifOutErrors";
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/ietf/ietf-yang-types.yang b/code-generator/binding-generator-impl/src/test/resources/ietf/ietf-yang-types.yang
new file mode 100644 (file)
index 0000000..51d9f8b
--- /dev/null
@@ -0,0 +1,396 @@
+ module ietf-yang-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types";
+   prefix "yang";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of counter and gauge types ***/
+
+   typedef counter32 {
+     type uint32;
+     description
+      "The counter32 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter32 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter32 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter32.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter32 {
+     type yang:counter32;
+     default "0";
+     description
+      "The zero-based-counter32 type represents a counter32
+       that has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter32 textual convention of the SMIv2.";
+     reference
+       "RFC 4502: Remote Network Monitoring Management Information
+                  Base Version 2";
+   }
+
+   typedef counter64 {
+     type uint64;
+     description
+      "The counter64 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter64 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter64 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter64.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter64 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter64 {
+     type yang:counter64;
+     default "0";
+     description
+      "The zero-based-counter64 type represents a counter64 that
+       has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter64 textual convention of the SMIv2.";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   typedef gauge32 {
+     type uint32;
+     description
+      "The gauge32 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^32-1 (4294967295 decimal), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge32 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge32 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the Gauge32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef gauge64 {
+     type uint64;
+     description
+      "The gauge64 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^64-1 (18446744073709551615), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge64 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge64 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the CounterBasedGauge64 SMIv2 textual convention defined
+       in RFC 2856";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   /*** collection of identifier related types ***/
+
+   typedef object-identifier {
+     type string {
+       pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))'
+             + '(\.(0|([1-9]\d*)))*';
+     }
+     description
+      "The object-identifier type represents administratively
+       assigned names in a registration-hierarchical-name tree.
+
+       Values of this type are denoted as a sequence of numerical
+       non-negative sub-identifier values.  Each sub-identifier
+       value MUST NOT exceed 2^32-1 (4294967295).  Sub-identifiers
+       are separated by single dots and without any intermediate
+       whitespace.
+
+       The ASN.1 standard restricts the value space of the first
+       sub-identifier to 0, 1, or 2.  Furthermore, the value space
+       of the second sub-identifier is restricted to the range
+       0 to 39 if the first sub-identifier is 0 or 1.  Finally,
+       the ASN.1 standard requires that an object identifier
+       has always at least two sub-identifier.  The pattern
+       captures these restrictions.
+
+       Although the number of sub-identifiers is not limited,
+       module designers should realize that there may be
+       implementations that stick with the SMIv2 limit of 128
+       sub-identifiers.
+
+       This type is a superset of the SMIv2 OBJECT IDENTIFIER type
+       since it is not restricted to 128 sub-identifiers.  Hence,
+       this type SHOULD NOT be used to represent the SMIv2 OBJECT
+       IDENTIFIER type, the object-identifier-128 type SHOULD be
+       used instead.";
+     reference
+      "ISO9834-1: Information technology -- Open Systems
+       Interconnection -- Procedures for the operation of OSI
+       Registration Authorities: General procedures and top
+       arcs of the ASN.1 Object Identifier tree";
+   }
+
+
+
+
+   typedef object-identifier-128 {
+     type object-identifier {
+       pattern '\d*(\.\d*){1,127}';
+     }
+     description
+      "This type represents object-identifiers restricted to 128
+       sub-identifiers.
+
+       In the value set and its semantics, this type is equivalent
+       to the OBJECT IDENTIFIER type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   /*** collection of date and time related types ***/
+
+   typedef date-and-time {
+     type string {
+       pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
+             + '(Z|[\+\-]\d{2}:\d{2})';
+     }
+     description
+      "The date-and-time type is a profile of the ISO 8601
+       standard for representation of dates and times using the
+       Gregorian calendar.  The profile is defined by the
+       date-time production in Section 5.6 of RFC 3339.
+
+       The date-and-time type is compatible with the dateTime XML
+       schema type with the following notable exceptions:
+
+       (a) The date-and-time type does not allow negative years.
+
+       (b) The date-and-time time-offset -00:00 indicates an unknown
+           time zone (see RFC 3339) while -00:00 and +00:00 and Z all
+           represent the same time zone in dateTime.
+
+       (c) The canonical format (see below) of data-and-time values
+           differs from the canonical format used by the dateTime XML
+           schema type, which requires all times to be in UTC using the
+           time-offset 'Z'.
+
+       This type is not equivalent to the DateAndTime textual
+       convention of the SMIv2 since RFC 3339 uses a different
+       separator between full-date and full-time and provides
+       higher resolution of time-secfrac.
+
+       The canonical format for date-and-time values with a known time
+       zone uses a numeric time zone offset that is calculated using
+       the device's configured known offset to UTC time.  A change of
+       the device's offset to UTC time will cause date-and-time values
+       to change accordingly.  Such changes might happen periodically
+       in case a server follows automatically daylight saving time
+       (DST) time zone offset changes.  The canonical format for
+       date-and-time values with an unknown time zone (usually referring
+       to the notion of local time) uses the time-offset -00:00.";
+     reference
+      "RFC 3339: Date and Time on the Internet: Timestamps
+       RFC 2579: Textual Conventions for SMIv2
+       XSD-TYPES: XML Schema Part 2: Datatypes Second Edition";
+   }
+
+   typedef timeticks {
+     type uint32;
+     description
+      "The timeticks type represents a non-negative integer that
+       represents the time, modulo 2^32 (4294967296 decimal), in
+       hundredths of a second between two epochs.  When a schema
+       node is defined that uses this type, the description of
+       the schema node identifies both of the reference epochs.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeTicks type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef timestamp {
+     type yang:timeticks;
+     description
+      "The timestamp type represents the value of an associated
+       timeticks schema node at which a specific occurrence happened.
+       The specific occurrence must be defined in the description
+       of any schema node defined using this type.  When the specific
+       occurrence occurred prior to the last time the associated
+       timeticks attribute was zero, then the timestamp value is
+       zero.  Note that this requires all timestamp values to be
+       reset to zero when the value of the associated timeticks
+       attribute reaches 497+ days and wraps around to zero.
+
+       The associated timeticks schema node must be specified
+       in the description of any schema node using this type.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeStamp textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of generic address types ***/
+
+   typedef phys-address {
+     type string {
+       pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
+     }
+     description
+      "Represents media- or physical-level addresses represented
+       as a sequence octets, each octet represented by two hexadecimal
+       numbers.  Octets are separated by colons.  The canonical
+       representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the PhysAddress textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   typedef mac-address {
+     type string {
+       pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
+     }
+     description
+      "The mac-address type represents an IEEE 802 MAC address.
+       The canonical representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the MacAddress textual convention of the SMIv2.";
+     reference
+      "IEEE 802: IEEE Standard for Local and Metropolitan Area
+                 Networks: Overview and Architecture
+       RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of XML specific types ***/
+
+   typedef xpath1.0 {
+     type string;
+     description
+      "This type represents an XPATH 1.0 expression.
+
+       When a schema node is defined that uses this type, the
+       description of the schema node MUST specify the XPath
+       context in which the XPath expression is evaluated.";
+     reference
+      "XPATH: XML Path Language (XPath) Version 1.0";
+   }
+
+ }
diff --git a/code-generator/binding-generator-impl/src/test/resources/leafref-test-invalid-model/foo.yang b/code-generator/binding-generator-impl/src/test/resources/leafref-test-invalid-model/foo.yang
new file mode 100644 (file)
index 0000000..6a09a4d
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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 "f";
+
+    revision "2014-03-10" {
+    }
+
+    container links {
+        container link {
+            leaf source {
+                type leafref {
+                    path "../id";
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/leafref-test-models/abstract-topology@2013-02-08.yang b/code-generator/binding-generator-impl/src/test/resources/leafref-test-models/abstract-topology@2013-02-08.yang
new file mode 100644 (file)
index 0000000..be31192
--- /dev/null
@@ -0,0 +1,147 @@
+module abstract-topology {
+    yang-version 1;
+    namespace "urn:model:abstract:topology";
+    prefix "tp";
+
+    import ietf-inet-types {
+        prefix "inet";
+        revision-date 2010-09-24;
+    }
+
+    import ietf-interfaces {
+        prefix "if";
+        revision-date 2012-11-15;
+    }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description
+        "This module contains the definitions of elements that creates network 
+    topology i.e. definition of network nodes and links. This module is not designed to be used solely for network representation. This module SHOULD be used as base module in defining the network topology.";
+
+    revision "2013-02-08" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+    
+    revision "2013-01-01" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+    
+    typedef node-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id";
+        }
+        description "This type is used for leafs that reference network node instance.";
+    }
+
+    typedef link-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-links/tp:network-link/tp:link-id";
+        }
+        description "This type is used for leafs that reference network link instance.";
+    }
+
+    typedef interface-id-ref {
+        type leafref {
+            path "/tp:topology/tp:interfaces/tp:interface/tp:interface-id";
+        }
+    }
+
+    container topology {
+        description "This is the model of abstract topology which contains only Network Nodes and Network Links. Each topology MUST be identified by unique topology-id for reason that the store could contain many topologies.";
+
+        leaf topology-id {
+            type inet:uri;
+            description "It is presumed that datastore will contain many topologies. To distinguish between topologies it is vital to have
+            UNIQUE topology identifier.";
+        }
+
+        leaf cond-leafref {
+            type leafref {
+                path "/tp:topology/tp:network-nodes/tp:network-node[node-id = 'super-node']";
+            }
+        }
+
+        container network-nodes {
+            list network-node {
+                key "node-id";
+
+                leaf node-id {
+                    type inet:uri;
+                    description "The Topology identifier of network-node.";
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Node contains.";
+                }
+                description "The list of network nodes defined for topology.";
+            }
+        }
+
+        container interfaces {
+            list interface {
+                key "interface-id";
+
+                leaf interface-id {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:name";
+                    }
+                }
+
+                leaf-list higher-layer-if {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:higher-layer-if";
+                    }
+                }
+            }
+        }
+        
+        container network-links {
+            list network-link {
+                key "link-id";
+
+                leaf link-id {
+                    type inet:uri;
+                    description "";
+                }
+
+                container source-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Source node identifier.";
+                    }
+                }
+
+                container destination-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Destination node identifier.";
+                    }
+                }
+
+                container tunnels {
+                    list tunnel {
+                        key "tunnel-id";
+
+                        leaf tunnel-id {
+                            type leafref {
+                                path "../../../link-id";
+                            }
+                        }
+                    }
+                }
+
+                leaf interface {
+                    type interface-id-ref;
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Link contains.";
+                }
+                description "The Network Link which is defined by Local (Source) and Remote (Destination) Network Nodes. Every link MUST be defined either by identifier and
+                his local and remote Network Nodes (In real applications it is common that many links are originated from one node and end up in same remote node). To ensure that we would always know to distinguish between links, every link SHOULD have identifier.";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/list-composite-key.yang b/code-generator/binding-generator-impl/src/test/resources/list-composite-key.yang
new file mode 100644 (file)
index 0000000..07e1dc7
--- /dev/null
@@ -0,0 +1,62 @@
+module list-composite-key {
+    yang-version 1;
+    namespace "urn:composite.key";
+    prefix "scd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+        This module contains the definitions of elements that creates network 
+        topology i.e. definition of network nodes and links. This module is
+        not designed to be used solely for network representation. This module
+        SHOULD be used as base module in defining the network topology.
+    ";
+
+    revision "2013-02-27" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    container list-parent-container {
+
+        list composite-key-list {
+            key "key1 key2";
+
+            leaf key1 {
+                type int8;
+            }
+            
+            leaf key2 {
+                type string;
+            }
+            
+            list inner-list {
+                key "key1";
+                
+                leaf key1 {
+                    type uint16;
+                }
+                
+                leaf foo {
+                    type int32;
+                }
+            }
+            
+            leaf foo {
+                type int32;
+            }
+        }
+        
+        list no-key-list {
+            leaf foo {
+                type int32;
+            }
+            
+            leaf bar {
+                type decimal64 {
+                    fraction-digits 2;
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/refine.yang b/code-generator/binding-generator-impl/src/test/resources/refine.yang
new file mode 100644 (file)
index 0000000..11115f8
--- /dev/null
@@ -0,0 +1,65 @@
+module module-refine {
+
+    namespace "urn:refine:module";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-9-11 {
+    }
+
+    grouping grp {
+        leaf-list lflst {
+            type string;
+            min-elements 16;
+            max-elements 32;
+            must "old = 44";
+        }
+        choice chc {
+            default second;
+            case first {
+                leaf lf-of-case1 {
+                    type int32;
+                }
+            }
+            case second {
+                leaf lf-of-case2 {
+                    type int16;
+                }
+            }
+        }
+        choice chc2 {
+            mandatory "true";
+            case first2 {
+            }
+            case second2 {
+            }
+        }
+        anyxml data {
+            mandatory "true";
+            must "something = 7";
+        }
+    }
+
+    uses grp {
+        refine lflst {
+            min-elements 32;
+            max-elements 64;
+            must "new = 57";
+            new-subnode "some value from lflst";
+        }
+        refine chc {
+            default first;
+            new-subnode-chc "some value from chc";
+        }
+        refine chc2 {
+            mandatory "false"; 
+        }            
+        refine data {
+            mandatory "false";
+            must "something-else = 9";
+            new-subnode-data "some value from data";
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/simple-bits-demo.yang b/code-generator/binding-generator-impl/src/test/resources/simple-bits-demo.yang
new file mode 100644 (file)
index 0000000..160181b
--- /dev/null
@@ -0,0 +1,54 @@
+module simple-bits-demo {
+    
+    namespace "urn:simple:bits:demo";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";    
+
+    revision 2013-06-11 {
+        
+    }
+
+    typedef byte-type {
+        type bits {
+            bit first-bit {
+                position 10;
+            }
+            bit second-bit {
+                position 20;
+            }
+            bit third-bit {
+                position 30;
+            }
+            bit forth-bit {
+                position 40;
+            }       
+            bit fifth-bit {
+                position 50;
+            }       
+            bit sixth-bit {
+                position 60;
+            }       
+            bit seventh-bit {
+                position 70;
+            }       
+            bit eight-bit {
+                position 80;
+            }       
+        }
+    }
+
+    typedef jo {
+        type uint32;
+    }
+
+    
+    container leaf-parent-container {
+        leaf byte-leaf {
+            type byte-type;
+        }
+        
+    }
+
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/simple-container-demo.yang b/code-generator/binding-generator-impl/src/test/resources/simple-container-demo.yang
new file mode 100644 (file)
index 0000000..3962274
--- /dev/null
@@ -0,0 +1,45 @@
+module simple-container-demo {
+       yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "scd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+        This module contains the definitions of elements that creates network 
+        topology i.e. definition of network nodes and links. This module is
+        not designed to be used solely for network representation. This module
+        SHOULD be used as base module in defining the network topology.
+    ";
+
+    revision "2012-02-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    revision "2010-02-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    container simple-container {
+
+       leaf foo {
+               type int32;
+       }
+
+       leaf bar {
+               type string;
+               config true;
+       }
+
+       container nested-container {
+               leaf foo {
+                       type uint8;
+               }
+
+               leaf bar {
+                       type string;
+               }
+       }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/simple-leaf-list-demo.yang b/code-generator/binding-generator-impl/src/test/resources/simple-leaf-list-demo.yang
new file mode 100644 (file)
index 0000000..c0e77ef
--- /dev/null
@@ -0,0 +1,46 @@
+module simple-leaf-list-demo {
+    yang-version 1;
+    namespace "urn:simple.leaf-list.demo";
+    prefix "scd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+        This module contains the definitions of elements that creates network 
+        topology i.e. definition of network nodes and links. This module is
+        not designed to be used solely for network representation. This module
+        SHOULD be used as base module in defining the network topology.
+    ";
+
+    revision "2012-02-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    revision "2010-02-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    container simple-container {
+
+        leaf-list foo {
+            type int32;
+        }
+
+        leaf bar {
+            type string;
+            config true;
+        }
+
+        container nested-container {
+            leaf foo {
+                type uint8;
+            }
+
+            leaf-list bar {
+                type string;
+                config true;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/simple-list-demo.yang b/code-generator/binding-generator-impl/src/test/resources/simple-list-demo.yang
new file mode 100644 (file)
index 0000000..69f7f5c
--- /dev/null
@@ -0,0 +1,49 @@
+module simple-list-demo {
+       yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "scd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+        This module contains the definitions of elements that creates network 
+        topology i.e. definition of network nodes and links. This module is
+        not designed to be used solely for network representation. This module
+        SHOULD be used as base module in defining the network topology.
+    ";
+
+    revision "2013-02-27" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    container list-parent-container {
+
+       list simple-list {
+               key "list-key";
+
+               leaf list-key {
+                       type int8;
+               }
+            
+            container list-child-container {
+                leaf foo {
+                    type uint8;
+                }
+            }
+            
+               leaf foo {
+                       type int32;
+               }
+            
+            leaf-list simple-leaf-list {
+                type int32;
+            }
+            
+               leaf bar {
+                       type string;
+                       config true;
+               }       
+       }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/simple-string-demo.yang b/code-generator/binding-generator-impl/src/test/resources/simple-string-demo.yang
new file mode 100644 (file)
index 0000000..687d2a1
--- /dev/null
@@ -0,0 +1,23 @@
+module simple-string-demo {
+
+    namespace "urn:simple:string:demo";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-06-18 {
+        
+    }
+
+
+    typedef typedef-string {
+        type string {
+            length "40";
+            pattern "[0-9A-F]*";
+            pattern "[B-D]*";
+            pattern "[4-7]*";
+        }
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/type-provider/test.yang b/code-generator/binding-generator-impl/src/test/resources/type-provider/test.yang
new file mode 100644 (file)
index 0000000..d17b86e
--- /dev/null
@@ -0,0 +1,414 @@
+module test {
+    yang-version 1;
+    namespace "urn:opendaylight:test";
+    prefix "t";
+
+    import ietf-inet-types {
+        prefix "inet";
+    }
+
+    revision "2013-10-08" {
+    }
+
+
+
+    // binary
+    typedef my-binary {
+        type binary;
+    }
+
+    leaf ext-binary {
+        type my-binary;
+        default "TWFu";
+    }
+
+    leaf leaf-binary {
+        type binary;
+        default "TWFu";
+    }
+
+
+
+    // bits
+    typedef my-bits {
+        type bits {
+            bit ctrl;
+            bit alt {
+                position 5;
+            }
+            bit delete;
+        }
+    }
+
+    leaf ext-bits {
+        type my-bits;
+        default "delete";
+    }
+
+    leaf leaf-bits {
+        type bits {
+            bit ctrl;
+            bit alt {
+                position 5;
+            }
+            bit delete;
+        }
+        default "delete";
+    }
+
+
+
+    // boolean
+    typedef my-boolean {
+        type boolean;
+    }
+
+    leaf ext-boolean {
+        type my-boolean;
+        default true;
+    }
+
+    leaf leaf-boolean {
+        type boolean;
+        default true;
+    }
+
+
+
+    // decimal64
+    typedef my-decimal64 {
+        type decimal64 {
+            fraction-digits 4;
+        }
+    }
+
+    leaf ext-decimal64 {
+        type my-decimal64;
+        default "3.14";
+    }
+
+    leaf leaf-decimal64 {
+        type decimal64 {
+            fraction-digits 4;
+        }
+        default "3.14";
+    }
+
+
+
+    // empty
+    typedef my-empty {
+        type empty;
+    }
+
+    leaf ext-empty {
+        type my-empty;
+        default false;
+    }
+
+    leaf leaf-empty {
+        type empty;
+        default false;
+    }
+
+
+
+    // enumeration
+    typedef my-enumeration {
+        type enumeration {
+            enum zero;
+            enum one;
+            enum seven {
+                value 7;
+            }
+        }
+    }
+
+    leaf ext-enumeration {
+        type my-enumeration;
+        default seven;
+    }
+
+    leaf leaf-enumeration {
+        type enumeration {
+            enum zero;
+            enum one;
+            enum seven {
+                value 7;
+            }
+        }
+        default seven;
+    }
+
+
+
+    // identityref
+    typedef my-identityref {
+        type identityref {
+            base alg;
+        }
+    }
+
+    leaf ext-identityref {
+        type my-identityref;
+    }
+
+    leaf leaf-identityref {
+        type identityref {
+            base alg;
+        }
+    }
+
+
+
+    // int8
+    typedef my-int8 {
+        type int8;
+    }
+
+    leaf ext-int8 {
+        type my-int8;
+        default "11";
+    }
+
+    leaf leaf-int8 {
+        type int8;
+        default "11";
+    }
+
+
+
+    // int16
+    typedef my-int16 {
+        type int16;
+    }
+
+    leaf ext-int16 {
+        type my-int16;
+        default "111";
+    }
+
+    leaf leaf-int16 {
+        type int16;
+        default "111";
+    }
+
+
+
+    // int32
+    typedef my-int32 {
+        type int32;
+    }
+
+    leaf ext-int32 {
+        type my-int32;
+        default "1111";
+    }
+
+    leaf leaf-int32 {
+        type int32;
+        default "1111";
+    }
+
+
+
+    // int64
+    typedef my-int64 {
+        type int64;
+    }
+
+    leaf ext-int64 {
+        type my-int64;
+        default "11111";
+    }
+
+    leaf leaf-int64 {
+        type int64;
+        default "11111";
+    }
+
+
+
+    // leafref
+    typedef my-leafref {
+        type leafref {
+            path "/links/node/id-64";
+        }
+    }
+
+    leaf ext-leafref {
+        type my-leafref;
+        default "1.234";
+    }
+
+    leaf leaf-leafref {
+        type leafref {
+            path "/links/node/id-64";
+        }
+        default "1.234";
+    }
+
+    typedef my-leafref1 {
+        type leafref {
+            path "/links/node/id-for-binary";
+        }
+    }
+
+    leaf ext-leafref1 {
+        type my-leafref1;
+        default "TWFu";
+    }
+
+    leaf leaf-leafref1 {
+        type leafref {
+            path "/links/node/id-for-binary";
+        }
+        default "TWFu";
+    }
+
+
+
+    // string
+    typedef my-string {
+        type string;
+    }
+
+    leaf ext-string {
+        type my-string;
+        default "name";
+    }
+
+    leaf leaf-string {
+        type string;
+        default "name";
+    }
+
+
+
+    // uint8
+    typedef my-uint8 {
+        type uint8;
+    }
+
+    leaf ext-uint8 {
+        type my-uint8;
+        default "11";
+    }
+
+    leaf leaf-uint8 {
+        type uint8;
+        default "11";
+    }
+
+
+
+    // uint16
+    typedef my-uint16 {
+        type uint16;
+    }
+
+    leaf ext-uint16 {
+        type my-uint16;
+        default "111";
+    }
+
+    leaf leaf-uint16 {
+        type uint16;
+        default "111";
+    }
+
+
+
+    // uint32
+    typedef my-uint32 {
+        type uint32;
+    }
+
+    leaf ext-uint32 {
+        type my-uint32;
+        default "1111";
+    }
+
+    leaf leaf-uint32 {
+        type uint32;
+        default "1111";
+    }
+
+
+
+    // uint64
+    typedef my-uint64 {
+        type uint64;
+    }
+
+    leaf ext-uint64 {
+        type my-uint64;
+        default "11111";
+    }
+
+    leaf leaf-uint64 {
+        type uint64;
+        default "11111";
+    }
+
+    // uint64
+    typedef my-union {
+        type union {
+            type string;
+            type my-binary;
+        }
+    }
+
+    leaf ext-union {
+        type my-union;
+        default "111";
+    }
+
+    leaf leaf-union {
+        type union {
+            type string;
+            type int8;
+        }
+        default "111";
+    }
+
+    container c1 {
+        container c2 {
+            typedef nested-union {
+                type union {
+                    type string;
+                    type int16;
+                }
+            }
+            container c3 {
+                leaf id {
+                    type nested-union;
+                    default "111";
+                }
+            }
+        }
+    }
+
+
+    list links {
+        container node {
+            leaf id-64 {
+                type decimal64 {
+                    fraction-digits "7";
+                }
+            }
+            leaf id-for-binary {
+                type my-binary;
+            }
+        }
+    }
+
+    identity alg {
+    }
+
+    leaf ip-leaf {
+        type inet:ipv4-address;
+        default "0.0.0.1";
+    }
+
+}
diff --git a/code-generator/binding-generator-impl/src/test/resources/typedef-of-typedef/typedef_of_typedef.yang b/code-generator/binding-generator-impl/src/test/resources/typedef-of-typedef/typedef_of_typedef.yang
new file mode 100644 (file)
index 0000000..b8558b3
--- /dev/null
@@ -0,0 +1,91 @@
+module typedef_typedef {
+    
+    namespace "urn:typedef:typedef";
+    prefix "sbd";
+
+    import ietf-inet-types {
+        prefix "inet";
+        revision-date 2010-09-24;
+    }    
+
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-09 {
+        
+    }
+
+
+    typedef typedef-from-import {
+       type inet:ipv4-address;
+    }
+
+
+   typedef byte-type {
+        type bits {
+            bit first-bit {
+                position 10;
+            }
+            bit second-bit {
+                position 20;
+            }
+         }
+    }    
+    
+    
+  typedef typedef-enum-fruit {
+    type enumeration {
+      enum "apple" {
+        value 1;
+        description "gold";
+      }
+      enum "pear" {
+        value 2;
+      }
+    }
+  }    
+    
+    typedef simple-typedef1 {
+        type uint8;
+    }
+    
+    typedef simple-typedef2 {
+        type simple-typedef1;
+    }
+    
+    typedef simple-typedef3 {
+        type simple-typedef2;
+    }
+    
+    typedef simple-typedef4 {
+        type simple-typedef3;
+    }
+    
+    typedef simple-typedef1-1 {
+        type uint16;
+    }
+
+    
+    typedef union-typedef {
+        type union {
+            type simple-typedef1;
+            type simple-typedef4;
+            type byte-type;
+            type typedef-enum-fruit;
+        }
+    }
+    
+    typedef extended-typedef-union {
+        type union-typedef;
+    }
+    
+    
+    typedef extended-typedef-simple {
+        type simple-typedef1;
+    }
+    
+    typedef extended-typedef-enum {
+        type typedef-enum-fruit;
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/union-test-models/abstract-topology.yang b/code-generator/binding-generator-impl/src/test/resources/union-test-models/abstract-topology.yang
new file mode 100644 (file)
index 0000000..a4b589b
--- /dev/null
@@ -0,0 +1,120 @@
+module abstract-topology {
+    yang-version 1;
+    namespace "urn:model:abstract:topology";
+    prefix "tp";
+
+    import ietf-inet-types { 
+        prefix "inet"; 
+        revision-date 2010-09-24;
+    }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description
+        "This module contains the definitions of elements that creates network 
+    topology i.e. definition of network nodes and links. This module is not designed to be used solely for network representation. This module SHOULD be used as base module in defining the network topology.";
+
+    revision "2013-02-08" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+    
+    revision "2013-01-01" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+
+    typedef union-enum {
+        type union {
+            type int32;
+            type enumeration {
+                enum "unbounded";
+            }
+        }
+    }
+
+    typedef link-address {
+        type union {
+            type inet:ip-address;
+            type string;
+        }
+    }
+
+    typedef node-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id";
+        }
+        description "This type is used for leafs that reference network node instance.";
+    }
+
+    typedef link-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-links/tp:network-link/tp:link-id";
+        }
+        description "This type is used for leafs that reference network link instance.";
+    }
+
+    container topology {
+        description "This is the model of abstract topology which contains only Network Nodes and Network Links. Each topology MUST be identified by unique topology-id for reason that the store could contain many topologies.";
+
+        leaf topology-id {
+            type inet:uri;
+            description "It is presumed that datastore will contain many topologies. To distinguish between topologies it is vital to have
+            UNIQUE topology identifier.";
+        }
+
+        container network-nodes {
+            list network-node {
+                key "node-id";
+
+                leaf node-id {
+                    type inet:uri;
+                    description "The Topology identifier of network-node.";
+                }
+
+                leaf bounding {
+                    type union-enum;
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Node contains.";
+                }
+                description "The list of network nodes defined for topology.";
+            }
+        }
+        
+        container network-links {
+            list network-link {
+                key "link-id";
+
+                leaf link-id {
+                    type inet:uri;
+                    description "";
+                }
+
+                leaf link-address {
+                    type link-address;
+                }
+
+                container source-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Source node identifier.";
+                    }
+                }
+
+                container destination-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Destination node identifier.";
+                    }
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Link contains.";
+                }
+                description "The Network Link which is defined by Local (Source) and Remote (Destination) Network Nodes. Every link MUST be defined either by identifier and
+                his local and remote Network Nodes (In real applications it is common that many links are originated from one node and end up in same remote node). To ensure that we would always know to distinguish between links, every link SHOULD have identifier.";
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping.yang
new file mode 100644 (file)
index 0000000..36913cd
--- /dev/null
@@ -0,0 +1,145 @@
+module grouping_uses {
+
+    namespace "urn:uses:of:grouping";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+
+
+  
+    grouping grouping-modul-test {
+        leaf leaf-grouping-modul-test {
+            type string;
+        }
+        leaf leaf-grouping-modul-test2 {
+            type uint8;
+        }
+    }
+
+    grouping grouping-container-test {
+        leaf leaf-grouping-container-test1 {
+            type string;
+        }
+        leaf leaf-grouping-container-test2 {
+            type uint8;
+        }
+    }
+
+    grouping grouping-case-test {
+        leaf leaf-grouping-case-test1 {
+            type string;
+        }     
+    }
+
+    grouping grouping-choice-test {
+        choice choice-grouing-choice-test {
+            case case-choice-grouping-choice-test1 {
+                leaf leaf-case-choice-grouping-choice-test1 {
+                    type string;
+                }
+            }
+            case case-choice-grouping-choice-test2 {
+                leaf leaf-case-choice-grouping-choice-test2 {
+                    type uint8;
+                }
+            }
+        }
+    }
+    grouping grouping-list-test {
+        leaf leaf-grouping-list-test {
+            type string;
+        }
+        container container-grouping-list-test {
+            leaf leaf-container-grouping-list-test {
+                type uint8;
+            }
+        }
+        list list-grouping-list-test {
+            leaf leaf-list-grouping-list-test {
+                type int32;
+            }
+        }
+        leaf-list leaflist-grouping-list-test {
+            type string;
+        }
+    }     
+
+    grouping grouping-grouping-test {
+        leaf leaf-grouping-grouping {
+            type string;
+        }
+    }
+
+    grouping grouping-rpc-input-test {
+        container container-grouping-rpc-input-test {
+            leaf leaf-container-grouping-rpc-input-test {
+                type string;
+            }
+        }
+        leaf-list leaflist-grouping-rpc-input-test {
+            type uint8;
+        }
+    }
+    
+    grouping grouping-rpc-output-test {
+        leaf leaf-grouping-rpc-output-test {
+            type int8;
+        }
+    }
+     
+//grouping in GROUPING
+    grouping grouping-atest {
+        leaf leaf-grouping-test {
+            type int8;
+        }
+        uses grouping-grouping-test;
+    }
+    
+//grouping in MODUL     
+//     uses grouping-modul-test;
+
+//grouping in RPC
+        rpc rpc-test {
+            input {
+                uses grouping-rpc-input-test;
+            }
+            output {
+                uses grouping-rpc-output-test;
+            }
+        }     
+
+//grouping in CONTAINER
+    container container-test {
+        leaf container-leaf-test {
+            type string;
+        }
+        uses grouping-container-test;
+    }
+
+//grouping in CASE     
+    container container-with-choicetest {
+        choice choice-test {
+            case a {
+                leaf leaf-choice-test1 {
+                    type string;
+                }
+            }
+            case c {                 
+                uses grouping-case-test;                 
+            }
+        }     
+    }  
+//grouping in LIST     
+    list list-test {
+        leaf list-leaf-test {
+            type string;
+        }
+        uses grouping-list-test;
+    }   
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-augment.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-augment.yang
new file mode 100644 (file)
index 0000000..0b99911
--- /dev/null
@@ -0,0 +1,31 @@
+module grouping_uses_augment {
+    
+    namespace "urn:grouping:uses:augment";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+
+    grouping grouping-augment-test {
+        leaf leaf-grouping-augment-test {
+            type string;
+        }
+    }
+    
+
+    container container-augment {
+        leaf leaf-container-augment1 {
+            type string;
+        }
+        leaf leaf-container-augment2 {
+            type int64;
+        }
+    }         
+    
+    augment "/container-augment" {
+        uses grouping-augment-test;        
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-case.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-case.yang
new file mode 100644 (file)
index 0000000..2f97f1b
--- /dev/null
@@ -0,0 +1,47 @@
+module grouping_uses_case {
+
+    namespace "urn:grouping:uses:case";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+
+
+    grouping grouping-case-test {
+        leaf leaf-grouping-case-test1 {
+            type string;
+        }
+    }
+
+    grouping grouping-choice-test {
+        choice choice-grouing-choice-test {
+            case case-choice-grouping-choice-test1 {
+                leaf leaf-case-choice-grouping-choice-test1 {
+                    type string;
+                }
+            }
+            case case-choice-grouping-choice-test2 {
+                leaf leaf-case-choice-grouping-choice-test2 {
+                    type uint8;
+                }
+            }
+        }
+    }
+
+//grouping in CASE
+    container container-with-choicetest {
+        choice choice-test {
+            case a {
+                leaf leaf-choice-test1 {
+                    type string;
+                }
+            }
+            case c {
+                uses grouping-case-test;
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-container.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-container.yang
new file mode 100644 (file)
index 0000000..77b8c00
--- /dev/null
@@ -0,0 +1,28 @@
+module grouping_uses_container {
+    
+    namespace "urn:grouping:uses:container";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+    
+    grouping grouping-container-test {
+        leaf leaf-grouping-container-test1 {
+            type string;
+        }
+        leaf leaf-grouping-container-test2 {
+            type uint8;
+        }
+    }
+    
+//grouping in CONTAINER
+    container container-test {
+        leaf container-leaf-test {
+            type string;
+        }
+        uses grouping-container-test;
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-dependencies.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-dependencies.yang
new file mode 100644 (file)
index 0000000..ef6efb5
--- /dev/null
@@ -0,0 +1,52 @@
+module grouping_dependencies {
+    
+    namespace "urn:grouping:dependencies";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+  
+    grouping grouping-U {
+        leaf leaf-grouping-U {
+            type string;
+        }
+        uses grouping-V;
+        uses grouping-X;
+    }
+
+    grouping grouping-V {
+        leaf leaf-grouping-V {
+            type string;
+        }
+        uses grouping-Z;
+        uses grouping-ZZ;
+    }
+
+    grouping grouping-X {
+        leaf leaf-grouping-X {
+            type string;
+        }
+        uses grouping-Y;
+    }
+
+    grouping grouping-Y {
+        leaf leaf-grouping-Y {
+            type string;
+        }
+    }
+    
+    grouping grouping-Z {
+        leaf leaf-grouping-Z {
+            type string;
+        }
+    }
+    
+    grouping grouping-ZZ {
+        leaf leaf-grouping-ZZ {
+            type string;
+        }
+    }    
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-grouping.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-grouping.yang
new file mode 100644 (file)
index 0000000..3c68cd7
--- /dev/null
@@ -0,0 +1,27 @@
+module grouping_uses_grouping {
+    
+    namespace "urn:grouping:uses:grouping";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+
+    grouping grouping-grouping-test {
+        leaf leaf-grouping-grouping {
+            type string;
+        }
+    }
+     
+
+//grouping in GROUPING
+    grouping grouping-test {
+        leaf leaf-grouping-test {
+            type int8;
+        }
+        uses grouping-grouping-test;
+    }
+    
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-list.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-list.yang
new file mode 100644 (file)
index 0000000..420d336
--- /dev/null
@@ -0,0 +1,39 @@
+module grouping_uses_list {
+    
+    namespace "urn:grouping:uses:list";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+
+
+    grouping grouping-list-test {
+        leaf leaf-grouping-list-test {
+            type string;
+        }
+        container container-grouping-list-test {
+            leaf leaf-container-grouping-list-test {
+                type uint8;
+            }
+        }
+        list list-grouping-list-test {
+            leaf leaf-list-grouping-list-test {
+                type int32;
+            }
+        }
+        leaf-list leaffllist-grouping-list-test {
+            type string;
+        }
+    }
+
+//grouping in LIST
+    list list-test {
+        leaf list-leaf-test {
+            type string;
+        }
+        uses grouping-list-test;
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-modul.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-modul.yang
new file mode 100644 (file)
index 0000000..4dc6b17
--- /dev/null
@@ -0,0 +1,23 @@
+module grouping_uses_modul {
+
+    namespace "urn:grouping:uses:modul";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+
+    grouping grouping-modul-test {
+        leaf leaf-grouping-modul-test {
+            type string;
+        }
+        leaf leaf-grouping-modul-test2 {
+            type uint8;
+        }
+    }
+    
+//grouping in MODUL     
+    uses grouping-modul-test;
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-notification.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-notification.yang
new file mode 100644 (file)
index 0000000..e3caf2a
--- /dev/null
@@ -0,0 +1,30 @@
+module grouping_uses_notification {
+    
+    namespace "urn:grouping:uses:notification";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+
+    grouping grouping-notification-test {
+        container container-grouping-notification-test {
+            leaf leaf-container-grouping-notification-test {
+                type uint32;
+            }
+        }
+        leaf-list leaffllist-grouping-notification-test {
+            type string;
+        }
+    }
+
+//grouping in NOTIFICATION
+    notification notification-test {
+        leaf leaf-notification-test {
+            type string;
+        }
+        uses grouping-notification-test;
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-rpc.yang b/code-generator/binding-generator-impl/src/test/resources/uses-of-grouping/uses-of-grouping-rpc.yang
new file mode 100644 (file)
index 0000000..81f3b3c
--- /dev/null
@@ -0,0 +1,40 @@
+module grouping_uses_rpc {
+    
+    namespace "urn:grouping:uses:rpc";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-18 {
+    }
+
+     
+
+    grouping grouping-rpc-input-test {
+        container container-grouping-rpc-input-test {
+            leaf leaf-container-grouping-rpc-input-test {
+                type string;
+            }
+        }
+        leaf-list leaflist-grouping-rpc-input-test {
+            type uint8;
+        }
+    }
+    
+    grouping grouping-rpc-output-test {
+        leaf leaf-grouping-rpc-output-test {
+            type int8;
+        }
+    }
+
+//grouping in RPC
+    rpc rpc-test {
+        input {
+            uses grouping-rpc-input-test;
+        }
+        output {
+            uses grouping-rpc-output-test;
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-spi/pom.xml b/code-generator/binding-generator-spi/pom.xml
new file mode 100644 (file)
index 0000000..4ed76cc
--- /dev/null
@@ -0,0 +1,50 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>binding-generator-spi</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/BindingGeneratorServiceProvider.java b/code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/BindingGeneratorServiceProvider.java
new file mode 100644 (file)
index 0000000..d306069
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * 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.sal.binding.generator.spi;
+
+public interface BindingGeneratorServiceProvider {
+
+    void registerTypeProvider(final TypeProvider provider);
+}
diff --git a/code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/TypeProvider.java b/code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/TypeProvider.java
new file mode 100644 (file)
index 0000000..89d7a8c
--- /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.sal.binding.generator.spi;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+public interface TypeProvider {
+
+    @Deprecated
+    Type javaTypeForYangType(String type);
+
+    /**
+     * Resolve of yang Type Definition to it's java counter part.
+     * If the Type Definition contains one of yang primitive types the method
+     * will return java.lang. counterpart. (For example if yang type is int32
+     * the java counterpart is java.lang.Integer). In case that Type
+     * Definition contains extended type defined via yang typedef statement
+     * the method SHOULD return Generated Type or Generated Transfer Object
+     * if that Type is correctly referenced to resolved imported yang module.
+     * The method will return <code>null</code> value in situations that
+     * TypeDefinition can't be resolved (either due missing yang import or
+     * incorrectly specified type).
+     *
+     *
+     * @param type Type Definition to resolve from
+     * @return Resolved Type
+     */
+    Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode);
+
+    Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode, final Restrictions restrictions);
+
+    /**
+     * Returns string containing code for creation of new type instance.
+     *
+     * @param node
+     * @return
+     */
+    String getTypeDefaultConstruction(LeafSchemaNode node);
+
+    String getConstructorPropertyName(SchemaNode node);
+
+    String getParamNameFromType(TypeDefinition<?> type);
+
+}
diff --git a/code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/TypeProviderFactory.java b/code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/TypeProviderFactory.java
new file mode 100644 (file)
index 0000000..d0aa79b
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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.sal.binding.generator.spi;
+
+import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
+
+//FIXME not implemented anywhere
+public interface TypeProviderFactory {
+
+    TypeProvider providerFor(ModuleIdentifier module);
+}
diff --git a/code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/package-info.java b/code-generator/binding-generator-spi/src/main/java/org/opendaylight/yangtools/sal/binding/generator/spi/package-info.java
new file mode 100644 (file)
index 0000000..65b4db2
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.sal.binding.generator.spi;
\ No newline at end of file
diff --git a/code-generator/binding-generator-util/pom.xml b/code-generator/binding-generator-util/pom.xml
new file mode 100644 (file)
index 0000000..80e09f2
--- /dev/null
@@ -0,0 +1,56 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>binding-generator-util</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-parser-impl</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/AbstractBaseType.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/AbstractBaseType.java
new file mode 100644 (file)
index 0000000..2c15ad8
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * 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.binding.generator.util;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+/**
+ * It is used only as ancestor for other <code>Type</code>s
+ *
+ */
+public class AbstractBaseType implements Type {
+
+    /**
+     * Name of the package to which this <code>Type</code> belongs.
+     */
+    private final String packageName;
+
+    /**
+     * Name of this <code>Type</code>.
+     */
+    private final String name;
+
+    @Override
+    public String getPackageName() {
+        return packageName;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getFullyQualifiedName() {
+        if (packageName.isEmpty()) {
+            return name;
+        } else {
+            return packageName + "." + name;
+        }
+    }
+
+    /**
+     * Constructs the instance of this class with the concrete package name type
+     * name.
+     *
+     * @param pkName
+     *            string with the package name to which this <code>Type</code>
+     *            belongs
+     * @param name
+     *            string with the name for this <code>Type</code>
+     */
+    protected AbstractBaseType(String pkName, String name) {
+        if (pkName == null) {
+            throw new IllegalArgumentException("Package Name for Generated Type cannot be null!");
+        }
+        if (name == null) {
+            throw new IllegalArgumentException("Name of Generated Type cannot be null!");
+        }
+        this.packageName = pkName;
+        this.name = name;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((packageName == null) ? 0 : packageName.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof Type)) {
+            return false;
+        }
+        Type other = (Type) obj;
+        if (name == null) {
+            if (other.getName() != null) {
+                return false;
+            }
+        } else if (!name.equals(other.getName())) {
+            return false;
+        }
+        if (packageName == null) {
+            if (other.getPackageName() != null) {
+                return false;
+            }
+        } else if (!packageName.equals(other.getPackageName())) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        if (packageName.isEmpty()) {
+            return "Type (" + name + ")";
+        }
+        return "Type (" + packageName + "." + name + ")";
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtil.java
new file mode 100644 (file)
index 0000000..f5d72d7
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * 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.binding.generator.util;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.collect.Iterables;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.TypeMemberBuilder;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+
+/**
+ * Contains the methods for converting strings to valid JAVA language strings
+ * (package names, class names, attribute names).
+ *
+ *
+ */
+public final class BindingGeneratorUtil {
+
+    /**
+     * Impossible to instantiate this class. All of the methods or attributes
+     * are static.
+     */
+    private BindingGeneratorUtil() {
+    }
+
+    /**
+     * Pre-compiled replacement pattern.
+     */
+    private static final CharMatcher DOT_MATCHER = CharMatcher.is('.');
+    private static final CharMatcher DASH_COLON_MATCHER = CharMatcher.anyOf("-:");
+
+    private static final Restrictions EMPTY_RESTRICTIONS = new Restrictions() {
+        @Override
+        public List<LengthConstraint> getLengthConstraints() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<PatternConstraint> getPatternConstraints() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<RangeConstraint> getRangeConstraints() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return true;
+        }
+    };
+
+    private static final Comparator<TypeMemberBuilder<?>> SUID_MEMBER_COMPARATOR = new Comparator<TypeMemberBuilder<?>>() {
+        @Override
+        public int compare(final TypeMemberBuilder<?> o1, final TypeMemberBuilder<?> o2) {
+            return o1.getName().compareTo(o2.getName());
+        }
+    };
+
+    private static final Comparator<Type> SUID_NAME_COMPARATOR = new Comparator<Type>() {
+        @Override
+        public int compare(final Type o1, final Type o2) {
+            return o1.getFullyQualifiedName().compareTo(o2.getFullyQualifiedName());
+        }
+    };
+
+    /**
+     * Converts <code>parameterName</code> to valid JAVA parameter name.
+     *
+     * If the <code>parameterName</code> is one of the JAVA reserved words then
+     * it is prefixed with underscore character.
+     *
+     * @param parameterName
+     *            string with the parameter name
+     * @return string with the admissible parameter name
+     */
+    public static String resolveJavaReservedWordEquivalency(final String parameterName) {
+        if (parameterName != null && BindingMapping.JAVA_RESERVED_WORDS.contains(parameterName)) {
+            return "_" + parameterName;
+        }
+        return parameterName;
+    }
+
+    /**
+     * Converts module name to valid JAVA package name.
+     *
+     * The package name consists of:
+     * <ul>
+     * <li>prefix - <i>org.opendaylight.yang.gen.v</i></li>
+     * <li>module YANG version - <i>org.opendaylight.yang.gen.v</i></li>
+     * <li>module namespace - invalid characters are replaced with dots</li>
+     * <li>revision prefix - <i>.rev</i></li>
+     * <li>revision - YYYYMMDD (MM and DD aren't spread to the whole length)</li>
+     * </ul>
+     *
+     * @param module
+     *            module which contains data about namespace and revision date
+     * @return string with the valid JAVA package name
+     * @throws IllegalArgumentException
+     *             if the revision date of the <code>module</code> equals
+     *             <code>null</code>
+     * @deprecated USe {@link BindingMapping#getRootPackageName(QNameModule)} with {@link Module#getQNameModule()}.
+     */
+    @Deprecated
+    public static String moduleNamespaceToPackageName(final Module module) {
+        return BindingMapping.getRootPackageName(module.getQNameModule());
+    }
+
+    public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath) {
+        return packageNameForGeneratedType(basePackageName, schemaPath, false);
+    }
+
+    /**
+     * Creates package name from specified <code>basePackageName</code> (package
+     * name for module) and <code>schemaPath</code>.
+     *
+     * Resulting package name is concatenation of <code>basePackageName</code>
+     * and all local names of YANG nodes which are parents of some node for
+     * which <code>schemaPath</code> is specified.
+     *
+     * @param basePackageName
+     *            string with package name of the module
+     * @param schemaPath
+     *            list of names of YANG nodes which are parents of some node +
+     *            name of this node
+     * @return string with valid JAVA package name
+     */
+    public static String packageNameForGeneratedType(final String basePackageName, final SchemaPath schemaPath,
+            final boolean isUsesAugment) {
+        if (basePackageName == null) {
+            throw new IllegalArgumentException("Base Package Name cannot be NULL!");
+        }
+        if (schemaPath == null) {
+            throw new IllegalArgumentException("Schema Path cannot be NULL!");
+        }
+
+        final StringBuilder builder = new StringBuilder();
+        builder.append(basePackageName);
+        final Iterable<QName> iterable = schemaPath.getPathFromRoot();
+        final Iterator<QName> iterator = iterable.iterator();
+        int size = Iterables.size(iterable);
+        final int traversalSteps;
+        if (isUsesAugment) {
+            traversalSteps = size;
+        } else {
+            traversalSteps = size - 1;
+        }
+        for (int i = 0; i < traversalSteps; ++i) {
+            builder.append('.');
+            String nodeLocalName = iterator.next().getLocalName();
+            // FIXME: Collon ":" is invalid in node local name as per RFC6020, identifier statement.
+            builder.append(DASH_COLON_MATCHER.replaceFrom(nodeLocalName, '.'));
+        }
+        return BindingMapping.normalizePackageName(builder.toString());
+    }
+
+    /**
+     * Generates the package name for type definition from
+     * <code>typeDefinition</code> and <code>basePackageName</code>.
+     *
+     * @param basePackageName
+     *            string with the package name of the module
+     * @param typeDefinition
+     *            type definition for which the package name will be generated *
+     * @return string with valid JAVA package name
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>basePackageName</code> equals <code>null</code></li>
+     *             <li>if <code>typeDefinition</code> equals <code>null</code></li>
+     *             </ul>
+     */
+    public static String packageNameForTypeDefinition(final String basePackageName,
+            final TypeDefinition<?> typeDefinition) {
+        if (basePackageName == null) {
+            throw new IllegalArgumentException("Base Package Name cannot be NULL!");
+        }
+        if (typeDefinition == null) {
+            throw new IllegalArgumentException("Type Definition reference cannot be NULL!");
+        }
+
+        final StringBuilder builder = new StringBuilder();
+        builder.append(basePackageName);
+        return BindingMapping.normalizePackageName(builder.toString());
+    }
+
+    /**
+     * Converts <code>token</code> to string which is in accordance with best
+     * practices for JAVA class names.
+     *
+     * @param token
+     *            string which contains characters which should be converted to
+     *            JAVA class name
+     * @return string which is in accordance with best practices for JAVA class
+     *         name.
+     *
+     * @deprecated Use {@link BindingMapping#getClassName(QName)} instead.
+     */
+    @Deprecated
+    public static String parseToClassName(final String token) {
+        return parseToCamelCase(token, true);
+    }
+
+    /**
+     * Converts <code>token</code> to string which is in accordance with best
+     * practices for JAVA parameter names.
+     *
+     * @param token
+     *            string which contains characters which should be converted to
+     *            JAVA parameter name
+     * @return string which is in accordance with best practices for JAVA
+     *         parameter name.
+     *
+     * @deprecated Use {@link BindingMapping#getPropertyName(String)} instead.
+     */
+    @Deprecated public static String parseToValidParamName(final String token) {
+        return resolveJavaReservedWordEquivalency(parseToCamelCase(token, false));
+    }
+
+    /**
+     *
+     * Converts string <code>token</code> to the cammel case format.
+     *
+     * @param token
+     *            string which should be converted to the cammel case format
+     * @param uppercase
+     *            boolean value which says whether the first character of the
+     *            <code>token</code> should|shuldn't be uppercased
+     * @return string in the cammel case format
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>token</code> without white spaces is empty</li>
+     *             <li>if <code>token</code> equals null</li>
+     *             </ul>
+     */
+
+    private static String parseToCamelCase(final String token, final boolean uppercase) {
+        if (token == null) {
+            throw new IllegalArgumentException("Name can not be null");
+        }
+
+        String correctStr = DOT_MATCHER.removeFrom(token.trim());
+        if (correctStr.isEmpty()) {
+            throw new IllegalArgumentException("Name can not be empty");
+        }
+
+        correctStr = replaceWithCamelCase(correctStr, ' ');
+        correctStr = replaceWithCamelCase(correctStr, '-');
+        correctStr = replaceWithCamelCase(correctStr, '_');
+
+        char firstChar = correctStr.charAt(0);
+        firstChar = uppercase ? Character.toUpperCase(firstChar) : Character.toLowerCase(firstChar);
+
+        if (firstChar >= '0' && firstChar <= '9') {
+            return '_' + correctStr;
+        } else {
+            return firstChar + correctStr.substring(1);
+        }
+    }
+
+    /**
+     * Replaces all the occurrences of the <code>removalChar</code> in the
+     * <code>text</code> with empty string and converts following character to
+     * upper case.
+     *
+     * @param text
+     *            string with source text which should be converted
+     * @param removalChar
+     *            character which is sought in the <code>text</code>
+     * @return string which doesn't contain <code>removalChar</code> and has
+     *         following characters converted to upper case
+     * @throws IllegalArgumentException
+     *             if the length of the returning string has length 0
+     */
+    private static String replaceWithCamelCase(final String text, final char removalChar) {
+        int toBeRemovedPos = text.indexOf(removalChar);
+        if (toBeRemovedPos == -1) {
+            return text;
+        }
+
+        StringBuilder sb = new StringBuilder(text);
+        String toBeRemoved = String.valueOf(removalChar);
+        do {
+            sb.replace(toBeRemovedPos, toBeRemovedPos + 1, "");
+            // check if 'toBeRemoved' character is not the only character in
+            // 'text'
+            if (sb.length() == 0) {
+                throw new IllegalArgumentException("The resulting string can not be empty");
+            }
+            char replacement = Character.toUpperCase(sb.charAt(toBeRemovedPos));
+            sb.setCharAt(toBeRemovedPos, replacement);
+            toBeRemovedPos = sb.indexOf(toBeRemoved);
+        } while (toBeRemovedPos != -1);
+
+        return sb.toString();
+    }
+
+    private static <T> Iterable<T> sortedCollection(final Comparator<? super T> comparator, final Collection<T> input) {
+        if (input.size() > 1) {
+            final List<T> ret = new ArrayList<>(input);
+            Collections.sort(ret, comparator);
+            return ret;
+        } else {
+            return input;
+        }
+    }
+
+    public static long computeDefaultSUID(final GeneratedTypeBuilderBase<?> to) {
+        try {
+            ByteArrayOutputStream bout = new ByteArrayOutputStream();
+            DataOutputStream dout = new DataOutputStream(bout);
+
+            dout.writeUTF(to.getName());
+            dout.writeInt(to.isAbstract() ? 3 : 7);
+
+            for (Type ifc : sortedCollection(SUID_NAME_COMPARATOR, to.getImplementsTypes())) {
+                dout.writeUTF(ifc.getFullyQualifiedName());
+            }
+
+            for (GeneratedPropertyBuilder gp : sortedCollection(SUID_MEMBER_COMPARATOR, to.getProperties())) {
+                dout.writeUTF(gp.getName());
+            }
+
+            for (MethodSignatureBuilder m : sortedCollection(SUID_MEMBER_COMPARATOR, to.getMethodDefinitions())) {
+                if (!(m.getAccessModifier().equals(AccessModifier.PRIVATE))) {
+                    dout.writeUTF(m.getName());
+                    dout.write(m.getAccessModifier().ordinal());
+                }
+            }
+
+            dout.flush();
+
+            try {
+                MessageDigest md = MessageDigest.getInstance("SHA");
+                byte[] hashBytes = md.digest(bout.toByteArray());
+                long hash = 0;
+                for (int i = Math.min(hashBytes.length, 8) - 1; i >= 0; i--) {
+                    hash = (hash << 8) | (hashBytes[i] & 0xFF);
+                }
+                return hash;
+            } catch (NoSuchAlgorithmException ex) {
+                throw new SecurityException(ex.getMessage());
+            }
+        } catch (IOException ex) {
+            throw new InternalError();
+        }
+    }
+
+    public static Restrictions getRestrictions(final TypeDefinition<?> type) {
+        // Base types have no constraints, so get over it quickly
+        if (!(type instanceof ExtendedType)) {
+            return EMPTY_RESTRICTIONS;
+        }
+
+        // Take care of the extended types ...
+        final ExtendedType ext = (ExtendedType)type;
+        final List<LengthConstraint> length = ext.getLengthConstraints();
+        final List<PatternConstraint> pattern = ext.getPatternConstraints();
+
+        List<RangeConstraint> tmp = ext.getRangeConstraints();
+        if (tmp.isEmpty()) {
+            final TypeDefinition<?> base = ext.getBaseType();
+            if (base instanceof IntegerTypeDefinition) {
+                tmp = ((IntegerTypeDefinition)base).getRangeConstraints();
+            } else if (base instanceof UnsignedIntegerTypeDefinition) {
+                tmp = ((UnsignedIntegerTypeDefinition)base).getRangeConstraints();
+            } else if (base instanceof DecimalTypeDefinition) {
+                tmp = ((DecimalTypeDefinition)base).getRangeConstraints();
+            }
+        }
+
+        // Now, this may have ended up being empty, too...
+        if (length.isEmpty() && pattern.isEmpty() && tmp.isEmpty()) {
+            return EMPTY_RESTRICTIONS;
+        }
+
+        // Nope, not empty allocate a holder
+        final List<RangeConstraint> range = tmp;
+        return new Restrictions() {
+            @Override
+            public List<RangeConstraint> getRangeConstraints() {
+                return range;
+            }
+            @Override
+            public List<PatternConstraint> getPatternConstraints() {
+                return pattern;
+            }
+            @Override
+            public List<LengthConstraint> getLengthConstraints() {
+                return length;
+            }
+            @Override
+            public boolean isEmpty() {
+                return false;
+            }
+        };
+    }
+
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingTypes.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/BindingTypes.java
new file mode 100644 (file)
index 0000000..eb310b6
--- /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.binding.generator.util;
+
+import static org.opendaylight.yangtools.binding.generator.util.Types.parameterizedTypeFor;
+import static org.opendaylight.yangtools.binding.generator.util.Types.typeForClass;
+
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+public final class BindingTypes {
+
+    public static final ConcreteType AUGMENTABLE = typeForClass(Augmentable.class);
+    public static final ConcreteType AUGMENTATION = typeForClass(Augmentation.class);
+    public static final ConcreteType BASE_IDENTITY = typeForClass(BaseIdentity.class);
+    public static final ConcreteType DATA_OBJECT = typeForClass(DataObject.class);
+    public static final ConcreteType DATA_ROOT = typeForClass(DataRoot.class);
+    public static final ConcreteType IDENTIFIABLE = typeForClass(Identifiable.class);
+    public static final ConcreteType IDENTIFIER = typeForClass(Identifier.class);
+    public static final ConcreteType INSTANCE_IDENTIFIER = typeForClass(InstanceIdentifier.class);
+    public static final ConcreteType NOTIFICATION = typeForClass(Notification.class);
+    public static final ConcreteType NOTIFICATION_LISTENER = typeForClass(NotificationListener.class);
+    public static final ConcreteType RPC_SERVICE = typeForClass(RpcService.class);
+
+    private static final ConcreteType CHILD_OF = typeForClass(ChildOf.class);
+
+    private BindingTypes() {
+
+    }
+
+    public static ParameterizedType augmentable(Type t) {
+        return parameterizedTypeFor(AUGMENTABLE, t);
+    }
+
+    public static ParameterizedType childOf(Type t) {
+        return parameterizedTypeFor(CHILD_OF, t);
+    }
+
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/ReferencedTypeImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/ReferencedTypeImpl.java
new file mode 100644 (file)
index 0000000..c3c48d8
--- /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.binding.generator.util;
+
+/**
+ * 
+ * Wraps combination of <code>packageName</code> and <code>name</code> to the
+ * object representation
+ * 
+ */
+public final class ReferencedTypeImpl extends AbstractBaseType {
+
+    /**
+     * Creates instance of this class with concrete package name and type name
+     * 
+     * @param packageName
+     *            string with the package name
+     * @param name
+     *            string with the name for referenced type
+     */
+    public ReferencedTypeImpl(String packageName, String name) {
+        super(packageName, name);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("ReferencedTypeImpl [packageName=");
+        builder.append(getPackageName());
+        builder.append(", name=");
+        builder.append(getName());
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/TypeConstants.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/TypeConstants.java
new file mode 100644 (file)
index 0000000..d5982be
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.binding.generator.util;
+
+/**
+ * 
+ * Contains constants used in relations with <code>Type</code>.
+ */
+public final class TypeConstants {
+
+    /**
+     * Name of the class constant which hold list of the regular expression
+     * strings.
+     */
+    public static final String PATTERN_CONSTANT_NAME = "PATTERN_CONSTANTS";
+
+    /**
+     * Creation of new instance is prohibited.
+     */
+    private TypeConstants() {
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/Types.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/Types.java
new file mode 100644 (file)
index 0000000..be9b3d7
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * 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.binding.generator.util;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.Iterables;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Future;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.WildcardType;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+public final class Types {
+    private static final CacheLoader<Class<?>, ConcreteType> TYPE_LOADER =
+            new CacheLoader<Class<?>, ConcreteType>() {
+                @Override
+                public ConcreteType load(final Class<?> key) {
+                    return new ConcreteTypeImpl(key.getPackage().getName(), key.getSimpleName(), null);
+                }
+    };
+    private static final LoadingCache<Class<?>, ConcreteType> TYPE_CACHE =
+            CacheBuilder.newBuilder().weakKeys().softValues().build(TYPE_LOADER);
+
+    private static final Type SET_TYPE = typeForClass(Set.class);
+    private static final Type LIST_TYPE = typeForClass(List.class);
+    private static final Type MAP_TYPE = typeForClass(Map.class);
+
+    public static final ConcreteType BOOLEAN = typeForClass(Boolean.class);
+    public static final ConcreteType FUTURE = typeForClass(Future.class);
+    public static final ConcreteType STRING = typeForClass(String.class);
+    public static final ConcreteType VOID = typeForClass(Void.class);
+    public static final ConcreteType BYTE_ARRAY = primitiveType("byte[]", null);
+    public static final ConcreteType CHAR_ARRAY = primitiveType("char[]", null);
+    private static final Splitter DOT_SPLITTER = Splitter.on('.');
+
+    /**
+     * It is not desirable to create instance of this class
+     */
+    private Types() {
+    }
+
+    /**
+     * Creates the instance of type
+     * {@link org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
+     * ConcreteType} which represents JAVA <code>void</code> type.
+     *
+     * @return <code>ConcreteType</code> instance which represents JAVA
+     *         <code>void</code>
+     */
+    public static ConcreteType voidType() {
+        return VOID;
+    }
+
+    /**
+     * Creates the instance of type
+     * {@link org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
+     * ConcreteType} which represents primitive JAVA type for which package
+     * doesn't exist.
+     *
+     * @param primitiveType
+     *            string containing programmatic construction based on
+     *            primitive type (e.g byte[])
+     * @return <code>ConcreteType</code> instance which represents programmatic
+     *         construction with primitive JAVA type
+     */
+    public static ConcreteType primitiveType(final String primitiveType, final Restrictions restrictions) {
+        return new ConcreteTypeImpl("", primitiveType, restrictions);
+    }
+
+    /**
+     * Returns an instance of {@link ConcreteType} describing the class
+     *
+     * @param cls
+     *            Class to describe
+     * @return Description of class
+     */
+    public static ConcreteType typeForClass(final Class<?> cls) {
+        return TYPE_CACHE.getUnchecked(cls);
+    }
+
+    public static ConcreteType typeForClass(final Class<?> cls, final Restrictions restrictions) {
+        if (restrictions != null) {
+            return new ConcreteTypeImpl(cls.getPackage().getName(), cls.getSimpleName(), restrictions);
+        } else {
+            return typeForClass(cls);
+        }
+    }
+
+    /**
+     * Returns an instance of {@link ParameterizedType} describing the typed
+     * {@link Map}&lt;K,V&gt;
+     *
+     * @param keyType
+     *            Key Type
+     * @param valueType
+     *            Value Type
+     * @return Description of generic type instance
+     */
+    public static ParameterizedType mapTypeFor(final Type keyType, final Type valueType) {
+        return parameterizedTypeFor(MAP_TYPE, keyType, valueType);
+    }
+
+    /**
+     * Returns an instance of {@link ParameterizedType} describing the typed
+     * {@link Set}&lt;V&gt; with concrete type of value.
+     *
+     * @param valueType
+     *            Value Type
+     * @return Description of generic type instance of Set
+     */
+    public static ParameterizedType setTypeFor(final Type valueType) {
+        return parameterizedTypeFor(SET_TYPE, valueType);
+    }
+
+    /**
+     * Returns an instance of {@link ParameterizedType} describing the typed
+     * {@link List}&lt;V&gt; with concrete type of value.
+     *
+     * @param valueType
+     *            Value Type
+     * @return Description of type instance of List
+     */
+    public static ParameterizedType listTypeFor(final Type valueType) {
+        return parameterizedTypeFor(LIST_TYPE, valueType);
+    }
+
+    /**
+     * Creates instance of type
+     * {@link org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
+     * ParameterizedType}
+     *
+     * @param type
+     *            JAVA <code>Type</code> for raw type
+     * @param parameters
+     *            JAVA <code>Type</code>s for actual parameter types
+     * @return <code>ParametrizedType</code> reprezentation of <code>type</code>
+     *         and its parameters <code>parameters</code>
+     */
+    public static ParameterizedType parameterizedTypeFor(final Type type, final Type... parameters) {
+        return new ParametrizedTypeImpl(type, parameters);
+    }
+
+    /**
+     * Creates instance of type
+     * {@link org.opendaylight.yangtools.sal.binding.model.api.WildcardType
+     * WildcardType}
+     *
+     * @param packageName
+     *            string with the package name
+     * @param typeName
+     *            string with the type name
+     * @return <code>WildcardType</code> representation of
+     *         <code>packageName</code> and <code>typeName</code>
+     */
+    public static WildcardType wildcardTypeFor(final String packageName, final String typeName) {
+        return new WildcardTypeImpl(packageName, typeName);
+    }
+
+    /**
+     * Creates instance of
+     * {@link org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
+     * ParameterizedType} where raw type is
+     * {@link org.opendaylight.yangtools.yang.binding.Augmentable} and actual
+     * parameter is <code>valueType</code>.
+     *
+     * @param valueType
+     *            JAVA <code>Type</code> with actual parameter
+     * @return <code>ParametrizedType</code> representation of raw type
+     *         <code>Augmentable</code> with actual parameter
+     *         <code>valueType</code>
+     */
+    public static ParameterizedType augmentableTypeFor(final Type valueType) {
+        final Type augmentable = typeForClass(Augmentable.class);
+        return parameterizedTypeFor(augmentable, valueType);
+    }
+
+    /**
+     * Creates instance of
+     * {@link org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
+     * ParameterizedType} where raw type is
+     * {@link org.opendaylight.yangtools.yang.binding.Augmentation} and actual
+     * parameter is <code>valueType</code>.
+     *
+     * @param valueType
+     *            JAVA <code>Type</code> with actual parameter
+     * @return <code>ParametrizedType</code> reprezentation of raw type
+     *         <code>Augmentation</code> with actual parameter
+     *         <code>valueType</code>
+     */
+    public static ParameterizedType augmentationTypeFor(final Type valueType) {
+        final Type augmentation = typeForClass(Augmentation.class);
+        return parameterizedTypeFor(augmentation, valueType);
+    }
+
+
+    public static  @Nullable String getOuterClassName(final Type valueType) {
+        final String pkgName = valueType.getPackageName();
+        if(CharMatcher.JAVA_UPPER_CASE.indexIn(pkgName) >= 0) {
+            // It is inner class.
+            return Iterables.getLast(DOT_SPLITTER.split(pkgName));
+        }
+        return null;
+    }
+
+    /**
+     *
+     * Represents concrete JAVA type.
+     *
+     */
+    private static final class ConcreteTypeImpl extends AbstractBaseType implements ConcreteType {
+        private final Restrictions restrictions;
+
+        /**
+         * Creates instance of this class with package <code>pkName</code> and
+         * with the type name <code>name</code>.
+         *
+         * @param pkName
+         *            string with package name
+         * @param name
+         *            string with the name of the type
+         */
+        private ConcreteTypeImpl(final String pkName, final String name, final Restrictions restrictions) {
+            super(pkName, name);
+            this.restrictions = restrictions;
+        }
+
+        @Override
+        public Restrictions getRestrictions() {
+            return restrictions;
+        }
+    }
+
+    /**
+     *
+     * Represents parametrized JAVA type.
+     *
+     */
+    private static class ParametrizedTypeImpl extends AbstractBaseType implements ParameterizedType {
+        /**
+         * Array of JAVA actual type parameters.
+         */
+        private final Type[] actualTypes;
+
+        /**
+         * JAVA raw type (like List, Set, Map...)
+         */
+        private final Type rawType;
+
+        @Override
+        public Type[] getActualTypeArguments() {
+
+            return actualTypes;
+        }
+
+        @Override
+        public Type getRawType() {
+            return rawType;
+        }
+
+        /**
+         * Creates instance of this class with concrete rawType and array of
+         * actual parameters.
+         *
+         * @param rawType
+         *            JAVA <code>Type</code> for raw type
+         * @param actTypes
+         *            array of actual parameters
+         */
+        public ParametrizedTypeImpl(final Type rawType, final Type[] actTypes) {
+            super(rawType.getPackageName(), rawType.getName());
+            this.rawType = rawType;
+            this.actualTypes = actTypes.clone();
+        }
+
+    }
+
+    /**
+     *
+     * Represents JAVA bounded wildcard type.
+     *
+     */
+    private static class WildcardTypeImpl extends AbstractBaseType implements WildcardType {
+        /**
+         * Creates instance of this class with concrete package and type name.
+         *
+         * @param packageName
+         *            string with the package name
+         * @param typeName
+         *            string with the name of type
+         */
+        public WildcardTypeImpl(final String packageName, final String typeName) {
+            super(packageName, typeName);
+        }
+    }
+
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractGeneratedType.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractGeneratedType.java
new file mode 100644 (file)
index 0000000..a2bc6da
--- /dev/null
@@ -0,0 +1,215 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.yangtools.binding.generator.util.AbstractBaseType;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+
+abstract class AbstractGeneratedType extends AbstractBaseType implements GeneratedType {
+
+    private final Type parent;
+    private final String comment;
+    private final List<AnnotationType> annotations;
+    private final List<Type> implementsTypes;
+    private final List<Enumeration> enumerations;
+    private final List<Constant> constants;
+    private final List<MethodSignature> methodSignatures;
+    private final List<GeneratedType> enclosedTypes;
+    private final List<GeneratedProperty> properties;
+    private final boolean isAbstract;
+
+    public AbstractGeneratedType(final AbstractGeneratedTypeBuilder<?> builder) {
+        super(builder.getPackageName(), builder.getName());
+        this.parent = builder.getParent();
+        this.comment = builder.getComment();
+        this.annotations = toUnmodifiableAnnotations(builder.getAnnotations());
+        this.implementsTypes = makeUnmodifiable(builder.getImplementsTypes());
+        this.constants = makeUnmodifiable(builder.getConstants());
+        this.enumerations = toUnmodifiableEnumerations(builder.getEnumerations());
+        this.methodSignatures = toUnmodifiableMethods(builder.getMethodDefinitions());
+        this.enclosedTypes = toUnmodifiableEnclosedTypes(builder.getEnclosedTypes(),
+                builder.getEnclosedTransferObjects());
+        this.properties = toUnmodifiableProperties(builder.getProperties());
+        this.isAbstract = builder.isAbstract();
+    }
+
+    public AbstractGeneratedType(final Type parent, final String packageName, final String name, final String comment,
+            final List<AnnotationTypeBuilder> annotationBuilders, final boolean isAbstract,
+            final List<Type> implementsTypes, final List<GeneratedTypeBuilder> enclosedGenTypeBuilders,
+            final List<GeneratedTOBuilder> enclosedGenTOBuilders, final List<EnumBuilder> enumBuilders,
+            final List<Constant> constants, final List<MethodSignatureBuilder> methodBuilders,
+            final List<GeneratedPropertyBuilder> propertyBuilders) {
+        super(packageName, name);
+        this.parent = parent;
+        this.comment = comment;
+        this.annotations = toUnmodifiableAnnotations(annotationBuilders);
+        this.implementsTypes = makeUnmodifiable(implementsTypes);
+        this.constants = makeUnmodifiable(constants);
+        this.enumerations = toUnmodifiableEnumerations(enumBuilders);
+        this.methodSignatures = toUnmodifiableMethods(methodBuilders);
+        this.enclosedTypes = toUnmodifiableEnclosedTypes(enclosedGenTypeBuilders, enclosedGenTOBuilders);
+        this.properties = toUnmodifiableProperties(propertyBuilders);
+        this.isAbstract = isAbstract;
+    }
+
+    protected static final <T> List<T> makeUnmodifiable(final List<T> list) {
+        switch (list.size()) {
+        case 0:
+            return Collections.emptyList();
+        case 1:
+            return Collections.singletonList(list.get(0));
+        default:
+            return Collections.unmodifiableList(list);
+        }
+    }
+
+    private static List<GeneratedType> toUnmodifiableEnclosedTypes(final List<GeneratedTypeBuilder> enclosedGenTypeBuilders,
+            final List<GeneratedTOBuilder> enclosedGenTOBuilders) {
+        final ArrayList<GeneratedType> enclosedTypesList = new ArrayList<>(enclosedGenTypeBuilders.size() + enclosedGenTOBuilders.size());
+        for (final GeneratedTypeBuilder builder : enclosedGenTypeBuilders) {
+            if (builder != null) {
+                enclosedTypesList.add(builder.toInstance());
+            }
+        }
+
+        for (final GeneratedTOBuilder builder : enclosedGenTOBuilders) {
+            if (builder != null) {
+                enclosedTypesList.add(builder.toInstance());
+            }
+        }
+
+        return makeUnmodifiable(enclosedTypesList);
+    }
+
+    protected static final List<AnnotationType> toUnmodifiableAnnotations(final List<AnnotationTypeBuilder> annotationBuilders) {
+        final List<AnnotationType> annotationList = new ArrayList<>(annotationBuilders.size());
+        for (final AnnotationTypeBuilder builder : annotationBuilders) {
+            annotationList.add(builder.toInstance());
+        }
+        return makeUnmodifiable(annotationList);
+    }
+
+    protected final List<MethodSignature> toUnmodifiableMethods(final List<MethodSignatureBuilder> methodBuilders) {
+        final List<MethodSignature> methods = new ArrayList<>(methodBuilders.size());
+        for (final MethodSignatureBuilder methodBuilder : methodBuilders) {
+            methods.add(methodBuilder.toInstance(this));
+        }
+        return makeUnmodifiable(methods);
+    }
+
+    protected final List<Enumeration> toUnmodifiableEnumerations(final List<EnumBuilder> enumBuilders) {
+        final List<Enumeration> enums = new ArrayList<>(enumBuilders.size());
+        for (final EnumBuilder enumBuilder : enumBuilders) {
+            enums.add(enumBuilder.toInstance(this));
+        }
+        return makeUnmodifiable(enums);
+    }
+
+    protected final List<GeneratedProperty> toUnmodifiableProperties(final List<GeneratedPropertyBuilder> methodBuilders) {
+        final List<GeneratedProperty> methods = new ArrayList<>(methodBuilders.size());
+        for (final GeneratedPropertyBuilder methodBuilder : methodBuilders) {
+            methods.add(methodBuilder.toInstance(this));
+        }
+        return makeUnmodifiable(methods);
+    }
+
+    @Override
+    public final Type getParentType() {
+        return parent;
+    }
+
+    @Override
+    public final String getComment() {
+        return comment;
+    }
+
+    @Override
+    public final List<AnnotationType> getAnnotations() {
+        return annotations;
+    }
+
+    @Override
+    public final boolean isAbstract() {
+        return isAbstract;
+    }
+
+    @Override
+    public final List<Type> getImplements() {
+        return implementsTypes;
+    }
+
+    @Override
+    public final List<GeneratedType> getEnclosedTypes() {
+        return enclosedTypes;
+    }
+
+    @Override
+    public final List<Enumeration> getEnumerations() {
+        return enumerations;
+    }
+
+    @Override
+    public final List<Constant> getConstantDefinitions() {
+        return constants;
+    }
+
+    @Override
+    public final List<MethodSignature> getMethodDefinitions() {
+        return methodSignatures;
+    }
+
+    @Override
+    public final List<GeneratedProperty> getProperties() {
+        return properties;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("GeneratedType [packageName=");
+        builder.append(getPackageName());
+        builder.append(", name=");
+        builder.append(getName());
+        if (parent != null) {
+            builder.append(", parent=");
+            builder.append(parent.getFullyQualifiedName());
+        } else {
+            builder.append(", parent=null");
+        }
+        builder.append(", comment=");
+        builder.append(comment);
+        builder.append(", annotations=");
+        builder.append(annotations);
+        builder.append(", enclosedTypes=");
+        builder.append(enclosedTypes);
+        builder.append(", enumerations=");
+        builder.append(enumerations);
+        builder.append(", constants=");
+        builder.append(constants);
+        builder.append(", methodSignatures=");
+        builder.append(methodSignatures);
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractGeneratedTypeBuilder.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractGeneratedTypeBuilder.java
new file mode 100644 (file)
index 0000000..3c82dea
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import com.google.common.base.Preconditions;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.yangtools.binding.generator.util.AbstractBaseType;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.util.LazyCollections;
+
+abstract class AbstractGeneratedTypeBuilder<T extends GeneratedTypeBuilderBase<T>> extends AbstractBaseType implements GeneratedTypeBuilderBase<T> {
+
+    private List<AnnotationTypeBuilder> annotationBuilders = Collections.emptyList();
+    private List<Type> implementsTypes = Collections.emptyList();
+    private List<EnumBuilder> enumDefinitions = Collections.emptyList();
+    private List<Constant> constants = Collections.emptyList();
+    private List<MethodSignatureBuilder> methodDefinitions = Collections.emptyList();
+    private final List<GeneratedTypeBuilder> enclosedTypes = Collections.emptyList();
+    private List<GeneratedTOBuilder> enclosedTransferObjects = Collections.emptyList();
+    private List<GeneratedPropertyBuilder> properties = Collections.emptyList();
+    private String comment = "";
+    private boolean isAbstract;
+
+    protected AbstractGeneratedTypeBuilder(final String packageName, final String name) {
+        super(packageName, name);
+    }
+
+    protected String getComment() {
+        return comment;
+    }
+
+    protected List<AnnotationTypeBuilder> getAnnotations() {
+        return annotationBuilders;
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return isAbstract;
+    }
+
+    @Override
+    public List<Type> getImplementsTypes() {
+        return implementsTypes;
+    }
+
+    protected List<EnumBuilder> getEnumerations() {
+        return enumDefinitions;
+    }
+
+    protected List<Constant> getConstants() {
+        return constants;
+    }
+
+    @Override
+    public List<MethodSignatureBuilder> getMethodDefinitions() {
+        return methodDefinitions;
+    }
+
+    protected List<GeneratedTypeBuilder> getEnclosedTypes() {
+        return enclosedTypes;
+    }
+
+    protected List<GeneratedTOBuilder> getEnclosedTransferObjects() {
+        return enclosedTransferObjects;
+    }
+
+    protected abstract T thisInstance();
+
+    @Override
+    public GeneratedTOBuilder addEnclosingTransferObject(final String name) {
+        Preconditions.checkArgument(name != null, "Name for Enclosing Generated Transfer Object cannot be null!");
+        GeneratedTOBuilder builder = new GeneratedTOBuilderImpl(getFullyQualifiedName(), name);
+
+        Preconditions.checkArgument(!enclosedTransferObjects.contains(builder), "This generated type already contains equal enclosing transfer object.");
+        enclosedTransferObjects = LazyCollections.lazyAdd(enclosedTransferObjects, builder);
+        return builder;
+    }
+
+    @Override
+    public T addEnclosingTransferObject(final GeneratedTOBuilder genTOBuilder) {
+        Preconditions.checkArgument(genTOBuilder != null, "Parameter genTOBuilder cannot be null!");
+        Preconditions.checkArgument(!enclosedTransferObjects.contains(genTOBuilder), "This generated type already contains equal enclosing transfer object.");
+        enclosedTransferObjects = LazyCollections.lazyAdd(enclosedTransferObjects, genTOBuilder);
+        return thisInstance();
+    }
+
+    @Override
+    public T addComment(final String comment) {
+        this.comment = comment;
+        return thisInstance();
+    }
+
+    @Override
+    public AnnotationTypeBuilder addAnnotation(final String packageName, final String name) {
+        Preconditions.checkArgument(packageName != null, "Package Name for Annotation Type cannot be null!");
+        Preconditions.checkArgument(name != null, "Name of Annotation Type cannot be null!");
+
+        final AnnotationTypeBuilder builder = new AnnotationTypeBuilderImpl(packageName, name);
+
+        Preconditions.checkArgument(!annotationBuilders.contains(builder), "This generated type already contains equal annotation.");
+        annotationBuilders = LazyCollections.lazyAdd(annotationBuilders, builder);
+        return builder;
+    }
+
+    @Override
+    public T setAbstract(final boolean isAbstract) {
+        this.isAbstract = isAbstract;
+        return thisInstance();
+    }
+
+    @Override
+    public T addImplementsType(final Type genType) {
+        Preconditions.checkArgument(genType != null, "Type cannot be null");
+        Preconditions.checkArgument(!implementsTypes.contains(genType), "This generated type already contains equal implements type.");
+        implementsTypes = LazyCollections.lazyAdd(implementsTypes, genType);
+        return thisInstance();
+    }
+
+    @Override
+    public Constant addConstant(final Type type, final String name, final Object value) {
+        Preconditions.checkArgument(type != null, "Returning Type for Constant cannot be null!");
+        Preconditions.checkArgument(name != null, "Name of constant cannot be null!");
+        Preconditions.checkArgument(!containsConstant(name), "This generated type already contains constant with the same name.");
+
+        final Constant constant = new ConstantImpl(this, type, name, value);
+        constants = LazyCollections.lazyAdd(constants, constant);
+        return constant;
+    }
+
+    public boolean containsConstant(final String name) {
+        Preconditions.checkArgument(name != null, "Parameter name can't be null");
+        for (Constant constant : constants) {
+            if (name.equals(constant.getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public EnumBuilder addEnumeration(final String name) {
+        Preconditions.checkArgument(name != null, "Name of enumeration cannot be null!");
+        final EnumBuilder builder = new EnumerationBuilderImpl(getFullyQualifiedName(), name);
+
+        Preconditions.checkArgument(!enumDefinitions.contains(builder), "This generated type already contains equal enumeration.");
+        enumDefinitions = LazyCollections.lazyAdd(enumDefinitions, builder);
+        return builder;
+    }
+
+    @Override
+    public MethodSignatureBuilder addMethod(final String name) {
+        Preconditions.checkArgument(name != null, "Name of method cannot be null!");
+        final MethodSignatureBuilder builder = new MethodSignatureBuilderImpl(name);
+        builder.setAccessModifier(AccessModifier.PUBLIC);
+        builder.setAbstract(true);
+        methodDefinitions = LazyCollections.lazyAdd(methodDefinitions, builder);
+        return builder;
+    }
+
+    @Override
+    public boolean containsMethod(final String name) {
+        Preconditions.checkArgument(name != null, "Parameter name can't be null");
+        for (MethodSignatureBuilder methodDefinition : methodDefinitions) {
+            if (name.equals(methodDefinition.getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public GeneratedPropertyBuilder addProperty(final String name) {
+        Preconditions.checkArgument(name != null, "Parameter name can't be null");
+        Preconditions.checkArgument(!containsProperty(name), "This generated type already contains property with the same name.");
+
+        final GeneratedPropertyBuilder builder = new GeneratedPropertyBuilderImpl(name);
+        builder.setAccessModifier(AccessModifier.PUBLIC);
+        properties = LazyCollections.lazyAdd(properties, builder);
+        return builder;
+    }
+
+    @Override
+    public boolean containsProperty(final String name) {
+        Preconditions.checkArgument(name != null, "Parameter name can't be null");
+        for (GeneratedPropertyBuilder property : properties) {
+            if (name.equals(property.getName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result + ((getPackageName() == null) ? 0 : getPackageName().hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        AbstractGeneratedTypeBuilder<?> other = (AbstractGeneratedTypeBuilder<?>) obj;
+        if (getName() == null) {
+            if (other.getName() != null) {
+                return false;
+            }
+        } else if (!getName().equals(other.getName())) {
+            return false;
+        }
+        if (getPackageName() == null) {
+            if (other.getPackageName() != null) {
+                return false;
+            }
+        } else if (!getPackageName().equals(other.getPackageName())) {
+            return false;
+        }
+        return true;
+    }
+
+    public Type getParent() {
+        return null;
+    }
+
+    @Override
+    public List<GeneratedPropertyBuilder> getProperties() {
+        return properties;
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractTypeMember.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractTypeMember.java
new file mode 100644 (file)
index 0000000..18798fa
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.TypeMember;
+
+abstract class AbstractTypeMember implements TypeMember {
+
+    private final String name;
+    private final String comment;
+    private final Type definingType;
+    private final Type returnType;
+    private final List<AnnotationType> annotations;
+    private final boolean isFinal;
+    private final boolean isStatic;
+    private final AccessModifier accessModifier;
+
+    protected AbstractTypeMember(final Type definingType, final String name,  final List<AnnotationType> annotations,
+            final String comment, final AccessModifier accessModifier, final Type returnType,
+            final boolean isFinal, final boolean isStatic) {
+        super();
+        this.definingType = definingType;
+        this.name = name;
+        this.annotations = annotations;
+        this.comment = comment;
+        this.accessModifier = accessModifier;
+        this.returnType = returnType;
+        this.isFinal = isFinal;
+        this.isStatic = isStatic;
+    }
+
+    @Override
+    public List<AnnotationType> getAnnotations() {
+        return annotations;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public String getComment() {
+        return comment;
+    }
+
+    @Override
+    public Type getDefiningType() {
+        return definingType;
+    }
+
+    @Override
+    public AccessModifier getAccessModifier() {
+        return accessModifier;
+    }
+
+    @Override
+    public Type getReturnType() {
+        return returnType;
+    }
+
+    @Override
+    public boolean isFinal() {
+        return isFinal;
+    }
+
+    @Override
+    public boolean isStatic() {
+        return isStatic;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result
+                + ((getReturnType() == null) ? 0 : getReturnType().hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        AbstractTypeMember other = (AbstractTypeMember) obj;
+        if (getName() == null) {
+            if (other.getName() != null) {
+                return false;
+            }
+        } else if (!getName().equals(other.getName())) {
+            return false;
+        }
+        if (getReturnType() == null) {
+            if (other.getReturnType() != null) {
+                return false;
+            }
+        } else if (!getReturnType().equals(other.getReturnType())) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("MethodSignatureImpl [name=");
+        builder.append(getName());
+        builder.append(", comment=");
+        builder.append(getComment());
+        if (getDefiningType() != null) {
+            builder.append(", definingType=");
+            builder.append(getDefiningType().getPackageName());
+            builder.append(".");
+            builder.append(getDefiningType().getName());
+        } else {
+            builder.append(", definingType= null");
+        }
+        builder.append(", returnType=");
+        builder.append(getReturnType());
+        builder.append(", annotations=");
+        builder.append(getAnnotations());
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractTypeMemberBuilder.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractTypeMemberBuilder.java
new file mode 100644 (file)
index 0000000..849df26
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.TypeMemberBuilder;
+import org.opendaylight.yangtools.util.LazyCollections;
+
+abstract class AbstractTypeMemberBuilder<T extends TypeMemberBuilder<T>> implements TypeMemberBuilder<T> {
+    private final String name;
+    private Type returnType;
+    private List<AnnotationTypeBuilder> annotationBuilders = Collections.emptyList();
+    private String comment = "";
+    private boolean isFinal;
+    private boolean isStatic;
+    private AccessModifier accessModifier;
+
+    public AbstractTypeMemberBuilder(final String name) {
+        this.name = name;
+    }
+
+    @Override
+    public AnnotationTypeBuilder addAnnotation(final String packageName, final String name) {
+        Preconditions.checkArgument(packageName != null, "Annotation Type cannot have package name null!");
+        Preconditions.checkArgument(name != null, "Annotation Type cannot have name as null!");
+
+        final AnnotationTypeBuilder builder = new AnnotationTypeBuilderImpl(packageName, name);
+        annotationBuilders = LazyCollections.lazyAdd(annotationBuilders, builder);
+        return builder;
+    }
+
+    protected Type getReturnType() {
+        return returnType;
+    }
+
+    protected Iterable<AnnotationTypeBuilder> getAnnotationBuilders() {
+        return annotationBuilders;
+    }
+
+    protected String getComment() {
+        return comment;
+    }
+
+    protected boolean isFinal() {
+        return isFinal;
+    }
+
+    protected boolean isStatic() {
+        return isStatic;
+    }
+
+    @Override
+    public AccessModifier getAccessModifier() {
+        return accessModifier;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    protected abstract T thisInstance();
+
+    @Override
+    public T setReturnType(final Type returnType) {
+        Preconditions.checkArgument(returnType != null, "Return Type of member cannot be null!");
+        this.returnType = returnType;
+        return thisInstance();
+    }
+
+    @Override
+    public T setAccessModifier(final AccessModifier modifier) {
+        Preconditions.checkArgument(modifier != null, "Access Modifier for member type cannot be null!");
+        this.accessModifier = modifier;
+        return thisInstance();
+    }
+
+    @Override
+    public T setComment(final String comment) {
+        if (comment == null) {
+            this.comment = "";
+        }
+        this.comment = comment;
+        return thisInstance();
+    }
+
+    @Override
+    public T setFinal(final boolean isFinal) {
+        this.isFinal = isFinal;
+        return thisInstance();
+    }
+
+    @Override
+    public T setStatic(final boolean isStatic) {
+        this.isStatic = isStatic;
+        return thisInstance();
+    }
+
+    protected List<AnnotationType> toAnnotationTypes() {
+        final List<AnnotationType> annotations = new ArrayList<>();
+        for (final AnnotationTypeBuilder annotBuilder : getAnnotationBuilders()) {
+            if (annotBuilder != null) {
+                annotations.add(annotBuilder.toInstance());
+            }
+        }
+
+        return ImmutableList.copyOf(annotations);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result
+                + ((getReturnType() == null) ? 0 : getReturnType().hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        AbstractTypeMemberBuilder<?> other = (AbstractTypeMemberBuilder<?>) obj;
+        if (getName() == null) {
+            if (other.getName() != null) {
+                return false;
+            }
+        } else if (!getName().equals(other.getName())) {
+            return false;
+        }
+        if (getReturnType() == null) {
+            if (other.getReturnType() != null) {
+                return false;
+            }
+        } else if (!getReturnType().equals(other.getReturnType())) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("GeneratedPropertyImpl [name=");
+        builder.append(getName());
+        builder.append(", annotations=");
+        builder.append(getAnnotationBuilders());
+        builder.append(", comment=");
+        builder.append(getComment());
+        builder.append(", returnType=");
+        builder.append(getReturnType());
+        builder.append(", isFinal=");
+        builder.append(isFinal());
+        builder.append(", modifier=");
+        builder.append(getAccessModifier());
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AnnotationTypeBuilderImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AnnotationTypeBuilderImpl.java
new file mode 100644 (file)
index 0000000..df546ed
--- /dev/null
@@ -0,0 +1,343 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import com.google.common.collect.ImmutableList;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.yangtools.binding.generator.util.AbstractBaseType;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
+import org.opendaylight.yangtools.util.LazyCollections;
+
+final class AnnotationTypeBuilderImpl extends AbstractBaseType implements AnnotationTypeBuilder {
+
+    private final String packageName;
+    private final String name;
+    private List<AnnotationTypeBuilder> annotationBuilders = Collections.emptyList();
+    private List<AnnotationType.Parameter> parameters = Collections.emptyList();
+
+    public AnnotationTypeBuilderImpl(final String packageName, final String name) {
+        super(packageName, name);
+        this.packageName = packageName;
+        this.name = name;
+    }
+
+    @Override
+    public AnnotationTypeBuilder addAnnotation(final String packageName, final String name) {
+        if (packageName != null && name != null) {
+            final AnnotationTypeBuilder builder = new AnnotationTypeBuilderImpl(packageName, name);
+            if (!annotationBuilders.contains(builder)) {
+                annotationBuilders = LazyCollections.lazyAdd(annotationBuilders, builder);
+                return builder;
+            }
+        }
+        return null;
+    }
+
+    private boolean addParameter(final ParameterImpl param) {
+        if (!parameters.contains(param)) {
+            parameters = LazyCollections.lazyAdd(parameters, param);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean addParameter(final String paramName, final String value) {
+        if (paramName != null && value != null) {
+            final ParameterImpl param = new ParameterImpl(paramName, value);
+            return addParameter(param);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean addParameters(final String paramName, final List<String> values) {
+        if (paramName != null && values != null) {
+            final ParameterImpl param = new ParameterImpl(paramName, values);
+            return addParameter(param);
+        }
+        return false;
+    }
+
+    @Override
+    public AnnotationType toInstance() {
+        return new AnnotationTypeImpl(packageName, name, annotationBuilders, parameters);
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result
+                + ((packageName == null) ? 0 : packageName.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        AnnotationTypeBuilderImpl other = (AnnotationTypeBuilderImpl) obj;
+        if (name == null) {
+            if (other.name != null) {
+                return false;
+            }
+        } else if (!name.equals(other.name)) {
+            return false;
+        }
+        if (packageName == null) {
+            if (other.packageName != null) {
+                return false;
+            }
+        } else if (!packageName.equals(other.packageName)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("AnnotationTypeBuilder [packageName=");
+        builder.append(packageName);
+        builder.append(", name=");
+        builder.append(name);
+        builder.append(", annotationBuilders=");
+        builder.append(annotationBuilders);
+        builder.append(", parameters=");
+        builder.append(parameters);
+        builder.append("]");
+        return builder.toString();
+    }
+
+    private static final class AnnotationTypeImpl implements AnnotationType {
+
+        private final String packageName;
+        private final String name;
+        private final List<AnnotationType> annotations;
+        private final List<AnnotationType.Parameter> parameters;
+        private final List<String> paramNames;
+
+        public AnnotationTypeImpl(final String packageName, final String name,
+                final List<AnnotationTypeBuilder> annotationBuilders,
+                final List<AnnotationType.Parameter> parameters) {
+            super();
+            this.packageName = packageName;
+            this.name = name;
+
+            final List<AnnotationType> a = new ArrayList<>();
+            for (final AnnotationTypeBuilder builder : annotationBuilders) {
+                a.add(builder.toInstance());
+            }
+            this.annotations = ImmutableList.copyOf(a);
+
+            final List<String> p = new ArrayList<>();
+            for (final AnnotationType.Parameter parameter : parameters) {
+                p.add(parameter.getName());
+            }
+            this.paramNames = ImmutableList.copyOf(p);
+
+            this.parameters = parameters.isEmpty() ? Collections.<AnnotationType.Parameter>emptyList()
+                    : Collections.unmodifiableList(parameters);
+        }
+
+        @Override
+        public String getPackageName() {
+            return packageName;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String getFullyQualifiedName() {
+            return packageName + "." + name;
+        }
+
+        @Override
+        public List<AnnotationType> getAnnotations() {
+            return annotations;
+        }
+
+        @Override
+        public Parameter getParameter(final String paramName) {
+            if (paramName != null) {
+                for (final AnnotationType.Parameter parameter : parameters) {
+                    if (parameter.getName().equals(paramName)) {
+                        return parameter;
+                    }
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public List<Parameter> getParameters() {
+            return parameters;
+        }
+
+        @Override
+        public List<String> getParameterNames() {
+            return paramNames;
+        }
+
+        @Override
+        public boolean containsParameters() {
+            return !parameters.isEmpty();
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((name == null) ? 0 : name.hashCode());
+            result = prime * result
+                    + ((packageName == null) ? 0 : packageName.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(final Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            AnnotationTypeImpl other = (AnnotationTypeImpl) obj;
+            if (name == null) {
+                if (other.name != null) {
+                    return false;
+                }
+            } else if (!name.equals(other.name)) {
+                return false;
+            }
+            if (packageName == null) {
+                if (other.packageName != null) {
+                    return false;
+                }
+            } else if (!packageName.equals(other.packageName)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("AnnotationType [packageName=");
+            builder.append(packageName);
+            builder.append(", name=");
+            builder.append(name);
+            builder.append(", annotations=");
+            builder.append(annotations);
+            builder.append(", parameters=");
+            builder.append(parameters);
+            builder.append("]");
+            return builder.toString();
+        }
+    }
+
+    private static final class ParameterImpl implements AnnotationType.Parameter {
+
+        private final String name;
+        private final String value;
+        private final List<String> values;
+
+        public ParameterImpl(final String name, final String value) {
+            super();
+            this.name = name;
+            this.value = value;
+            this.values = Collections.emptyList();
+        }
+
+        public ParameterImpl(final String name, final List<String> values) {
+            super();
+            this.name = name;
+            this.values = values;
+            this.value = null;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String getValue() {
+            return value;
+        }
+
+        @Override
+        public List<String> getValues() {
+            return values;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((name == null) ? 0 : name.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(final Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            ParameterImpl other = (ParameterImpl) obj;
+            if (name == null) {
+                if (other.name != null) {
+                    return false;
+                }
+            } else if (!name.equals(other.name)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("ParameterImpl [name=");
+            builder.append(name);
+            builder.append(", value=");
+            builder.append(value);
+            builder.append(", values=");
+            builder.append(values);
+            builder.append("]");
+            return builder.toString();
+        }
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/ConstantImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/ConstantImpl.java
new file mode 100644 (file)
index 0000000..0bccace
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+final class ConstantImpl implements Constant {
+
+    private final Type definingType;
+    private final Type type;
+    private final String name;
+    private final Object value;
+
+    public ConstantImpl(final Type definingType, final Type type, final String name, final Object value) {
+        super();
+        this.definingType = definingType;
+        this.type = type;
+        this.name = name;
+        this.value = value;
+    }
+
+    @Override
+    public Type getDefiningType() {
+        return definingType;
+    }
+
+    @Override
+    public Type getType() {
+        return type;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public Object getValue() {
+        return value;
+    }
+
+    @Override
+    public String toFormattedString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(type);
+        builder.append(" ");
+        builder.append(name);
+        builder.append(" ");
+        builder.append(value);
+        return builder.toString();
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        ConstantImpl other = (ConstantImpl) obj;
+        if (name == null) {
+            if (other.name != null) {
+                return false;
+            }
+        } else if (!name.equals(other.name)) {
+            return false;
+        }
+        if (type == null) {
+            if (other.type != null) {
+                return false;
+            }
+        } else if (!type.equals(other.type)) {
+            return false;
+        }
+        if (value == null) {
+            if (other.value != null) {
+                return false;
+            }
+        } else if (!value.equals(other.value)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("Constant [type=");
+        builder.append(type);
+        builder.append(", name=");
+        builder.append(name);
+        builder.append(", value=");
+        builder.append(value);
+        if (definingType != null) {
+            builder.append(", definingType=");
+            builder.append(definingType.getPackageName());
+            builder.append(".");
+            builder.append(definingType.getName());
+        } else {
+            builder.append(", definingType= null");
+        }
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/EnumerationBuilderImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/EnumerationBuilderImpl.java
new file mode 100644 (file)
index 0000000..cec633a
--- /dev/null
@@ -0,0 +1,398 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import com.google.common.collect.ImmutableList;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.opendaylight.yangtools.binding.generator.util.AbstractBaseType;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration.Pair;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
+import org.opendaylight.yangtools.util.LazyCollections;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
+
+public final class EnumerationBuilderImpl extends AbstractBaseType implements EnumBuilder {
+    private final String packageName;
+    private final String name;
+    private List<Enumeration.Pair> values = Collections.emptyList();
+    private List<AnnotationTypeBuilder> annotationBuilders = Collections.emptyList();
+    private List<Pair> unmodifiableValues  = Collections.emptyList();
+    private String description;
+    private String reference;
+    private String moduleName;
+    private Iterable<QName> schemaPath;
+
+    public EnumerationBuilderImpl(final String packageName, final String name) {
+        super(packageName, name);
+        this.packageName = packageName;
+        this.name = name;
+    }
+
+    public void setReference(final String reference) {
+        this.reference = reference;
+    }
+
+    public void setModuleName(final String moduleName) {
+        this.moduleName = moduleName;
+    }
+
+    public void setSchemaPath(final Iterable<QName> schemaPath) {
+        this.schemaPath = schemaPath;
+    }
+
+    @Override
+    public void setDescription(String description) {
+        this.description = description;
+
+    }
+
+    @Override
+    public AnnotationTypeBuilder addAnnotation(final String packageName, final String name) {
+        if (packageName != null && name != null) {
+            final AnnotationTypeBuilder builder = new AnnotationTypeBuilderImpl(packageName, name);
+            if (!annotationBuilders.contains(builder)) {
+                annotationBuilders = LazyCollections.lazyAdd(annotationBuilders, builder);
+                return builder;
+            }
+        }
+        return null;
+    }
+
+    @Override
+    public void addValue(final String name, final Integer value, final String description) {
+        final EnumPairImpl p = new EnumPairImpl(name, value, description);
+        values = LazyCollections.lazyAdd(values, p);
+        unmodifiableValues = Collections.unmodifiableList(values);
+    }
+
+    @Override
+    public Enumeration toInstance(final Type definingType) {
+        return new EnumerationImpl(definingType, annotationBuilders, packageName, name, unmodifiableValues,
+                description, reference, moduleName, schemaPath);
+    }
+
+    /*
+     * (non-Javadoc)
+     *
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("EnumerationBuilderImpl [packageName=");
+        builder.append(packageName);
+        builder.append(", name=");
+        builder.append(name);
+        builder.append(", values=");
+        builder.append(values);
+        builder.append("]");
+        return builder.toString();
+    }
+
+    @Override
+    public void updateEnumPairsFromEnumTypeDef(final EnumTypeDefinition enumTypeDef) {
+        final List<EnumPair> enums = enumTypeDef.getValues();
+        if (enums != null) {
+            int listIndex = 0;
+            for (final EnumPair enumPair : enums) {
+                if (enumPair != null) {
+                    final String enumPairName = BindingMapping.getClassName(enumPair.getName());
+                    Integer enumPairValue = enumPair.getValue();
+
+                    if (enumPairValue == null) {
+                        enumPairValue = listIndex;
+                    }
+                    else {
+                        listIndex = enumPairValue;
+                    }
+
+                    this.addValue(enumPairName, enumPairValue, enumPair.getDescription());
+                    listIndex++;
+                }
+            }
+        }
+
+    }
+
+    private static final class EnumPairImpl implements Enumeration.Pair {
+
+        private final String name;
+        private final Integer value;
+        private final String description;
+
+        public EnumPairImpl(final String name, final Integer value, final String description) {
+            super();
+            this.name = name;
+            this.value = value;
+            this.description = description;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public Integer getValue() {
+            return value;
+        }
+
+        /*
+         * (non-Javadoc)
+         *
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((name == null) ? 0 : name.hashCode());
+            result = prime * result + ((value == null) ? 0 : value.hashCode());
+            return result;
+        }
+
+        /*
+         * (non-Javadoc)
+         *
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(final Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            EnumPairImpl other = (EnumPairImpl) obj;
+            if (name == null) {
+                if (other.name != null) {
+                    return false;
+                }
+            } else if (!name.equals(other.name)) {
+                return false;
+            }
+            if (value == null) {
+                if (other.value != null) {
+                    return false;
+                }
+            } else if (!value.equals(other.value)) {
+                return false;
+            }
+            return true;
+        }
+
+        /*
+         * (non-Javadoc)
+         *
+         * @see java.lang.Object#toString()
+         */
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("EnumPair [name=");
+            builder.append(name);
+            builder.append(", value=");
+            builder.append(value);
+            builder.append("]");
+            return builder.toString();
+        }
+
+        @Override
+        public String getDescription() {
+            return description;
+        }
+
+        @Override
+        public String getReference() {
+            return null;
+        }
+
+        @Override
+        public Status getStatus() {
+            // TODO Auto-generated method stub
+            return null;
+        }
+
+    }
+
+    private static final class EnumerationImpl extends AbstractBaseType implements Enumeration {
+
+        private final Type definingType;
+        private final String description;
+        private final String reference;
+        private final String moduleName;
+        private final Iterable<QName> schemaPath;
+        private final List<Pair> values;
+        private final List<AnnotationType> annotations;
+
+        public EnumerationImpl(final Type definingType, final List<AnnotationTypeBuilder> annotationBuilders,
+                final String packageName, final String name, final List<Pair> values, final String description,
+                final String reference, final String moduleName, final Iterable<QName> schemaPath) {
+            super(packageName, name);
+            this.definingType = definingType;
+            this.values = values;
+            this.description = description;
+            this.moduleName = moduleName;
+            this.schemaPath = schemaPath;
+            this.reference = reference;
+
+            final ArrayList<AnnotationType> a = new ArrayList<>();
+            for (final AnnotationTypeBuilder builder : annotationBuilders) {
+                a.add(builder.toInstance());
+            }
+            this.annotations = ImmutableList.copyOf(a);
+        }
+
+        @Override
+        public Type getParentType() {
+            return definingType;
+        }
+
+        @Override
+        public List<Pair> getValues() {
+            return values;
+        }
+
+        @Override
+        public List<AnnotationType> getAnnotations() {
+            return annotations;
+        }
+
+        @Override
+        public String toFormattedString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("public enum");
+            builder.append(" ");
+            builder.append(getName());
+            builder.append(" {");
+            builder.append("\n");
+
+            int i = 0;
+            for (final Enumeration.Pair valPair : values) {
+                builder.append("\t");
+                builder.append(" ");
+                builder.append(valPair.getName());
+                builder.append(" (");
+                builder.append(valPair.getValue());
+
+                if (i == (values.size() - 1)) {
+                    builder.append(" );");
+                } else {
+                    builder.append(" ),");
+                }
+                ++i;
+            }
+            builder.append("\n}");
+            return builder.toString();
+        }
+
+        /*
+         * (non-Javadoc)
+         *
+         * @see java.lang.Object#toString()
+         */
+        @Override
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("Enumeration [packageName=");
+            builder.append(getPackageName());
+            if (definingType != null) {
+                builder.append(", definingType=");
+                builder.append(definingType.getPackageName());
+                builder.append(".");
+                builder.append(definingType.getName());
+            } else {
+                builder.append(", definingType= null");
+            }
+            builder.append(", name=");
+            builder.append(getName());
+            builder.append(", values=");
+            builder.append(values);
+            builder.append("]");
+            return builder.toString();
+        }
+
+        @Override
+        public String getComment() {
+            return null;
+        }
+
+        @Override
+        public boolean isAbstract() {
+            return false;
+        }
+
+        @Override
+        public List<Type> getImplements() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<GeneratedType> getEnclosedTypes() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<Enumeration> getEnumerations() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<Constant> getConstantDefinitions() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<MethodSignature> getMethodDefinitions() {
+            // TODO Auto-generated method stub
+            return Collections.emptyList();
+        }
+
+        @Override
+        public List<GeneratedProperty> getProperties() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public String getDescription() {
+            return description;
+        }
+
+        @Override
+        public String getReference() {
+            return reference;
+        }
+
+        @Override
+        public Iterable<QName> getSchemaPath() {
+            return schemaPath;
+        }
+
+        @Override
+        public String getModuleName() {
+            return moduleName;
+        }
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyBuilderImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyBuilderImpl.java
new file mode 100644 (file)
index 0000000..e4c8019
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+
+public final class GeneratedPropertyBuilderImpl extends AbstractTypeMemberBuilder<GeneratedPropertyBuilder> implements GeneratedPropertyBuilder {
+    private String value;
+    private boolean isReadOnly;
+
+    public GeneratedPropertyBuilderImpl(String name) {
+        super(name);
+        this.isReadOnly = true;
+    }
+
+    @Override
+    public GeneratedPropertyBuilderImpl setValue(String value) {
+        this.value = value;
+        return this;
+    }
+
+    @Override
+    public GeneratedPropertyBuilderImpl setReadOnly(boolean isReadOnly) {
+        this.isReadOnly = isReadOnly;
+        return this;
+    }
+
+    @Override
+    protected GeneratedPropertyBuilderImpl thisInstance() {
+        return this;
+    }
+
+    @Override
+    public GeneratedProperty toInstance(Type definingType) {
+        final List<AnnotationType> annotations = toAnnotationTypes();
+        return new GeneratedPropertyImpl(definingType, getName(), annotations, getComment(), getAccessModifier(),
+                getReturnType(), isFinal(), isStatic(), isReadOnly, value);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("GeneratedPropertyImpl [name=");
+        builder.append(getName());
+        builder.append(", annotations=");
+        builder.append(getAnnotationBuilders());
+        builder.append(", comment=");
+        builder.append(getComment());
+        builder.append(", returnType=");
+        builder.append(getReturnType());
+        builder.append(", isFinal=");
+        builder.append(isFinal());
+        builder.append(", isReadOnly=");
+        builder.append(isReadOnly);
+        builder.append(", modifier=");
+        builder.append(getAccessModifier());
+        builder.append("]");
+        return builder.toString();
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyImpl.java
new file mode 100644 (file)
index 0000000..2abe75c
--- /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.binding.generator.util.generated.type.builder;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+final class GeneratedPropertyImpl extends AbstractTypeMember implements GeneratedProperty {
+    private String value;
+    private boolean isReadOnly;
+
+    public GeneratedPropertyImpl(Type definingType, String name, List<AnnotationType> annotations, String comment,
+                                 AccessModifier accessModifier, Type returnType, boolean isFinal, boolean isStatic, boolean isReadOnly, String value) {
+        super(definingType, name, annotations, comment, accessModifier, returnType, isFinal, isStatic);
+        this.value = value;
+        this.isReadOnly = isReadOnly;
+    }
+
+    @Override
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public boolean isReadOnly() {
+        return isReadOnly;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("GeneratedPropertyImpl [name=");
+        builder.append(getName());
+        builder.append(", annotations=");
+        builder.append(getAnnotations());
+        builder.append(", comment=");
+        builder.append(getComment());
+        if (getDefiningType() != null) {
+            builder.append(", parent=");
+            builder.append(getDefiningType().getPackageName());
+            builder.append(".");
+            builder.append(getDefiningType().getName());
+        } else {
+            builder.append(", parent=null");
+        }
+        builder.append(", returnType=");
+        builder.append(getReturnType());
+        builder.append(", isFinal=");
+        builder.append(isFinal());
+        builder.append(", isReadOnly=");
+        builder.append(isReadOnly);
+        builder.append(", modifier=");
+        builder.append(getAccessModifier());
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderImpl.java
new file mode 100644 (file)
index 0000000..c340d92
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.List;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.util.LazyCollections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+public final class GeneratedTOBuilderImpl extends AbstractGeneratedTypeBuilder<GeneratedTOBuilder> implements GeneratedTOBuilder {
+
+    private GeneratedTransferObject extendsType;
+    private List<GeneratedPropertyBuilder> equalsProperties = Collections.emptyList();
+    private List<GeneratedPropertyBuilder> hashProperties = Collections.emptyList();
+    private List<GeneratedPropertyBuilder> toStringProperties = Collections.emptyList();
+    private boolean isTypedef = false;
+    private boolean isUnionType = false;
+    private boolean isUnionTypeBuilder = false;
+    private TypeDefinition<?> baseType = null;
+    private Restrictions restrictions;
+    private GeneratedPropertyBuilder SUID;
+    private String reference;
+    private String description;
+    private String moduleName;
+    private Iterable<QName> schemaPath;
+
+    public GeneratedTOBuilderImpl(final String packageName, final String name) {
+        super(packageName, name);
+        setAbstract(false);
+    }
+
+    @Override
+    public GeneratedTOBuilder setExtendsType(final GeneratedTransferObject genTransObj) {
+        Preconditions.checkArgument(genTransObj != null, "Generated Transfer Object cannot be null!");
+        extendsType = genTransObj;
+        return this;
+    }
+
+    /**
+     * Add new Method Signature definition for Generated Type Builder and
+     * returns Method Signature Builder for specifying all Method parameters. <br>
+     * Name of Method cannot be <code>null</code>, if it is <code>null</code>
+     * the method SHOULD throw {@link IllegalArgumentException} <br>
+     * By <i>Default</i> the MethodSignatureBuilder SHOULD be pre-set as
+     * {@link MethodSignatureBuilder#setAbstract(boolean)},
+     * {TypeMemberBuilder#setFinal(boolean)} and
+     * {TypeMemberBuilder#setAccessModifier(boolean)}
+     *
+     * @param name
+     *            Name of Method
+     * @return <code>new</code> instance of Method Signature Builder.
+     */
+    @Override
+    public MethodSignatureBuilder addMethod(final String name) {
+        final MethodSignatureBuilder builder = super.addMethod(name);
+        builder.setAbstract(false);
+        return builder;
+    }
+
+    @Override
+    public GeneratedTOBuilder addEqualsIdentity(final GeneratedPropertyBuilder property) {
+        equalsProperties = LazyCollections.lazyAdd(equalsProperties, property);
+        return this;
+    }
+
+    @Override
+    public GeneratedTOBuilder addHashIdentity(final GeneratedPropertyBuilder property) {
+        hashProperties = LazyCollections.lazyAdd(hashProperties, property);
+        return this;
+    }
+
+    @Override
+    public GeneratedTOBuilder addToStringProperty(final GeneratedPropertyBuilder property) {
+        toStringProperties = LazyCollections.lazyAdd(toStringProperties, property);
+        return this;
+    }
+
+    @Override
+    protected GeneratedTOBuilder thisInstance() {
+        return this;
+    }
+
+    @Override
+    public void setRestrictions(final Restrictions restrictions) {
+        this.restrictions = restrictions;
+    }
+
+    @Override
+    public void setSUID(final GeneratedPropertyBuilder suid) {
+        this.SUID = suid;
+    }
+
+    @Override
+    public GeneratedTransferObject toInstance() {
+        return new GeneratedTransferObjectImpl(this);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("GeneratedTransferObject [packageName=");
+        builder.append(getPackageName());
+        builder.append(", name=");
+        builder.append(getName());
+        builder.append(", comment=");
+        builder.append(getComment());
+        builder.append(", constants=");
+        builder.append(getConstants());
+        builder.append(", enumerations=");
+        builder.append(getEnumerations());
+        builder.append(", equalsProperties=");
+        builder.append(equalsProperties);
+        builder.append(", hashCodeProperties=");
+        builder.append(hashProperties);
+        builder.append(", stringProperties=");
+        builder.append(toStringProperties);
+        builder.append(", annotations=");
+        builder.append(getAnnotations());
+        builder.append(", methods=");
+        builder.append(getMethodDefinitions());
+        builder.append("]");
+        return builder.toString();
+    }
+
+    @Override
+    public void setTypedef(final boolean isTypedef) {
+        this.isTypedef = isTypedef;
+    }
+
+    @Override
+    public void setBaseType(final TypeDefinition<?> typeDef) {
+        this.baseType = typeDef;
+    }
+
+    @Override
+    public void setIsUnion(final boolean isUnion) {
+        this.isUnionType = isUnion;
+    }
+
+    @Override
+    public void setIsUnionBuilder(final boolean isUnionTypeBuilder) {
+        this.isUnionTypeBuilder = isUnionTypeBuilder;
+    }
+
+    @Override
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @Override
+    public void setModuleName(String moduleName) {
+        this.moduleName = moduleName;
+    }
+
+    @Override
+    public void setSchemaPath(Iterable<QName> schemaPath) {
+        this.schemaPath = schemaPath;
+    }
+
+    @Override
+    public void setReference(String reference) {
+        this.reference = reference;
+    }
+
+    private static final class GeneratedTransferObjectImpl extends AbstractGeneratedType implements
+    GeneratedTransferObject {
+
+        private final List<GeneratedProperty> equalsProperties;
+        private final List<GeneratedProperty> hashCodeProperties;
+        private final List<GeneratedProperty> stringProperties;
+        private final GeneratedTransferObject extendsType;
+        private final boolean isTypedef;
+        private final TypeDefinition<?> baseType;
+        private final boolean isUnionType;
+        private final boolean isUnionTypeBuilder;
+        private final Restrictions restrictions;
+        private final GeneratedProperty SUID;
+        private final String reference;
+        private final String description;
+        private final String moduleName;
+        private final Iterable<QName> schemaPath;
+
+        public GeneratedTransferObjectImpl(final GeneratedTOBuilderImpl builder) {
+            super(builder);
+            this.extendsType = builder.extendsType;
+
+            // FIXME: if these fields were guaranteed to be constant, we could perhaps
+            //        cache and reuse them between instances...
+            this.equalsProperties = toUnmodifiableProperties(builder.equalsProperties);
+            this.hashCodeProperties = toUnmodifiableProperties(builder.hashProperties);
+            this.stringProperties = toUnmodifiableProperties(builder.toStringProperties);
+
+            this.isTypedef = builder.isTypedef;
+            this.baseType = builder.baseType;
+            this.isUnionType = builder.isUnionType;
+            this.isUnionTypeBuilder = builder.isUnionTypeBuilder;
+            this.restrictions = builder.restrictions;
+            this.reference = builder.reference;
+            this.description = builder.description;
+            this.moduleName = builder.moduleName;
+            this.schemaPath = builder.schemaPath;
+
+            if (builder.SUID == null) {
+                this.SUID = null;
+            } else {
+                this.SUID = builder.SUID.toInstance(GeneratedTransferObjectImpl.this);
+            }
+        }
+
+        @Override
+        public boolean isTypedef() {
+            return isTypedef;
+        }
+
+        @Override
+        public TypeDefinition<?> getBaseType() {
+            return baseType;
+        }
+
+        @Override
+        public boolean isUnionType() {
+            return isUnionType;
+        }
+
+        @Override
+        public boolean isUnionTypeBuilder() {
+            return isUnionTypeBuilder;
+        }
+
+        @Override
+        public GeneratedTransferObject getSuperType() {
+            return extendsType;
+        }
+
+        @Override
+        public List<GeneratedProperty> getEqualsIdentifiers() {
+            return equalsProperties;
+        }
+
+        @Override
+        public List<GeneratedProperty> getHashCodeIdentifiers() {
+            return hashCodeProperties;
+        }
+
+        @Override
+        public List<GeneratedProperty> getToStringIdentifiers() {
+            return stringProperties;
+        }
+
+        @Override
+        public Restrictions getRestrictions() {
+            return restrictions;
+        }
+
+        @Override
+        public GeneratedProperty getSUID() {
+            return SUID;
+        }
+
+        @Override
+        public String toString() {
+            if (isTypedef) {
+                return serializeTypedef(this);
+            }
+            StringBuilder builder = new StringBuilder();
+            builder.append("GeneratedTransferObject [packageName=");
+            builder.append(getPackageName());
+            builder.append(", name=");
+            builder.append(getName());
+            builder.append(", comment=");
+            builder.append(", annotations=");
+            builder.append(getAnnotations());
+            builder.append(getComment());
+            builder.append(", extends=");
+            builder.append(getSuperType());
+            builder.append(", implements=");
+            builder.append(getImplements());
+            builder.append(", enclosedTypes=");
+            builder.append(getEnclosedTypes());
+            builder.append(", constants=");
+            builder.append(getConstantDefinitions());
+            builder.append(", enumerations=");
+            builder.append(getEnumerations());
+            builder.append(", properties=");
+            builder.append(getProperties());
+            builder.append(", equalsProperties=");
+            builder.append(equalsProperties);
+            builder.append(", hashCodeProperties=");
+            builder.append(hashCodeProperties);
+            builder.append(", stringProperties=");
+            builder.append(stringProperties);
+            builder.append(", methods=");
+            builder.append(getMethodDefinitions());
+            builder.append("]");
+            return builder.toString();
+        }
+
+        public String serializeTypedef(final Type type) {
+            if (type instanceof ParameterizedType) {
+                ParameterizedType parameterizedType = (ParameterizedType) type;
+                StringBuilder sb = new StringBuilder();
+                sb.append(parameterizedType.getRawType().getFullyQualifiedName());
+                sb.append('<');
+                boolean first = true;
+                for (Type parameter : parameterizedType.getActualTypeArguments()) {
+                    if (first) {
+                        first = false;
+                    } else {
+                        sb.append(',');
+                    }
+                    sb.append(serializeTypedef(parameter));
+                }
+                sb.append('>');
+                return sb.toString();
+            } else {
+                return type.getFullyQualifiedName();
+            }
+        }
+
+        @Override
+        public String getDescription() {
+            return description;
+        }
+
+        @Override
+        public String getReference() {
+            return reference;
+        }
+
+        @Override
+        public Iterable<QName> getSchemaPath() {
+            return schemaPath;
+        }
+
+        @Override
+        public String getModuleName() {
+            return moduleName;
+        }
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTypeBuilderImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTypeBuilderImpl.java
new file mode 100644 (file)
index 0000000..92c5629
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public final class GeneratedTypeBuilderImpl extends AbstractGeneratedTypeBuilder<GeneratedTypeBuilder> implements
+        GeneratedTypeBuilder {
+
+    private String description;
+    private String reference;
+    private String moduleName;
+    private Iterable<QName> schemaPath;
+
+    public GeneratedTypeBuilderImpl(final String packageName, final String name) {
+        super(packageName, name);
+        setAbstract(true);
+    }
+
+    @Override
+    public GeneratedType toInstance() {
+        return new GeneratedTypeImpl(this);
+    }
+
+    @Override
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    @Override
+    public void setModuleName(String moduleName) {
+        this.moduleName = moduleName;
+    }
+
+    @Override
+    public void setSchemaPath(Iterable<QName> schemaPath) {
+        this.schemaPath = schemaPath;
+    }
+
+    @Override
+    public void setReference(String reference) {
+        this.reference = reference;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("GeneratedTransferObject [packageName=");
+        builder.append(getPackageName());
+        builder.append(", name=");
+        builder.append(getName());
+        builder.append(", comment=");
+        builder.append(getComment());
+        builder.append(", annotations=");
+        builder.append(getAnnotations());
+        builder.append(", implements=");
+        builder.append(getImplementsTypes());
+        builder.append(", enclosedTypes=");
+        builder.append(getEnclosedTypes());
+        builder.append(", constants=");
+        builder.append(getConstants());
+        builder.append(", enumerations=");
+        builder.append(getEnumerations());
+        builder.append(", properties=");
+        builder.append(", methods=");
+        builder.append(getMethodDefinitions());
+        builder.append("]");
+        return builder.toString();
+    }
+
+    @Override
+    protected GeneratedTypeBuilderImpl thisInstance() {
+        return this;
+    }
+
+    private static final class GeneratedTypeImpl extends AbstractGeneratedType {
+
+        private final String description;
+        private final String reference;
+        private final String moduleName;
+        private final Iterable<QName> schemaPath;
+
+        public GeneratedTypeImpl(GeneratedTypeBuilderImpl builder) {
+            super(builder);
+
+            this.description = builder.description;
+            this.reference = builder.reference;
+            this.moduleName = builder.moduleName;
+            this.schemaPath = builder.schemaPath;
+        }
+
+        @Override
+        public String getDescription() {
+            return description;
+        }
+
+        @Override
+        public String getReference() {
+            return reference;
+        }
+
+        @Override
+        public Iterable<QName> getSchemaPath() {
+            return schemaPath;
+        }
+
+        @Override
+        public String getModuleName() {
+            return moduleName;
+        }
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodParameterImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodParameterImpl.java
new file mode 100644 (file)
index 0000000..4e3b6e1
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature.Parameter;
+
+final class MethodParameterImpl implements Parameter {
+
+    private final String name;
+    private final Type type;
+
+    public MethodParameterImpl(final String name, final Type type) {
+        super();
+        this.name = name;
+        this.type = type;
+    }
+
+    @Override
+    public String getName() {
+        return name;
+    }
+
+    @Override
+    public Type getType() {
+        return type;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#hashCode()
+     */
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        return result;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#equals(java.lang.Object)
+     */
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        MethodParameterImpl other = (MethodParameterImpl) obj;
+        if (name == null) {
+            if (other.name != null) {
+                return false;
+            }
+        } else if (!name.equals(other.name)) {
+            return false;
+        }
+        if (type == null) {
+            if (other.type != null) {
+                return false;
+            }
+        } else if (!type.equals(other.type)) {
+            return false;
+        }
+        return true;
+    }
+
+    /*
+     * (non-Javadoc)
+     * 
+     * @see java.lang.Object#toString()
+     */
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("MethodParameter [name=");
+        builder.append(name);
+        builder.append(", type=");
+        builder.append(type.getPackageName());
+        builder.append(".");
+        builder.append(type.getName());
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureBuilderImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureBuilderImpl.java
new file mode 100644 (file)
index 0000000..ea0ff07
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.util.LazyCollections;
+
+final class MethodSignatureBuilderImpl extends AbstractTypeMemberBuilder<MethodSignatureBuilder> implements MethodSignatureBuilder {
+
+    private List<MethodSignature.Parameter> parameters = Collections.emptyList();
+    private List<MethodSignature.Parameter> unmodifiableParams  = Collections.emptyList();
+    private boolean isAbstract;
+
+    public MethodSignatureBuilderImpl(final String name) {
+        super(name);
+    }
+
+    @Override
+    public MethodSignatureBuilder setAbstract(final boolean isAbstract) {
+        this.isAbstract = isAbstract;
+        return this;
+    }
+
+    @Override
+    public MethodSignatureBuilder addParameter(final Type type, final String name) {
+        parameters = LazyCollections.lazyAdd(parameters, new MethodParameterImpl(name, type));
+        unmodifiableParams = Collections.unmodifiableList(parameters);
+        return this;
+    }
+
+    @Override
+    protected MethodSignatureBuilder thisInstance() {
+        return this;
+    }
+
+    @Override
+    public MethodSignature toInstance(final Type definingType) {
+        final List<AnnotationType> annotations = toAnnotationTypes();
+        return new MethodSignatureImpl(definingType, getName(), annotations, getComment(), getAccessModifier(),
+                getReturnType(), unmodifiableParams, isFinal(), isAbstract, isStatic());
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result + ((parameters == null) ? 0 : parameters.hashCode());
+        result = prime * result + ((getReturnType() == null) ? 0 : getReturnType().hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        MethodSignatureBuilderImpl other = (MethodSignatureBuilderImpl) obj;
+        if (getName() == null) {
+            if (other.getName() != null) {
+                return false;
+            }
+        } else if (!getName().equals(other.getName())) {
+            return false;
+        }
+        if (parameters == null) {
+            if (other.parameters != null) {
+                return false;
+            }
+        } else if (!parameters.equals(other.parameters)) {
+            return false;
+        }
+        if (getReturnType() == null) {
+            if (other.getReturnType() != null) {
+                return false;
+            }
+        } else if (!getReturnType().equals(other.getReturnType())) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("MethodSignatureBuilderImpl [name=");
+        builder.append(getName());
+        builder.append(", returnType=");
+        builder.append(getReturnType());
+        builder.append(", parameters=");
+        builder.append(parameters);
+        builder.append(", annotationBuilders=");
+        builder.append(getAnnotationBuilders());
+        builder.append(", comment=");
+        builder.append(getComment());
+        builder.append("]");
+        return builder.toString();
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureImpl.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureImpl.java
new file mode 100644 (file)
index 0000000..cf0f7ea
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+class MethodSignatureImpl extends AbstractTypeMember implements MethodSignature {
+
+    private final List<Parameter> params;
+    private final boolean isAbstract;
+
+    public MethodSignatureImpl(final Type definingType, final String name,
+            final List<AnnotationType> annotations,
+            final String comment, final AccessModifier accessModifier,
+            final Type returnType, final List<Parameter> params, final boolean isFinal,
+            final boolean isAbstract, final boolean isStatic) {
+        super(definingType, name, annotations, comment, accessModifier, returnType, isFinal, isStatic);
+        this.params = params;
+        this.isAbstract = isAbstract;
+    }
+
+    @Override
+    public boolean isAbstract() {
+        return isAbstract;
+    }
+
+    @Override
+    public List<Parameter> getParameters() {
+        return params;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getName() == null) ? 0 : getName().hashCode());
+        result = prime * result
+                + ((params == null) ? 0 : params.hashCode());
+        result = prime * result
+                + ((getReturnType() == null) ? 0 : getReturnType().hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        MethodSignatureImpl other = (MethodSignatureImpl) obj;
+        if (getName() == null) {
+            if (other.getName() != null) {
+                return false;
+            }
+        } else if (!getName().equals(other.getName())) {
+            return false;
+        }
+        if (params == null) {
+            if (other.params != null) {
+                return false;
+            }
+        } else if (!params.equals(other.params)) {
+            return false;
+        }
+        if (getReturnType() == null) {
+            if (other.getReturnType() != null) {
+                return false;
+            }
+        } else if (!getReturnType().equals(other.getReturnType())) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("MethodSignatureImpl [name=");
+        builder.append(getName());
+        builder.append(", comment=");
+        builder.append(getComment());
+        if (getDefiningType() != null) {
+            builder.append(", definingType=");
+            builder.append(getDefiningType().getPackageName());
+            builder.append(".");
+            builder.append(getDefiningType().getName());
+        } else {
+            builder.append(", definingType= null");
+        }
+        builder.append(", returnType=");
+        builder.append(getReturnType());
+        builder.append(", params=");
+        builder.append(params);
+        builder.append(", annotations=");
+        builder.append(getAnnotations());
+        builder.append("]");
+        return builder.toString();
+    }
+}
diff --git a/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/package-info.java b/code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/package-info.java
new file mode 100644 (file)
index 0000000..2621e2e
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.binding.generator.util;
\ No newline at end of file
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/AbstractBaseTypeTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/AbstractBaseTypeTest.java
new file mode 100644 (file)
index 0000000..ef82041
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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.binding.generator.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class AbstractBaseTypeTest {
+
+    @Rule
+    public ExpectedException expException = ExpectedException.none();
+
+    @Test
+    public void testgetFullyQualifiedName() {
+        AbstractBaseType baseType = new AbstractBaseType("", "");
+        assertTrue(baseType.getFullyQualifiedName().isEmpty());
+    }
+
+    @Test
+    public void testCreateAbstractBaseTypeWithNullPackagename() {
+        expException.expect(IllegalArgumentException.class);
+        expException.expectMessage("Package Name for Generated Type cannot be null!");
+        new AbstractBaseType(null, "Test");
+    }
+
+    @Test
+    public void testCreateAbstractBaseTypeWithNullTypeName() {
+        expException.expect(IllegalArgumentException.class);
+        expException.expectMessage("Name of Generated Type cannot be null!");
+        new AbstractBaseType("org.opendaylight.yangtools.test", null);
+    }
+
+    @Test
+    public void testHashCode() {
+        AbstractBaseType baseType1 = new AbstractBaseType("org.opendaylight.yangtools.test", "Test");
+        AbstractBaseType baseType2 = new AbstractBaseType("org.opendaylight.yangtools.test", "Test2");
+        assertNotEquals(baseType1.hashCode(), baseType2.hashCode());
+    }
+
+    @Test
+    public void testToString() {
+        AbstractBaseType baseType = new AbstractBaseType("org.opendaylight.yangtools.test", "Test");
+        assertTrue(baseType.toString().contains("org.opendaylight.yangtools.test.Test"));
+        baseType = new AbstractBaseType("", "Test");
+        assertTrue(baseType.toString().contains("Test"));
+    }
+
+    @Test
+    public void testEquals() {
+        AbstractBaseType baseType1 = new AbstractBaseType("org.opendaylight.yangtools.test", "Test");
+        AbstractBaseType baseType2 = new AbstractBaseType("org.opendaylight.yangtools.test", "Test2");
+        AbstractBaseType baseType3 = null;
+        AbstractBaseType baseType4 = new AbstractBaseType("org.opendaylight.yangtools.test", "Test");
+        AbstractBaseType baseType5 = new AbstractBaseType("org.opendaylight.yangtools.test1", "Test");
+
+        assertFalse(baseType1.equals(baseType2));
+        assertFalse(baseType1.equals(baseType3));
+        assertTrue(baseType1.equals(baseType4));
+        assertFalse(baseType1.equals(baseType5));
+        assertFalse(baseType1.equals(null));
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtilTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/BindingGeneratorUtilTest.java
new file mode 100644 (file)
index 0000000..91e93ed
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ * 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.binding.generator.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Optional;
+import java.io.File;
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.model.util.BaseConstraints;
+import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
+import org.opendaylight.yangtools.yang.model.util.Decimal64;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType.Builder;
+import org.opendaylight.yangtools.yang.model.util.Int16;
+import org.opendaylight.yangtools.yang.model.util.StringType;
+import org.opendaylight.yangtools.yang.model.util.Uint16;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class BindingGeneratorUtilTest {
+
+    @Rule
+    public ExpectedException expectedEx = ExpectedException.none();
+
+    private static List<File> loadTestResources(String testFile) {
+        final List<File> testModels = new ArrayList<File>();
+        File listModelFile;
+        try {
+            listModelFile = new File(BindingGeneratorUtilTest.class.getResource(testFile).toURI());
+        } catch (URISyntaxException e) {
+            throw new IllegalArgumentException("Failed to load sources from " + testFile);
+        }
+        testModels.add(listModelFile);
+        return testModels;
+    }
+
+    /**
+     * Tests methods:
+     * <ul>
+     * <li>moduleNamespaceToPackageName</li> - with revision
+     * <li>packageNameForGeneratedType</li>
+     * <ul>
+     * <li>validateJavaPackage</li>
+     * </ul>
+     * <li>packageNameForTypeDefinition</li> <li>moduleNamespaceToPackageName</li>
+     * - without revision </ul>
+     */
+    @Test
+    public void testBindingGeneratorUtilMethods() throws IOException {
+        List<File> testModels = loadTestResources("/module.yang");
+        final YangContextParser parser = new YangParserImpl();
+        final Set<Module> modules = parser.parseFiles(testModels).getModules();
+        String packageName = "";
+        Module module = null;
+        for (Module m : modules) {
+            module = m;
+            break;
+        }
+        assertNotNull("Module can't be null", module);
+
+        // test of the method moduleNamespaceToPackageName()
+        packageName = BindingGeneratorUtil.moduleNamespaceToPackageName(module);
+        assertEquals("Generated package name is incorrect.",
+                "org.opendaylight.yang.gen.v1.urn.m.o.d.u.l.e.n.a.m.e.t.e.s.t._case._1digit.rev130910", packageName);
+
+        // test of the method packageNameForGeneratedType()
+        DataNodeIterator it = new DataNodeIterator(module);
+        List<ContainerSchemaNode> schemaContainers = it.allContainers();
+        String subPackageNameForDataNode = "";
+        for (ContainerSchemaNode containerSchemaNode : schemaContainers) {
+            if (containerSchemaNode.getQName().getLocalName().equals("cont-inner")) {
+                subPackageNameForDataNode = BindingGeneratorUtil.packageNameForGeneratedType(packageName,
+                        containerSchemaNode.getPath());
+                break;
+            }
+        }
+        assertEquals("The name of the subpackage is incorrect.",
+                "org.opendaylight.yang.gen.v1.urn.m.o.d.u.l.e.n.a.m.e.t.e.s.t._case._1digit.rev130910.cont.outter",
+                subPackageNameForDataNode);
+
+        // test of the method packageNameForTypeDefinition
+        Set<TypeDefinition<?>> typeDefinitions = module.getTypeDefinitions();
+        String subPackageNameForTypeDefinition = "";
+        TypeDefinition<?> firstTypeDef = null;
+
+        for (TypeDefinition<?> tpDef : typeDefinitions) {
+            if (tpDef.getQName().getLocalName().equals("tpdf")) {
+                subPackageNameForTypeDefinition = BindingGeneratorUtil.packageNameForTypeDefinition(packageName, tpDef);
+                firstTypeDef = tpDef;
+                break;
+            }
+        }
+        assertEquals("The name of the subpackage is incorrect.",
+                "org.opendaylight.yang.gen.v1.urn.m.o.d.u.l.e.n.a.m.e.t.e.s.t._case._1digit.rev130910",
+                subPackageNameForTypeDefinition);
+
+        // test method getRestrictions
+        Restrictions restriction = BindingGeneratorUtil.getRestrictions(firstTypeDef);
+        assertNotNull(restriction);
+
+        // test method computeDefaultSUID
+        GeneratedTypeBuilder genTypeBuilder = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test", "TestType");
+        genTypeBuilder.addMethod("testMethod");
+        genTypeBuilder.addAnnotation("org.opendaylight.yangtools.test.annotation", "AnnotationTest");
+        genTypeBuilder.addEnclosingTransferObject("testObject");
+        genTypeBuilder.addProperty("newProp");
+        GeneratedTypeBuilder genType = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test", "Type2");
+        genTypeBuilder.addImplementsType(genType);
+        long computedSUID = BindingGeneratorUtil.computeDefaultSUID(genTypeBuilder);
+
+        GeneratedTypeBuilder genTypeBuilder2 = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test2", "TestType2");
+        long computedSUID2 = BindingGeneratorUtil.computeDefaultSUID(genTypeBuilder2);
+        assertNotEquals(computedSUID, computedSUID2);
+
+        // test of exception part of the method moduleNamespaceToPackageName()
+        ModuleBuilder moduleBuilder = new ModuleBuilder("module-withut-revision", null);
+        moduleBuilder.setSource("");
+        Module moduleWithoutRevision = moduleBuilder.build();
+        boolean passedSuccesfully = false;
+        try {
+            BindingGeneratorUtil.moduleNamespaceToPackageName(moduleWithoutRevision);
+            passedSuccesfully = true;
+        } catch (IllegalArgumentException e) {
+        }
+        assertFalse("Exception 'IllegalArgumentException' wasn't raised", passedSuccesfully);
+
+    }
+
+    /**
+     * Test for the method
+     * <ul>
+     * <li>{@link BindingGeneratorUtil#packageNameForTypeDefinition()
+     * packageNameForTypeDefinition()}</li>
+     * </ul>
+     */
+    @Test
+    public void testPackageNameForTypeDefinitionNullBasePackageName() {
+        expectedEx.expect(IllegalArgumentException.class);
+        expectedEx.expectMessage("Base Package Name cannot be NULL!");
+        BindingGeneratorUtil.packageNameForTypeDefinition(null, null);
+    }
+
+    /**
+     * Test for the method
+     * <ul>
+     * <li>{@link BindingGeneratorUtil#packageNameForTypeDefinition()
+     * packageNameForTypeDefinition()}</li>
+     * </ul>
+     */
+    @Test
+    public void testPackageNameForTypeDefinitionNullTypeDefinition() {
+        expectedEx.expect(IllegalArgumentException.class);
+        expectedEx.expectMessage("Type Definition reference cannot be NULL!");
+        BindingGeneratorUtil.packageNameForTypeDefinition("test.package", null);
+    }
+
+    /**
+     * Test for the method
+     * <ul>
+     * <li>{@link BindingGeneratorUtil#packageNameForGeneratedType()
+     * packageNameForGeneratedType()}</li>
+     * </ul>
+     */
+    @Test
+    public void testPackageNameForGeneratedTypeNullBasePackageName() {
+        expectedEx.expect(IllegalArgumentException.class);
+        expectedEx.expectMessage("Base Package Name cannot be NULL!");
+        BindingGeneratorUtil.packageNameForGeneratedType(null, null);
+    }
+
+    /**
+     * Test for the method
+     * <ul>
+     * <li>{@link BindingGeneratorUtil#packageNameForGeneratedType()
+     * packageNameForGeneratedType()}</li>
+     * </ul>
+     */
+    @Test
+    public void testPackageNameForGeneratedTypeNullSchemaPath() {
+        expectedEx.expect(IllegalArgumentException.class);
+        expectedEx.expectMessage("Schema Path cannot be NULL!");
+        BindingGeneratorUtil.packageNameForGeneratedType("test.package", null);
+    }
+
+    /**
+     * Test for the method
+     * <ul>
+     * <li>{@link BindingGeneratorUtil#parseToClassName()
+     * parseToClassName()}</li>
+     * </ul>
+     */
+    @Test
+    public void testParseToClassNameNullValue() {
+        String className = BindingGeneratorUtil.parseToClassName("test-class-name");
+        assertEquals("TestClassName", className);
+
+        expectedEx.expect(IllegalArgumentException.class);
+        expectedEx.expectMessage("Name can not be null");
+        className = BindingGeneratorUtil.parseToClassName(null);
+    }
+
+    /**
+     * Test for the method
+     * <ul>
+     * <li>{@link BindingGeneratorUtil#parseToClassName()
+     * parseToClassName()}</li>
+     * </ul>
+     */
+    @Test
+    public void testParseToClassNameEmptyValue() {
+        String className = BindingGeneratorUtil.parseToClassName("test-class-name");
+        assertEquals("TestClassName", className);
+
+        expectedEx.expect(IllegalArgumentException.class);
+        expectedEx.expectMessage("Name can not be empty");
+        className = BindingGeneratorUtil.parseToClassName("");
+    }
+
+    /**
+     * Test for the method
+     * <ul>
+     * <li>{@link BindingGeneratorUtil#validateParameterName()
+     * validateParameterName()}</li>
+     * <ul>
+     */
+    @Test
+    public void testValidateParameterName() {
+        assertNull("Return value is incorrect.", BindingGeneratorUtil.resolveJavaReservedWordEquivalency(null));
+        assertEquals("Return value is incorrect.", "whatever",
+                BindingGeneratorUtil.resolveJavaReservedWordEquivalency("whatever"));
+        assertEquals("Return value is incorrect.", "_case",
+                BindingGeneratorUtil.resolveJavaReservedWordEquivalency("case"));
+    }
+
+    /**
+     * Tests the methods:
+     * <ul>
+     * <li>parseToClassName</li>
+     * <ul>
+     * <li>parseToCamelCase</li>
+     * <ul>
+     * <li>replaceWithCamelCase</li>
+     * </ul>
+     * </ul> <li>parseToValidParamName</li>
+     * <ul>
+     * <li>parseToCamelCase</li>
+     * <ul>
+     * <li>replaceWithCamelCase</li>
+     * </ul>
+     * </ul>
+     * <ul>
+     */
+    @Test
+    public void testParsingMethods() {
+        // parseToClassName method testing
+        assertEquals("Class name has incorrect format", "SomeTestingClassName",
+                BindingMapping.getClassName("  some-testing_class name   "));
+        assertEquals("Class name has incorrect format", "_0SomeTestingClassName",
+                BindingMapping.getClassName("  0 some-testing_class name   "));
+
+        // parseToValidParamName
+        assertEquals("Parameter name has incorrect format", "someTestingParameterName",
+                BindingGeneratorUtil.parseToValidParamName("  some-testing_parameter   name   "));
+        assertEquals("Parameter name has incorrect format", "_0someTestingParameterName",
+                BindingGeneratorUtil.parseToValidParamName("  0some-testing_parameter   name   "));
+    }
+
+    @Test
+    public void computeDefaultSUIDTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        MethodSignatureBuilder method = generatedTypeBuilder.addMethod("myMethodName");
+        method.setAccessModifier(AccessModifier.PUBLIC);
+        generatedTypeBuilder.addProperty("myProperty");
+        generatedTypeBuilder.addImplementsType(Types.typeForClass(Serializable.class));
+
+        assertEquals(6788238694991761868L, BindingGeneratorUtil.computeDefaultSUID(generatedTypeBuilder));
+
+    }
+
+    @Test
+    public void getRestrictionsTest() {
+
+        Optional<String> absent = Optional.absent();
+
+        Builder extTypeBuilder = ExtendedType.builder(new QName(URI.create("namespace"), "localName"),
+                Int16.getInstance(), absent, absent, SchemaPath.create(true, QName.create("/root")));
+
+        ArrayList<LengthConstraint> lenght = new ArrayList<LengthConstraint>();
+        ArrayList<RangeConstraint> range = new ArrayList<RangeConstraint>();
+        ArrayList<PatternConstraint> pattern = new ArrayList<PatternConstraint>();
+
+        lenght.add(BaseConstraints.newLengthConstraint(1, 2, absent, absent));
+        range.add(BaseConstraints.newRangeConstraint(1, 2, absent, absent));
+        pattern.add(BaseConstraints.newPatternConstraint(".*", absent, absent));
+
+        extTypeBuilder.lengths(lenght);
+        extTypeBuilder.ranges(range);
+        extTypeBuilder.patterns(pattern);
+
+        Restrictions restrictions = BindingGeneratorUtil.getRestrictions(extTypeBuilder.build());
+
+        assertNotNull(restrictions);
+
+        assertEquals(1, restrictions.getLengthConstraints().size());
+        assertEquals(1, restrictions.getRangeConstraints().size());
+        assertEquals(1, restrictions.getPatternConstraints().size());
+
+        assertFalse(restrictions.isEmpty());
+        assertTrue(restrictions.getLengthConstraints().contains(
+                BaseConstraints.newLengthConstraint(1, 2, absent, absent)));
+        assertTrue(restrictions.getRangeConstraints()
+                .contains(BaseConstraints.newRangeConstraint(1, 2, absent, absent)));
+        assertTrue(restrictions.getPatternConstraints().contains(
+                BaseConstraints.newPatternConstraint(".*", absent, absent)));
+    }
+
+    @Test
+    public void getEmptyRestrictionsTest() {
+
+        Optional<String> absent = Optional.absent();
+
+        Builder extTypeBuilder = ExtendedType.builder(new QName(URI.create("namespace"), "localName"),
+                StringType.getInstance(), absent, absent, SchemaPath.create(true, QName.create("/root")));
+
+        Restrictions restrictions = BindingGeneratorUtil.getRestrictions(extTypeBuilder.build());
+
+        assertNotNull(restrictions);
+        assertTrue(restrictions.isEmpty());
+
+    }
+
+    @Test
+    public void getDefaultIntegerRestrictionsTest() {
+
+        Optional<String> absent = Optional.absent();
+
+        Builder extTypeBuilder = ExtendedType.builder(new QName(URI.create("namespace"), "localName"),
+                Int16.getInstance(), absent, absent, SchemaPath.create(true, QName.create("/root")));
+
+        ExtendedType extType = extTypeBuilder.build();
+        Restrictions restrictions = BindingGeneratorUtil.getRestrictions(extType);
+
+        assertNotNull(restrictions);
+        assertFalse(restrictions.isEmpty());
+        assertEquals(((IntegerTypeDefinition) extType.getBaseType()).getRangeConstraints(),
+                restrictions.getRangeConstraints());
+        assertTrue(restrictions.getLengthConstraints().isEmpty());
+        assertTrue(restrictions.getPatternConstraints().isEmpty());
+
+    }
+
+    @Test
+    public void getDefaultUnsignedIntegerRestrictionsTest() {
+
+        Optional<String> absent = Optional.absent();
+
+        Builder extTypeBuilder = ExtendedType.builder(new QName(URI.create("namespace"), "localName"),
+                Uint16.getInstance(), absent, absent, SchemaPath.create(true, QName.create("/root")));
+
+        ExtendedType extType = extTypeBuilder.build();
+        Restrictions restrictions = BindingGeneratorUtil.getRestrictions(extType);
+
+        assertNotNull(restrictions);
+        assertFalse(restrictions.isEmpty());
+        assertEquals(((UnsignedIntegerTypeDefinition) extType.getBaseType()).getRangeConstraints(),
+                restrictions.getRangeConstraints());
+        assertTrue(restrictions.getLengthConstraints().isEmpty());
+        assertTrue(restrictions.getPatternConstraints().isEmpty());
+    }
+
+    @Test
+    public void getDefaultDecimalRestrictionsTest() {
+
+        Optional<String> absent = Optional.absent();
+        SchemaPath path = SchemaPath.create(true, QName.create("/root"));
+
+        Builder extTypeBuilder = ExtendedType.builder(new QName(URI.create("namespace"), "localName"),
+                Decimal64.create(path, 10), absent, absent, path);
+
+        ExtendedType extType = extTypeBuilder.build();
+        Restrictions restrictions = BindingGeneratorUtil.getRestrictions(extType);
+
+        assertNotNull(restrictions);
+        assertFalse(restrictions.isEmpty());
+        assertEquals(((DecimalTypeDefinition) extType.getBaseType()).getRangeConstraints(),
+                restrictions.getRangeConstraints());
+        assertTrue(restrictions.getLengthConstraints().isEmpty());
+        assertTrue(restrictions.getPatternConstraints().isEmpty());
+
+    }
+
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/BindingTypesTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/BindingTypesTest.java
new file mode 100644 (file)
index 0000000..3ebcf4e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.binding.generator.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.opendaylight.yangtools.binding.generator.util.Types.typeForClass;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+
+public class BindingTypesTest {
+
+    @Test
+    public void staticBindingTypesTest() {
+        assertEquals("AUGMENTABLE", typeForClass(Augmentable.class), BindingTypes.AUGMENTABLE);
+        assertEquals("AUGMENTATION", typeForClass(Augmentation.class), BindingTypes.AUGMENTATION);
+        assertEquals("BASE_IDENTITY", typeForClass(BaseIdentity.class), BindingTypes.BASE_IDENTITY);
+        assertEquals("DATA_OBJECT", typeForClass(DataObject.class), BindingTypes.DATA_OBJECT);
+        assertEquals("DATA_ROOT", typeForClass(DataRoot.class), BindingTypes.DATA_ROOT);
+        assertEquals("IDENTIFIABLE", typeForClass(Identifiable.class), BindingTypes.IDENTIFIABLE);
+        assertEquals("IDENTIFIER", typeForClass(Identifier.class), BindingTypes.IDENTIFIER);
+        assertEquals("INSTANCE_IDENTIFIER", typeForClass(InstanceIdentifier.class), BindingTypes.INSTANCE_IDENTIFIER);
+        assertEquals("NOTIFICATION", typeForClass(Notification.class), BindingTypes.NOTIFICATION);
+        assertEquals("NOTIFICATION_LISTENER", typeForClass(NotificationListener.class), BindingTypes.NOTIFICATION_LISTENER);
+        assertEquals("RPC_SERVICE", typeForClass(RpcService.class), BindingTypes.RPC_SERVICE);
+    }
+
+    @Test
+    public void testAugmentable() {
+        ParameterizedType augmentType = BindingTypes.augmentable(null);
+        assertNotNull(augmentType);
+    }
+
+    @Test
+    public void testChildOf() {
+        ParameterizedType childOfType = BindingTypes.childOf(null);
+        assertNotNull(childOfType);
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/ReferencedTypeImplTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/ReferencedTypeImplTest.java
new file mode 100644 (file)
index 0000000..04e3982
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.binding.generator.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class ReferencedTypeImplTest {
+
+    @Test
+    public void testCreateNewReferencedType() {
+        ReferencedTypeImpl refType = new ReferencedTypeImpl("org.opendaylight.yangtools.test", "RefTypeTest");
+        assertEquals("RefTypeTest", refType.getName());
+    }
+
+    @Test
+    public void testToStringMethod() {
+        ReferencedTypeImpl refType = new ReferencedTypeImpl("org.opendaylight.yangtools.test", "RefTypeTest");
+        assertTrue(refType.toString().contains("RefTypeTest"));
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/TypesTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/TypesTest.java
new file mode 100644 (file)
index 0000000..5595e23
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.binding.generator.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.WildcardType;
+
+public class TypesTest {
+
+    @Test
+    public void testVoidType() {
+        final ConcreteType voidType = Types.voidType();
+        assertEquals("Void", voidType.getName());
+        assertNotNull(voidType);
+    }
+
+    @Test
+    public void testPrimitiveType() {
+        final Type primitiveType = Types.primitiveType("newType", null);
+        assertEquals("newType", primitiveType.getName());
+        assertNotNull(primitiveType);
+    }
+
+    @Test
+    public void testMapTypeFor() {
+        final ParameterizedType mapType = Types.mapTypeFor(null, null);
+        assertEquals("Map", mapType.getName());
+        assertNotNull(mapType);
+    }
+
+    @Test
+    public void testSetTypeFor() {
+        final ParameterizedType setType = Types.setTypeFor(null);
+        assertEquals("Set", setType.getName());
+        assertNotNull(setType);
+    }
+
+    @Test
+    public void testListTypeFor() {
+        final ParameterizedType listType = Types.listTypeFor(null);
+        assertEquals("List", listType.getName());
+        assertNotNull(listType);
+    }
+
+    @Test
+    public void testWildcardTypeFor() {
+        final WildcardType wildcardType = Types.wildcardTypeFor("org.opendaylight.yangtools.test", "WildcardTypeTest");
+        assertEquals("WildcardTypeTest", wildcardType.getName());
+        assertNotNull(wildcardType);
+    }
+
+    @Test
+    public void testAugmentableTypeFor() {
+        ParameterizedType augmentableType = Types.augmentableTypeFor(null);
+        assertEquals("Augmentable", augmentableType.getName());
+    }
+
+    @Test
+    public void augmentationTypeFor() {
+        ParameterizedType augmentationType = Types.augmentationTypeFor(null);
+        assertEquals("Augmentation", augmentationType.getName());
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractGeneratedTypeBuilderTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractGeneratedTypeBuilderTest.java
new file mode 100644 (file)
index 0000000..0841f80
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ */
+package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
+
+import java.io.Serializable;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+
+public class AbstractGeneratedTypeBuilderTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addPropertyIllegalArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addProperty(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addPropertyIllegalArgumentTest2() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addProperty("myName");
+        generatedTypeBuilder.addProperty("myName");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addEnclosingTransferObjectArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addEnclosingTransferObject(new GeneratedTOBuilderImpl("my.package", "myName"));
+        generatedTypeBuilder.addEnclosingTransferObject(new GeneratedTOBuilderImpl("my.package", "myName"));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addEnclosingTransferObjectArgumentTest2() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addEnclosingTransferObject("myName");
+        generatedTypeBuilder.addEnclosingTransferObject("myName");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addImplementsTypeIllegalArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addImplementsType(Types.typeForClass(Serializable.class));
+        generatedTypeBuilder.addImplementsType(Types.typeForClass(Serializable.class));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addConstantIllegalArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addConstant(Types.STRING, "myName", "Value");
+        generatedTypeBuilder.addConstant(Types.BOOLEAN, "myName", true);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addAnnotationIllegalArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addAnnotation("my.package", "myName");
+        generatedTypeBuilder.addAnnotation("my.package", "myName");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addEnumerationIllegalArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addEnumeration("myName");
+        generatedTypeBuilder.addEnumeration("myName");
+    }
+
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractTypeMemberTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AbstractTypeMemberTest.java
new file mode 100644 (file)
index 0000000..88f03ff
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+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.sal.binding.model.api.MethodSignature;
+
+public class AbstractTypeMemberTest {
+
+    @Test
+    public void testMethodsForAbstractTypeMemberBuilder() {
+        final MethodSignatureBuilderImpl methodSignatureBuilderImpl = new MethodSignatureBuilderImpl("TestProperty");
+        final GeneratedTypeBuilderImpl typeBuilderImpl = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test", "TestType");
+        final GeneratedTypeBuilderImpl typeBuilderImpl2 = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test", "TestType2");
+        methodSignatureBuilderImpl.setComment("test comment");
+        methodSignatureBuilderImpl.setFinal(true);
+        methodSignatureBuilderImpl.setStatic(true);
+
+        final MethodSignature genProperty = methodSignatureBuilderImpl.toInstance(typeBuilderImpl);
+        final MethodSignature genProperty2 = methodSignatureBuilderImpl.toInstance(typeBuilderImpl2);
+        assertEquals("test comment", genProperty.getComment());
+        assertTrue(genProperty.isFinal());
+        assertTrue(genProperty.isStatic());
+        assertEquals(genProperty.hashCode(), genProperty2.hashCode());
+        assertTrue(genProperty.toString().contains("org.opendaylight.yangtools.test.TestType"));
+        assertNotNull(genProperty.toString());
+        assertTrue(genProperty.equals(genProperty2));
+        assertFalse(genProperty.equals(null));
+
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AnnotationBuilderTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/AnnotationBuilderTest.java
new file mode 100644 (file)
index 0000000..6e9e85a
--- /dev/null
@@ -0,0 +1,518 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType.Parameter;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.AnnotationTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+
+public class AnnotationBuilderTest {
+
+    @Test
+    public void generatedTypeAnnotationTest() {
+        final GeneratedTypeBuilder genTypeBuilder = new GeneratedTypeBuilderImpl("org.opendaylight.controller",
+                "AnnotInterface");
+
+        genTypeBuilder.addAnnotation("javax.management", "MXBean");
+        final AnnotationTypeBuilder annotDesc = genTypeBuilder.addAnnotation("javax.management", "Description");
+        annotDesc.addParameter("description", "some sort of interface");
+
+        final GeneratedType genType = genTypeBuilder.toInstance();
+
+        assertNotNull(genType);
+        assertNotNull(genType.getAnnotations());
+        assertEquals(2, genType.getAnnotations().size());
+
+        int annotCount = 0;
+        for (final AnnotationType annotation : genType.getAnnotations()) {
+            if (annotation.getPackageName().equals("javax.management") && annotation.getName().equals("MXBean")) {
+                annotCount++;
+                assertEquals(0, annotation.getParameters().size());
+            }
+            if (annotation.getPackageName().equals("javax.management") && annotation.getName().equals("Description")) {
+                annotCount++;
+                assertEquals(1, annotation.getParameters().size());
+                AnnotationType.Parameter param = annotation.getParameter("description");
+                assertNotNull(param);
+                assertEquals("description", param.getName());
+                assertNotNull(param.getValue());
+                assertEquals("some sort of interface", param.getValue());
+                assertNotNull(param.getValues());
+                assertTrue(param.getValues().isEmpty());
+            }
+        }
+        assertEquals(2, annotCount);
+    }
+
+    @Test
+    public void methodSignatureAnnotationTest() {
+        final GeneratedTypeBuilder genTypeBuilder = new GeneratedTypeBuilderImpl("org.opendaylight.controller",
+                "TransferObject");
+
+        final MethodSignatureBuilder methodBuilder = genTypeBuilder.addMethod("simpleMethod");
+        methodBuilder.setReturnType(Types.typeForClass(Integer.class));
+        final AnnotationTypeBuilder annotManAttr = methodBuilder.addAnnotation(
+                "org.springframework.jmx.export.annotation", "ManagedAttribute");
+
+        annotManAttr.addParameter("description", "\"The Name Attribute\"");
+        annotManAttr.addParameter("currencyTimeLimit", "20");
+        annotManAttr.addParameter("defaultValue", "\"bar\"");
+        annotManAttr.addParameter("persistPolicy", "\"OnUpdate\"");
+
+        final AnnotationTypeBuilder annotManProp = methodBuilder.addAnnotation(
+                "org.springframework.jmx.export.annotation", "ManagedOperation");
+
+        final List<String> typeValues = new ArrayList<String>();
+        typeValues.add("\"val1\"");
+        typeValues.add("\"val2\"");
+        typeValues.add("\"val3\"");
+        annotManProp.addParameters("types", typeValues);
+
+        final GeneratedType genType = genTypeBuilder.toInstance();
+
+        assertNotNull(genType);
+        assertNotNull(genType.getAnnotations());
+        assertNotNull(genType.getMethodDefinitions());
+        assertNotNull(genType.getMethodDefinitions().get(0));
+        assertNotNull(genType.getMethodDefinitions().get(0).getAnnotations());
+        final List<AnnotationType> annotations = genType.getMethodDefinitions().get(0).getAnnotations();
+        assertEquals(2, annotations.size());
+
+        int annotCount = 0;
+        for (final AnnotationType annotation : annotations) {
+            if (annotation.getPackageName().equals("org.springframework.jmx.export.annotation")
+                    && annotation.getName().equals("ManagedAttribute")) {
+                annotCount++;
+                assertEquals(4, annotation.getParameters().size());
+
+                assertNotNull(annotation.getParameter("description"));
+                assertNotNull(annotation.getParameter("currencyTimeLimit"));
+                assertNotNull(annotation.getParameter("defaultValue"));
+                assertNotNull(annotation.getParameter("persistPolicy"));
+                assertEquals("\"The Name Attribute\"", annotation.getParameter("description").getValue());
+                assertEquals("20", annotation.getParameter("currencyTimeLimit").getValue());
+                assertEquals("\"bar\"", annotation.getParameter("defaultValue").getValue());
+                assertEquals("\"OnUpdate\"", annotation.getParameter("persistPolicy").getValue());
+            }
+            if (annotation.getPackageName().equals("org.springframework.jmx.export.annotation")
+                    && annotation.getName().equals("ManagedOperation")) {
+                annotCount++;
+
+                assertEquals(1, annotation.getParameters().size());
+                assertNotNull(annotation.getParameter("types"));
+                assertEquals(3, annotation.getParameter("types").getValues().size());
+            }
+        }
+        assertEquals(2, annotCount);
+    }
+
+    @Test
+    public void generatedPropertyAnnotationTest() {
+        final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.controller",
+                "AnnotInterface");
+
+        final GeneratedPropertyBuilder propertyBuilder = genTOBuilder.addProperty("simpleProperty");
+        propertyBuilder.setReturnType(Types.typeForClass(Integer.class));
+        final AnnotationTypeBuilder annotManAttr = propertyBuilder.addAnnotation(
+                "org.springframework.jmx.export.annotation", "ManagedAttribute");
+
+        annotManAttr.addParameter("description", "\"The Name Attribute\"");
+        annotManAttr.addParameter("currencyTimeLimit", "20");
+        annotManAttr.addParameter("defaultValue", "\"bar\"");
+        annotManAttr.addParameter("persistPolicy", "\"OnUpdate\"");
+
+        final AnnotationTypeBuilder annotManProp = propertyBuilder.addAnnotation(
+                "org.springframework.jmx.export.annotation", "ManagedOperation");
+
+        final List<String> typeValues = new ArrayList<String>();
+        typeValues.add("\"val1\"");
+        typeValues.add("\"val2\"");
+        typeValues.add("\"val3\"");
+        annotManProp.addParameters("types", typeValues);
+
+        final GeneratedTransferObject genTransObj = genTOBuilder.toInstance();
+
+        assertNotNull(genTransObj);
+        assertNotNull(genTransObj.getAnnotations());
+        assertNotNull(genTransObj.getProperties());
+        assertNotNull(genTransObj.getProperties().get(0));
+        assertNotNull(genTransObj.getProperties().get(0).getAnnotations());
+        final List<AnnotationType> annotations = genTransObj.getProperties().get(0).getAnnotations();
+        assertEquals(2, annotations.size());
+
+        int annotCount = 0;
+        for (final AnnotationType annotation : annotations) {
+            if (annotation.getPackageName().equals("org.springframework.jmx.export.annotation")
+                    && annotation.getName().equals("ManagedAttribute")) {
+                annotCount++;
+                assertEquals(4, annotation.getParameters().size());
+
+                assertNotNull(annotation.getParameter("description"));
+                assertNotNull(annotation.getParameter("currencyTimeLimit"));
+                assertNotNull(annotation.getParameter("defaultValue"));
+                assertNotNull(annotation.getParameter("persistPolicy"));
+                assertEquals("\"The Name Attribute\"", annotation.getParameter("description").getValue());
+                assertEquals("20", annotation.getParameter("currencyTimeLimit").getValue());
+                assertEquals("\"bar\"", annotation.getParameter("defaultValue").getValue());
+                assertEquals("\"OnUpdate\"", annotation.getParameter("persistPolicy").getValue());
+            }
+            if (annotation.getPackageName().equals("org.springframework.jmx.export.annotation")
+                    && annotation.getName().equals("ManagedOperation")) {
+                annotCount++;
+
+                assertEquals(1, annotation.getParameters().size());
+                assertNotNull(annotation.getParameter("types"));
+                assertEquals(3, annotation.getParameter("types").getValues().size());
+            }
+        }
+        assertEquals(2, annotCount);
+    }
+
+    @Test
+    public void generatedTransfeObjectAnnotationTest() {
+        final GeneratedTOBuilder genTypeBuilder = new GeneratedTOBuilderImpl("org.opendaylight.controller",
+                "AnnotClassCache");
+
+        genTypeBuilder.addAnnotation("javax.management", "MBean");
+        final AnnotationTypeBuilder annotNotify = genTypeBuilder.addAnnotation("javax.management", "NotificationInfo");
+
+        final List<String> notifyList = new ArrayList<String>();
+        notifyList.add("\"my.notif.type\"");
+        annotNotify.addParameters("types", notifyList);
+        annotNotify.addParameter("description", "@Description(\"my notification\")");
+
+        GeneratedTransferObject genTO = genTypeBuilder.toInstance();
+
+        assertNotNull(genTO);
+        assertNotNull(genTO.getAnnotations());
+        assertEquals(2, genTO.getAnnotations().size());
+
+        int annotCount = 0;
+        for (final AnnotationType annotation : genTO.getAnnotations()) {
+            if (annotation.getPackageName().equals("javax.management") && annotation.getName().equals("MBean")) {
+                annotCount++;
+                assertEquals(0, annotation.getParameters().size());
+            }
+            if (annotation.getPackageName().equals("javax.management")
+                    && annotation.getName().equals("NotificationInfo")) {
+                annotCount++;
+                assertEquals(2, annotation.getParameters().size());
+                AnnotationType.Parameter param = annotation.getParameter("types");
+                assertNotNull(param);
+                assertEquals("types", param.getName());
+                assertNull(param.getValue());
+                assertNotNull(param.getValues());
+                assertEquals(1, param.getValues().size());
+                assertEquals("\"my.notif.type\"", param.getValues().get(0));
+
+                param = annotation.getParameter("description");
+                assertNotNull(param);
+                assertEquals("description", param.getName());
+                assertNotNull(param.getValue());
+                assertEquals("@Description(\"my notification\")", param.getValue());
+            }
+        }
+        assertEquals(2, annotCount);
+    }
+
+    @Test
+    public void annotationTypeBuilderAddAnnotationTest() {
+        AnnotationTypeBuilder annotationTypeBuilder = new AnnotationTypeBuilderImpl("my.package", "MyName");
+
+        assertNull(annotationTypeBuilder.addAnnotation("my.package", null));
+        assertNull(annotationTypeBuilder.addAnnotation(null, "MyName"));
+
+        assertNotNull(annotationTypeBuilder.addAnnotation("", ""));
+
+        assertNotNull(annotationTypeBuilder.addAnnotation("my.package2", "MyName2"));
+        assertNull(annotationTypeBuilder.addAnnotation("my.package2", "MyName2"));
+
+        AnnotationType annotationTypeInstance = annotationTypeBuilder.toInstance();
+
+        assertEquals(2, annotationTypeInstance.getAnnotations().size());
+
+        assertEquals("my.package", annotationTypeInstance.getPackageName());
+        assertEquals("MyName", annotationTypeInstance.getName());
+
+    }
+
+    @Test
+    public void annotationTypeBuilderEqualsTest() {
+        AnnotationTypeBuilder annotationTypeBuilder = new AnnotationTypeBuilderImpl("my.package", "MyName");
+        AnnotationTypeBuilder annotationTypeBuilder2 = new AnnotationTypeBuilderImpl("my.package2", "MyName");
+        AnnotationTypeBuilder annotationTypeBuilder3 = new AnnotationTypeBuilderImpl("my.package", "MyName2");
+        AnnotationTypeBuilder annotationTypeBuilder4 = new AnnotationTypeBuilderImpl("my.package", "MyName");
+
+        assertFalse(annotationTypeBuilder.equals(null));
+        assertFalse(annotationTypeBuilder.equals(new Object()));
+
+        assertTrue(annotationTypeBuilder.equals(annotationTypeBuilder));
+
+        assertTrue(annotationTypeBuilder.equals(annotationTypeBuilder4));
+        assertFalse(annotationTypeBuilder.equals(annotationTypeBuilder2));
+        assertFalse(annotationTypeBuilder.equals(annotationTypeBuilder3));
+
+        AnnotationType instance = annotationTypeBuilder.toInstance();
+        AnnotationType instance2 = annotationTypeBuilder2.toInstance();
+        AnnotationType instance3 = annotationTypeBuilder3.toInstance();
+        AnnotationType instance4 = annotationTypeBuilder4.toInstance();
+
+        assertFalse(instance.equals(null));
+        assertFalse(instance.equals(new Object()));
+        assertTrue(instance.equals(instance));
+
+        assertFalse(instance.equals(instance2));
+        assertFalse(instance.equals(instance3));
+        assertTrue(instance.equals(instance4));
+
+        annotationTypeBuilder.addParameter("myName", "myValue1");
+        annotationTypeBuilder.addParameter("myName2", "myValue2");
+        annotationTypeBuilder2.addParameter("myName", "myValue3");
+
+        instance = annotationTypeBuilder.toInstance();
+        instance2 = annotationTypeBuilder2.toInstance();
+
+        Parameter parameter = instance.getParameter("myName");
+        Parameter parameter2 = instance.getParameter("myName2");
+        Parameter parameter3 = instance2.getParameter("myName");
+
+        assertFalse(parameter.equals(null));
+        assertFalse(parameter.equals(new Object()));
+        assertTrue(parameter.equals(parameter));
+        assertTrue(parameter.equals(parameter3));
+        assertFalse(parameter.equals(parameter2));
+    }
+
+    @Test
+    public void annotationTypeBuilderHashCodeTest() {
+        AnnotationTypeBuilder annotationTypeBuilder = new AnnotationTypeBuilderImpl("my.package", "MyName");
+        AnnotationTypeBuilder annotationTypeBuilder2 = new AnnotationTypeBuilderImpl("my.package2", "MyName");
+        AnnotationTypeBuilder annotationTypeBuilder3 = new AnnotationTypeBuilderImpl("my.package", "MyName2");
+        AnnotationTypeBuilder annotationTypeBuilder4 = new AnnotationTypeBuilderImpl("my.package", "MyName");
+
+        assertFalse(annotationTypeBuilder.hashCode() == annotationTypeBuilder2.hashCode());
+        assertFalse(annotationTypeBuilder.hashCode() == annotationTypeBuilder3.hashCode());
+
+        assertTrue(annotationTypeBuilder.hashCode() == annotationTypeBuilder4.hashCode());
+        assertTrue(annotationTypeBuilder.hashCode() == annotationTypeBuilder.hashCode());
+
+        AnnotationType instance = annotationTypeBuilder.toInstance();
+        AnnotationType instance2 = annotationTypeBuilder2.toInstance();
+        AnnotationType instance3 = annotationTypeBuilder3.toInstance();
+        AnnotationType instance4 = annotationTypeBuilder4.toInstance();
+
+        assertFalse(instance.hashCode() == instance2.hashCode());
+        assertFalse(instance.hashCode() == instance3.hashCode());
+
+        assertTrue(instance.hashCode() == instance4.hashCode());
+        assertTrue(instance.hashCode() == instance.hashCode());
+
+        annotationTypeBuilder.addParameter("myName", "myValue1");
+        annotationTypeBuilder.addParameter("myName2", "myValue2");
+        annotationTypeBuilder2.addParameter("myName", "myValue3");
+
+        instance = annotationTypeBuilder.toInstance();
+        instance2 = annotationTypeBuilder2.toInstance();
+
+        Parameter parameter = instance.getParameter("myName");
+        Parameter parameter2 = instance.getParameter("myName2");
+        Parameter parameter3 = instance2.getParameter("myName");
+
+        assertTrue(parameter.hashCode() == parameter.hashCode());
+        assertTrue(parameter.hashCode() == parameter3.hashCode());
+        assertFalse(parameter.hashCode() == parameter2.hashCode());
+
+    }
+
+    @Test
+    public void annotationTypeBuilderAddParameterTest() {
+        AnnotationTypeBuilder annotationTypeBuilder = new AnnotationTypeBuilderImpl("my.package", "MyName");
+
+        assertFalse(annotationTypeBuilder.addParameter(null, "myValue"));
+        assertFalse(annotationTypeBuilder.addParameter("myName", null));
+
+        assertFalse(annotationTypeBuilder.addParameters(null, new ArrayList<String>()));
+        assertFalse(annotationTypeBuilder.addParameters("myName", null));
+
+        assertTrue(annotationTypeBuilder.addParameter("myName", "myValue"));
+        assertFalse(annotationTypeBuilder.addParameter("myName", "myValue"));
+        assertFalse(annotationTypeBuilder.addParameters("myName", new ArrayList<String>()));
+
+        ArrayList<String> values = new ArrayList<String>();
+        values.add("myValue");
+        assertTrue(annotationTypeBuilder.addParameters("myName2", values));
+
+        AnnotationType annotationTypeInstance = annotationTypeBuilder.toInstance();
+        assertTrue(annotationTypeInstance.containsParameters());
+        assertEquals(2, annotationTypeInstance.getParameters().size());
+        assertEquals(2, annotationTypeInstance.getParameterNames().size());
+        assertTrue(annotationTypeInstance.getParameterNames().contains("myName"));
+        assertTrue(annotationTypeInstance.getParameterNames().contains("myName2"));
+        assertFalse(annotationTypeInstance.getParameterNames().contains("myName3"));
+
+        Parameter parameter = annotationTypeInstance.getParameter("myName");
+        Parameter parameter2 = annotationTypeInstance.getParameter("myName2");
+        Parameter parameter3 = annotationTypeInstance.getParameter("myName3");
+
+        assertNotNull(parameter);
+        assertNotNull(parameter2);
+        assertNull(parameter3);
+
+        assertEquals(parameter.getValue(), "myValue");
+        assertTrue(parameter.getValues().isEmpty());
+
+        assertEquals(1, parameter2.getValues().size());
+        assertTrue(parameter2.getValues().contains("myValue"));
+
+    }
+
+    @Test
+    public void annotationTypeBuilderToStringTest() {
+        AnnotationTypeBuilder annotationTypeBuilder = new AnnotationTypeBuilderImpl("my.package", "MyAnnotationName");
+        annotationTypeBuilder.addAnnotation("my.package", "MySubAnnotationName");
+        annotationTypeBuilder.addParameter("MyParameter", "myValue");
+
+        assertEquals(
+                "AnnotationTypeBuilder [packageName=my.package, name=MyAnnotationName, annotationBuilders=[AnnotationTypeBuilder [packageName=my.package, name=MySubAnnotationName, annotationBuilders=[], parameters=[]]], parameters=[ParameterImpl [name=MyParameter, value=myValue, values=[]]]]",
+                annotationTypeBuilder.toString());
+
+        AnnotationType annotationTypeInstance = annotationTypeBuilder.toInstance();
+
+        assertEquals("my.package.MyAnnotationName", annotationTypeInstance.getFullyQualifiedName());
+        assertEquals(
+                "AnnotationType [packageName=my.package, name=MyAnnotationName, annotations=[AnnotationType [packageName=my.package, name=MySubAnnotationName, annotations=[], parameters=[]]], parameters=[ParameterImpl [name=MyParameter, value=myValue, values=[]]]]",
+                annotationTypeInstance.toString());
+
+    }
+
+    public void testAddAnnotation() {
+        final AnnotationTypeBuilderImpl annotBuilderImpl = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+        annotBuilderImpl.addAnnotation("org.opedaylight.yangtools.test.v1", "AnnotationTest2");
+        annotBuilderImpl.addAnnotation(null, "AnnotationTest2");
+        assertFalse(annotBuilderImpl.toInstance().getAnnotations().isEmpty());
+    }
+
+    @Test
+    public void testAddParameterMethod() {
+        final AnnotationTypeBuilderImpl annotBuilderImpl = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+        annotBuilderImpl.addParameter("testParam", "test value");
+        annotBuilderImpl.addParameter(null, "test value");
+        final AnnotationType annotType = annotBuilderImpl.toInstance();
+        assertEquals(1, annotType.getParameters().size());
+    }
+
+    @Test
+    public void testAddParametersMethod() {
+        final AnnotationTypeBuilderImpl annotBuilderImpl = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+
+        final List<String> values = new ArrayList<>();
+        values.add("test1");
+        values.add("test2");
+        values.add("test3");
+        annotBuilderImpl.addParameters("testParam", values);
+
+        AnnotationType annotType = annotBuilderImpl.toInstance();
+        assertEquals(1, annotType.getParameters().size());
+
+        annotBuilderImpl.addParameters("testParam", null);
+
+        annotType = annotBuilderImpl.toInstance();
+        assertEquals(1, annotType.getParameters().size());
+    }
+
+    @Test
+    public void testHashCode() {
+        final AnnotationTypeBuilderImpl annotBuilderImpl = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+        final AnnotationTypeBuilderImpl annotBuilderImpl2 = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest2");
+        assertFalse(annotBuilderImpl.hashCode() == annotBuilderImpl2.hashCode());
+    }
+
+    @Test
+    public void testEquals() {
+        final AnnotationTypeBuilderImpl annotBuilderImpl = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+        final AnnotationTypeBuilderImpl annotBuilderImpl2 = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+        final AnnotationTypeBuilderImpl annotBuilderImpl3 = annotBuilderImpl2;
+
+        assertTrue(annotBuilderImpl.equals(annotBuilderImpl2));
+        assertTrue(annotBuilderImpl2.equals(annotBuilderImpl3));
+        assertFalse(annotBuilderImpl2.equals(null));
+        assertFalse(annotBuilderImpl2.equals("test"));
+    }
+
+    @Test
+    public void testToString() {
+        final AnnotationTypeBuilderImpl annotBuilderImpl = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+        assertNotNull(annotBuilderImpl.toString());
+    }
+
+    @Test
+    public void testMethodsForAnnotationTypeImpl() {
+        final AnnotationTypeBuilderImpl annotBuilderImpl = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+        annotBuilderImpl.addParameter("testParam", "test value");
+        final AnnotationType annotationType = annotBuilderImpl.toInstance();
+
+        final AnnotationTypeBuilderImpl annotBuilderImpl2 = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+        final AnnotationType annotationType2 = annotBuilderImpl2.toInstance();
+
+        assertTrue(annotationType.containsParameters());
+        assertTrue(annotationType.getAnnotations().isEmpty());
+        assertNotNull(annotationType.getFullyQualifiedName());
+        assertNotNull(annotationType.getName());
+        assertNotNull(annotationType.getPackageName());
+        assertNull(annotationType.getParameter(null));
+        assertNotNull(annotationType.getParameter("testParam"));
+        assertFalse(annotationType.getParameterNames().isEmpty());
+        assertFalse(annotationType.getParameters().isEmpty());
+
+        assertTrue(annotationType.hashCode() == annotationType2.hashCode());
+        assertTrue(annotationType.equals(annotationType2));
+        assertNotNull(annotationType.toString());
+    }
+
+    @Test
+    public void testMethodsForParameterImpl() {
+        final AnnotationTypeBuilderImpl annotBuilderImpl = new AnnotationTypeBuilderImpl("org.opedaylight.yangtools.test", "AnnotationTest");
+        annotBuilderImpl.addParameter("testParam", "test value");
+        annotBuilderImpl.addParameter("testParam", "test value");
+        annotBuilderImpl.addParameter("", "test value");
+        annotBuilderImpl.addParameter(null, "test value");
+        annotBuilderImpl.addParameter("", null);
+        final AnnotationType annotationType = annotBuilderImpl.toInstance();
+
+        final Parameter testParam = annotationType.getParameter("testParam");
+        assertEquals("testParam", testParam.getName());
+        assertEquals("test value", testParam.getValue());
+        assertEquals(0, testParam.getValues().size());
+
+        final List<Parameter> testParams = annotationType.getParameters();
+        final Parameter sameParam = testParams.get(0);
+
+        assertFalse(testParams.get(0).equals(testParams.get(1)));
+        assertFalse(testParams.get(0).equals(null));
+        assertFalse(testParams.get(0).equals("test"));
+        assertTrue(testParams.get(0).equals(sameParam));
+        assertFalse(testParams.get(0).hashCode() == testParams.get(1).hashCode());
+        assertTrue(testParams.get(0).hashCode() == testParams.get(0).hashCode());
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/ConstantImplTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/ConstantImplTest.java
new file mode 100644 (file)
index 0000000..b545cc3
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+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;
+
+public class ConstantImplTest {
+
+    @Test
+    public void testMethodsOfConstantImpl() {
+        final GeneratedTypeBuilderImpl definingType = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test",
+                "DefiningType");
+        final GeneratedTypeBuilderImpl type = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test.v1",
+                "BaseType");
+        final ConstantImpl constImpl = new ConstantImpl(definingType, type, "IpAddress", "127.0.0.1");
+        final ConstantImpl constImpl2 = new ConstantImpl(definingType, type, "IpAddress", "127.0.0.1");
+        final ConstantImpl constImpl3 = new ConstantImpl(definingType, type, "IpAddress", "127.0.0.0");
+        final ConstantImpl constImpl4 = constImpl;
+        final ConstantImpl constImpl5 = new ConstantImpl(definingType, type, null, "127.0.0.0");
+        final ConstantImpl constImpl6 = new ConstantImpl(definingType, type, "IpAddress", null);
+
+        assertEquals("DefiningType", constImpl.getDefiningType().getName());
+        assertEquals("BaseType", constImpl.getType().getName());
+        assertEquals("IpAddress", constImpl.getName());
+        assertEquals("127.0.0.1", constImpl.getValue());
+        assertTrue(constImpl.toFormattedString().contains("GeneratedTransferObject"));
+        assertTrue(constImpl.toString().contains("GeneratedTransferObject"));
+        assertEquals(constImpl.hashCode(), constImpl2.hashCode());
+        assertNotNull(constImpl.getDefiningType());
+        assertNotNull(constImpl.getType());
+        assertNotNull(constImpl.getName());
+        assertNotNull(constImpl.getValue());
+        assertNotNull(constImpl.toFormattedString());
+        assertNotNull(constImpl.toString());
+        assertNotNull(constImpl.hashCode());
+        assertFalse(constImpl.equals(null));
+        assertFalse(constImpl.equals("test"));
+
+        assertTrue(constImpl.equals(constImpl2));
+        assertFalse(constImpl.equals(constImpl3));
+        assertTrue(constImpl.equals(constImpl4));
+        assertFalse(constImpl5.equals(constImpl));
+        assertFalse(constImpl6.equals(constImpl));
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/EnumerationBuilderImplTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/EnumerationBuilderImplTest.java
new file mode 100644 (file)
index 0000000..eb5bd65
--- /dev/null
@@ -0,0 +1,286 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import com.google.common.base.Optional;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.EnumerationType;
+
+public class EnumerationBuilderImplTest {
+
+    private EnumerationBuilderImpl enumerationBuilder;
+    private EnumerationBuilderImpl enumerationBuilderSame;
+    private EnumerationBuilderImpl enumerationBuilderOtherName;
+    private EnumerationBuilderImpl enumerationBuilderOtherPackage;
+    private final String DESCRIPTION = "Test description of Enum";
+    private final String packageName = "org.opendaylight.test";
+    private final String name = "TestName";
+    private final String moduleName = "TestModuleName";
+    private final String reference = "TestRef";
+    private final String valueName = "TestValue";
+    private final String valueDescription = "Value used for test";
+    private final int value = 12;
+    private Enumeration enumeration;
+    private final QName  qName = QName.create("TestQName", "10-10-2014", "TestLocalQName");
+
+
+    @Before
+    public void setup() {
+        enumerationBuilder = new EnumerationBuilderImpl(packageName, name);
+        enumerationBuilder.setDescription(DESCRIPTION);
+        enumerationBuilder.setModuleName(moduleName);
+        enumerationBuilder.setReference(reference);
+        enumerationBuilder.setSchemaPath(Collections.singletonList(qName));
+        enumerationBuilder.addValue(valueName, value, valueDescription);
+        enumerationBuilder.addAnnotation(packageName, "TestAnnotation");
+        enumerationBuilderSame = new EnumerationBuilderImpl(packageName, name);
+        enumerationBuilderOtherName = new EnumerationBuilderImpl(packageName, "SomeOtherName");
+        enumerationBuilderOtherPackage = new EnumerationBuilderImpl("org.opendaylight.other", name);
+        enumeration = enumerationBuilder.toInstance(enumerationBuilder);
+    }
+
+    @Test
+    public void testAddNullAnnotation() {
+        assertNull(enumerationBuilder.addAnnotation(null, null));
+        assertNull(enumerationBuilder.addAnnotation(null, "test"));
+        assertNull(enumerationBuilder.addAnnotation(packageName, null));
+    }
+
+    @Test
+    public void testEnumerationBuilder() {
+        assertEquals(packageName + "." + name, enumerationBuilder.getFullyQualifiedName());
+        assertEquals(name , enumerationBuilder.getName());
+        assertEquals(packageName, enumerationBuilder.getPackageName());
+
+        assertNotEquals(enumerationBuilder, null);
+        assertEquals(enumerationBuilder, enumerationBuilder);
+        assertNotEquals(enumerationBuilder, "string");
+        assertNotEquals(enumerationBuilder, enumerationBuilderOtherName);
+        assertNotEquals(enumerationBuilder, enumerationBuilderOtherPackage);
+        assertEquals(enumerationBuilder,enumerationBuilderSame);
+    }
+
+    @Test
+    public void testEnumeration() {
+        assertEquals(name, enumeration.getName());
+        assertEquals(packageName, enumeration.getPackageName());
+        assertEquals(null, enumeration.getComment());
+        assertEquals(enumerationBuilder, enumeration.getParentType());
+        assertEquals(DESCRIPTION, enumeration.getDescription());
+        assertEquals(moduleName, enumeration.getModuleName());
+        assertEquals(packageName + '.' + name, enumeration.getFullyQualifiedName());
+        assertEquals(reference, enumeration.getReference());
+        assertEquals(Collections.singletonList(qName), enumeration.getSchemaPath());
+        assertEquals(Collections.EMPTY_LIST, enumeration.getEnclosedTypes());
+        assertEquals(Collections.EMPTY_LIST, enumeration.getEnumerations());
+        assertEquals(Collections.EMPTY_LIST, enumeration.getMethodDefinitions());
+        assertEquals(Collections.EMPTY_LIST, enumeration.getConstantDefinitions());
+        assertEquals(Collections.EMPTY_LIST, enumeration.getProperties());
+        assertEquals(Collections.EMPTY_LIST, enumeration.getImplements());
+        assertNotNull(enumeration.getValues());
+        assertNotNull(enumeration.getAnnotations());
+
+        assertFalse(enumeration.isAbstract());
+        assertNotEquals(enumeration, null);
+        assertEquals(enumeration, enumeration);
+        assertNotEquals(enumeration, "string");
+
+        Enumeration enumerationOtherPackage = enumerationBuilderOtherPackage.toInstance(enumerationBuilderOtherPackage);
+        assertNotEquals(enumeration, enumerationOtherPackage);
+
+        Enumeration enumerationOtherName = enumerationBuilderOtherName.toInstance(enumerationBuilderOtherName);
+        assertNotEquals(enumeration, enumerationOtherName);
+
+        enumerationBuilderSame.addValue(valueName, value, valueDescription);
+        Enumeration enumerationSame = enumerationBuilderSame.toInstance(enumerationBuilderSame);
+        assertEquals(enumeration, enumerationSame);
+
+        EnumerationBuilderImpl enumerationBuilderSame1 = new EnumerationBuilderImpl(packageName, name);
+        Enumeration enumerationSame1 = enumerationBuilderSame1.toInstance(enumerationBuilderSame1);
+        enumerationBuilderSame1.addValue(valueName, 14, valueDescription);
+        // Enums are equal thanks to same package name and local name
+        assertEquals(enumeration, enumerationSame1);
+    }
+
+    @Test
+    public void testEnumerationToString() {
+        String formattedString =
+                "public enum " + name + " {\n" +
+                "\t TestValue " + "(12 );\n" +
+                "}";
+        String s = "Enumeration [packageName="+packageName+", definingType="+packageName+"."+name+", name="+name+
+                ", values=[EnumPair [name=TestValue, value=12]]]";
+
+        assertEquals(s, enumeration.toString());
+        assertEquals(formattedString, enumeration.toFormattedString());
+
+        assertEquals("EnumerationBuilderImpl " +
+                "[packageName=org.opendaylight.test, name=TestName, " +
+                "values=[EnumPair [name=TestValue, value=12]]]",
+                enumerationBuilder.toString());
+    }
+
+    @Test
+    public void testUpdateEnumPairsFromEnumTypeDef() {
+        EnumTypeDefinition.EnumPair enumPair = EnumPairImpl.create(qName);
+        EnumTypeDefinition enumTypeDefinition = EnumerationType.create(SchemaPath.SAME,
+                Arrays.asList(enumPair), Optional.of(enumPair));
+        enumerationBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDefinition);
+    }
+
+    /**
+     * Internal implementation of EnumPair.
+     */
+    private static class EnumPairImpl implements EnumTypeDefinition.EnumPair {
+        private final QName qname;
+        private final SchemaPath path;
+        private final String description;
+        private final String reference;
+        private final Status status;
+        private final List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+        private final String name;
+        private final Integer value;
+
+        private EnumPairImpl(QName qName) {
+            qname = qName;
+            path = SchemaPath.SAME;
+            description = "Some Other Description";
+            reference = "Some other reference";
+            status = Status.CURRENT;
+            name = "SomeName";
+            value = 45;
+        }
+
+        public static EnumPairImpl create(QName qName) {
+            return new EnumPairImpl(qName);
+        }
+
+        @Override
+        public QName getQName() {
+            return qname;
+        }
+
+        @Override
+        public SchemaPath getPath() {
+            return path;
+        }
+
+        @Override
+        public String getDescription() {
+            return description;
+        }
+
+        @Override
+        public String getReference() {
+            return reference;
+        }
+
+        @Override
+        public Status getStatus() {
+            return status;
+        }
+
+        @Override
+        public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+            return unknownNodes;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public Integer getValue() {
+            return value;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+            result = prime * result + ((path == null) ? 0 : path.hashCode());
+            result = prime * result + ((unknownNodes == null) ? 0 : unknownNodes.hashCode());
+            result = prime * result + ((name == null) ? 0 : name.hashCode());
+            result = prime * result + ((value == null) ? 0 : value.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(final Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            EnumPairImpl other = (EnumPairImpl) obj;
+            if (qname == null) {
+                if (other.qname != null) {
+                    return false;
+                }
+            } else if (!qname.equals(other.qname)) {
+                return false;
+            }
+            if (path == null) {
+                if (other.path != null) {
+                    return false;
+                }
+            } else if (!path.equals(other.path)) {
+                return false;
+            }
+            if (unknownNodes == null) {
+                if (other.unknownNodes != null) {
+                    return false;
+                }
+            } else if (!unknownNodes.equals(other.unknownNodes)) {
+                return false;
+            }
+            if (name == null) {
+                if (other.name != null) {
+                    return false;
+                }
+            } else if (!name.equals(other.name)) {
+                return false;
+            }
+            if (value == null) {
+                if (other.value != null) {
+                    return false;
+                }
+            } else if (!value.equals(other.value)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return EnumTypeDefinition.EnumPair.class.getSimpleName() + "[name=" + name + ", value=" + value + "]";
+        }
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyBuilderImplTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyBuilderImplTest.java
new file mode 100644 (file)
index 0000000..0f7dab6
--- /dev/null
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ */
+package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
+
+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.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+
+public class GeneratedPropertyBuilderImplTest {
+
+    @Test
+    public void generatedPropertyBuilderImplTest() {
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl = new GeneratedPropertyBuilderImpl("myPropertyName");
+        generatedPropertyBuilderImpl.setValue("myValue");
+        generatedPropertyBuilderImpl.setReadOnly(false);
+        generatedPropertyBuilderImpl.setStatic(true);
+        generatedPropertyBuilderImpl.setComment(null);
+        generatedPropertyBuilderImpl.setFinal(true);
+        generatedPropertyBuilderImpl.setAccessModifier(AccessModifier.PUBLIC);
+        generatedPropertyBuilderImpl.setReturnType(Types.BOOLEAN);
+
+        assertEquals(
+                "GeneratedPropertyImpl [name=myPropertyName, annotations=[], comment=null, returnType=Type (java.lang.Boolean), isFinal=true, isReadOnly=false, modifier=PUBLIC]",
+                generatedPropertyBuilderImpl.toString());
+
+        GeneratedProperty instance = generatedPropertyBuilderImpl.toInstance(null);
+
+        assertNotNull(instance);
+
+        assertTrue(instance.isFinal());
+        assertTrue(instance.isStatic());
+        assertFalse(instance.isReadOnly());
+        assertEquals("myValue", instance.getValue());
+        assertEquals(null, instance.getComment());
+        assertEquals(AccessModifier.PUBLIC, instance.getAccessModifier());
+        assertEquals(Types.BOOLEAN, instance.getReturnType());
+
+    }
+
+    @Test
+    public void generatedPropertyBuilderImplEqualsAndHashCodeTest() {
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl = new GeneratedPropertyBuilderImpl("myPropertyName");
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl2 = new GeneratedPropertyBuilderImpl("myPropertyName");
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl3 = new GeneratedPropertyBuilderImpl("myPropertyName3");
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl4 = new GeneratedPropertyBuilderImpl("myPropertyName");
+
+        assertNotNull(generatedPropertyBuilderImpl);
+        assertNotNull(generatedPropertyBuilderImpl2);
+        assertNotNull(generatedPropertyBuilderImpl3);
+        assertNotNull(generatedPropertyBuilderImpl4);
+
+        generatedPropertyBuilderImpl.setReturnType(Types.BOOLEAN);
+        generatedPropertyBuilderImpl2.setReturnType(Types.BOOLEAN);
+        generatedPropertyBuilderImpl3.setReturnType(Types.BOOLEAN);
+        generatedPropertyBuilderImpl4.setReturnType(Types.STRING);
+
+        assertFalse(generatedPropertyBuilderImpl.equals(null));
+        assertFalse(generatedPropertyBuilderImpl.equals(new Object()));
+        assertTrue(generatedPropertyBuilderImpl.equals(generatedPropertyBuilderImpl));
+        assertTrue(generatedPropertyBuilderImpl.equals(generatedPropertyBuilderImpl2));
+        assertFalse(generatedPropertyBuilderImpl.equals(generatedPropertyBuilderImpl3));
+        assertFalse(generatedPropertyBuilderImpl.equals(generatedPropertyBuilderImpl4));
+
+        assertTrue(generatedPropertyBuilderImpl.hashCode() == generatedPropertyBuilderImpl.hashCode());
+        assertTrue(generatedPropertyBuilderImpl.hashCode() == generatedPropertyBuilderImpl2.hashCode());
+        assertFalse(generatedPropertyBuilderImpl.hashCode() == generatedPropertyBuilderImpl3.hashCode());
+        assertFalse(generatedPropertyBuilderImpl.hashCode() == generatedPropertyBuilderImpl4.hashCode());
+    }
+
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyImplTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyImplTest.java
new file mode 100644 (file)
index 0000000..01572ab
--- /dev/null
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ */
+package org.opendaylight.yangtools.binding.generator.util.generated.type.builder;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+
+public class GeneratedPropertyImplTest {
+
+    @Test
+    public void generatedPropertyImplTest() {
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl = new GeneratedPropertyBuilderImpl("myPropertyName");
+        generatedPropertyBuilderImpl.setValue("myValue");
+        generatedPropertyBuilderImpl.setReadOnly(false);
+        generatedPropertyBuilderImpl.setStatic(true);
+        generatedPropertyBuilderImpl.setComment("myComment");
+        generatedPropertyBuilderImpl.setFinal(true);
+        generatedPropertyBuilderImpl.setAccessModifier(AccessModifier.PUBLIC);
+        generatedPropertyBuilderImpl.setReturnType(Types.BOOLEAN);
+
+        GeneratedProperty instance = generatedPropertyBuilderImpl.toInstance(new GeneratedTypeBuilderImpl("my.package",
+                "myTypeName").toInstance());
+
+        assertNotNull(instance);
+
+        assertTrue(instance.isFinal());
+        assertTrue(instance.isStatic());
+        assertFalse(instance.isReadOnly());
+        assertEquals("myValue", instance.getValue());
+        assertEquals("myComment", instance.getComment());
+        assertEquals(AccessModifier.PUBLIC, instance.getAccessModifier());
+        assertEquals(Types.BOOLEAN, instance.getReturnType());
+
+        assertEquals(
+                "GeneratedPropertyImpl [name=myPropertyName, annotations=[], comment=myComment, parent=my.package.myTypeName, returnType=Type (java.lang.Boolean), isFinal=true, isReadOnly=false, modifier=PUBLIC]",
+                instance.toString());
+
+    }
+
+    @Test
+    public void generatedPropertyImplEqualsAndHashCodeTest() {
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl = new GeneratedPropertyBuilderImpl("myPropertyName");
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl2 = new GeneratedPropertyBuilderImpl("myPropertyName");
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl3 = new GeneratedPropertyBuilderImpl("myPropertyName3");
+        GeneratedPropertyBuilderImpl generatedPropertyBuilderImpl4 = new GeneratedPropertyBuilderImpl("myPropertyName");
+
+        generatedPropertyBuilderImpl.setReturnType(Types.BOOLEAN);
+        generatedPropertyBuilderImpl2.setReturnType(Types.BOOLEAN);
+        generatedPropertyBuilderImpl3.setReturnType(Types.BOOLEAN);
+        generatedPropertyBuilderImpl4.setReturnType(Types.STRING);
+
+        GeneratedProperty property = generatedPropertyBuilderImpl.toInstance(null);
+        GeneratedProperty property2 = generatedPropertyBuilderImpl2.toInstance(null);
+        GeneratedProperty property3 = generatedPropertyBuilderImpl3.toInstance(null);
+        GeneratedProperty property4 = generatedPropertyBuilderImpl4.toInstance(null);
+
+        assertNotNull(property);
+        assertNotNull(property2);
+        assertNotNull(property3);
+        assertNotNull(property4);
+
+        assertFalse(property.equals(null));
+        assertFalse(property.equals(new Object()));
+        assertTrue(property.equals(property));
+        assertTrue(property.equals(property2));
+        assertFalse(property.equals(property3));
+        assertFalse(property.equals(property4));
+
+        assertTrue(property.hashCode() == property.hashCode());
+        assertTrue(property.hashCode() == property2.hashCode());
+        assertFalse(property.hashCode() == property3.hashCode());
+        assertFalse(property.hashCode() == property4.hashCode());
+    }
+
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedPropertyTest.java
new file mode 100644 (file)
index 0000000..ffcf2a9
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+
+public class GeneratedPropertyTest {
+
+    @Test
+    public void testMethodsForGeneratedPropertyBuilderImpl() {
+        final GeneratedPropertyBuilderImpl propertyBuilderImpl = new GeneratedPropertyBuilderImpl("testProperty");
+
+        propertyBuilderImpl.setValue("new value");
+        propertyBuilderImpl.setReadOnly(true);
+
+        final GeneratedProperty genProperty = propertyBuilderImpl.toInstance(null);
+        assertNotNull(genProperty);
+
+        assertNotNull(propertyBuilderImpl.toString());
+    }
+
+    @Test
+    public void testMethodsForGeneratedPropertyImpl() {
+        final GeneratedPropertyImpl propertyImpl = new GeneratedPropertyImpl(null, "Test", null, "test property", AccessModifier.PRIVATE, null, true, true, true, "test value");
+
+        assertEquals("test value", propertyImpl.getValue());
+        assertTrue(propertyImpl.isReadOnly());
+        assertNotNull(propertyImpl.toString());
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderImplTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderImplTest.java
new file mode 100644 (file)
index 0000000..ef3da5e
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+
+public class GeneratedTOBuilderImplTest {
+
+    @Test
+    public void testCreateNewInstance() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        assertNotNull(genTOBuilder);
+    }
+
+    @Test
+    public void testSetExtendsType() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        final GeneratedTOBuilderImpl extendedTypeBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "ExtendedType");
+        final GeneratedTransferObject extendedType = extendedTypeBuilder.toInstance();
+        genTOBuilder.setExtendsType(extendedType);
+        final GeneratedTransferObject genTO = genTOBuilder.toInstance();
+
+        assertEquals("ExtendedType", genTO.getSuperType().getName());
+    }
+
+    @Test
+    public void testAddMethod() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        final MethodSignatureBuilder methodSignatureBuilder = genTOBuilder.addMethod("testMethod");
+        assertEquals(methodSignatureBuilder, genTOBuilder.getMethodDefinitions().get(0));
+        assertEquals("testMethod", genTOBuilder.getMethodDefinitions().get(0).getName());
+    }
+
+    @Test
+    public void testAddEqualsIdentity() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        final GeneratedPropertyBuilderImpl propertyBuilder = new GeneratedPropertyBuilderImpl("testProperty");
+        genTOBuilder.addEqualsIdentity(propertyBuilder);
+
+        final GeneratedTransferObject genTO = genTOBuilder.toInstance();
+        assertEquals(1, genTO.getEqualsIdentifiers().size());
+        assertEquals("testProperty", genTO.getEqualsIdentifiers().get(0).getName());
+    }
+
+    @Test
+    public void testAddHashIdentity() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        final GeneratedPropertyBuilderImpl propertyBuilder = new GeneratedPropertyBuilderImpl("testProperty");
+        genTOBuilder.addHashIdentity(propertyBuilder);
+
+        final GeneratedTransferObject genTO = genTOBuilder.toInstance();
+        assertEquals(1, genTO.getHashCodeIdentifiers().size());
+        assertEquals("testProperty", genTO.getHashCodeIdentifiers().get(0).getName());
+    }
+
+    @Test
+    public void testAddToStringProperty() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        final GeneratedPropertyBuilderImpl propertyBuilder = new GeneratedPropertyBuilderImpl("testProperty");
+        genTOBuilder.addToStringProperty(propertyBuilder);
+
+        final GeneratedTransferObject genTO = genTOBuilder.toInstance();
+        assertEquals(1, genTO.getToStringIdentifiers().size());
+        assertEquals("testProperty", genTO.getToStringIdentifiers().get(0).getName());
+    }
+
+    @Test
+    public void testSetRestrictions() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        final Restrictions restrictions = new Restrictions() {
+
+            @Override
+            public boolean isEmpty() {
+                return false;
+            }
+
+            @Override
+            public List<RangeConstraint> getRangeConstraints() {
+                return null;
+            }
+
+            @Override
+            public List<PatternConstraint> getPatternConstraints() {
+                return null;
+            }
+
+            @Override
+            public List<LengthConstraint> getLengthConstraints() {
+                return null;
+            }
+        };
+        genTOBuilder.setRestrictions(restrictions);
+        final GeneratedTransferObject genTO = genTOBuilder.toInstance();
+
+        assertNotNull(genTO.getRestrictions());
+    }
+
+    @Test
+    public void testSetSUID() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        final GeneratedPropertyBuilderImpl propertyBuilder = new GeneratedPropertyBuilderImpl("testProperty");
+        genTOBuilder.setSUID(propertyBuilder);
+
+        final GeneratedTransferObject genTO = genTOBuilder.toInstance();
+        assertEquals("testProperty", genTO.getSUID().getName());
+    }
+
+    @Test
+    public void testToStringMethod() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        assertNotNull(genTOBuilder.toString());
+    }
+
+    @Test
+    public void testSetterMethods() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        genTOBuilder.setTypedef(true);
+        genTOBuilder.setIsUnion(true);
+        genTOBuilder.setIsUnionBuilder(true);
+        genTOBuilder.setDescription("test description");
+        genTOBuilder.setModuleName("test-module");
+        genTOBuilder.setReference("http://tools.ietf.org/html/rfc6020");
+        genTOBuilder.setSchemaPath(SchemaPath.ROOT.getPathFromRoot());
+
+        final GeneratedTransferObject genTO = genTOBuilder.toInstance();
+
+        assertTrue(genTO.isTypedef());
+        assertTrue(genTO.isUnionType());
+        assertTrue(genTO.isUnionTypeBuilder());
+        assertEquals("test description", genTO.getDescription());
+        assertEquals("test-module", genTO.getModuleName());
+        assertEquals("http://tools.ietf.org/html/rfc6020", genTO.getReference());
+        assertEquals(SchemaPath.ROOT.getPathFromRoot(), genTO.getSchemaPath());
+    }
+
+    @Test
+    public void testMethodsOfGeneratedTransferObjectImpl() {
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl("org.opendaylight.yangtools.test", "Test");
+        final GeneratedTransferObject genTO = genTOBuilder.toInstance();
+
+        assertNotNull(genTO.toString());
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderTest.java
new file mode 100644 (file)
index 0000000..fe84ce0
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+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.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+
+public class GeneratedTOBuilderTest {
+
+    @Test
+    public void testBuilder() {
+        final GeneratedTOBuilder genTypeBuilder = new GeneratedTOBuilderImpl(
+                "org.opendaylight.controller", "AnnotClassCache");
+
+        genTypeBuilder.setSUID(genTypeBuilder.addProperty("SUID"));
+        genTypeBuilder.addMethod("addCount");
+
+        GeneratedTransferObject genTO = genTypeBuilder.toInstance();
+        genTypeBuilder.setExtendsType(genTO);
+
+        GeneratedPropertyBuilder property = genTypeBuilder
+                .addProperty("customProperty");
+        genTypeBuilder.addHashIdentity(property);
+
+        genTypeBuilder.addEqualsIdentity(property);
+
+        genTypeBuilder.addToStringProperty(property);
+
+        assertNotNull(genTO);
+        assertNotNull(genTO.getProperties());
+    }
+
+    @Test
+    public void testToString() {
+        final GeneratedTOBuilder genTypeBuilder = new GeneratedTOBuilderImpl(
+                "org.opendaylight.controller", "AnnotClassCache");
+        String toString = genTypeBuilder.toString();
+        assertTrue(toString.contains("GeneratedTransferObject"));
+    }
+
+    @Test
+    public void testTransferBuilderToString() {
+        final GeneratedTOBuilder genTypeBuilder1 = new GeneratedTOBuilderImpl(
+                "org.opendaylight.controller", "AnnotClassCache");
+
+        genTypeBuilder1.setTypedef(true);
+        GeneratedTransferObject genTO = genTypeBuilder1.toInstance();
+        String toString = genTO.toString();
+        assertFalse(toString.contains("GeneratedTransferObject"));
+
+        final GeneratedTOBuilder genTypeBuilder2 = new GeneratedTOBuilderImpl(
+                "org.opendaylight.controller", "AnnotClassCache");
+
+        genTypeBuilder2.setTypedef(false);
+        genTO = genTypeBuilder2.toInstance();
+        toString = genTO.toString();
+
+        assertTrue(toString.contains("GeneratedTransferObject"));
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTypeBuilderTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTypeBuilderTest.java
new file mode 100644 (file)
index 0000000..98139db
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+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 java.io.Serializable;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+
+public class GeneratedTypeBuilderTest {
+
+    @Test
+    public void addConstantTest() {
+        GeneratedTypeBuilder generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        // assertNotNull(generatedTypeBuilder.addComment("My comment ..."));
+
+        Constant constant = generatedTypeBuilder.addConstant(Types.typeForClass(String.class), "myConstant",
+                "myConstantValue");
+        // Constant constantx =
+        // generatedTypeBuilder.addConstant(Types.typeForClass(String.class),
+        // "myConstant", "myConstantValue");
+        Constant constant2 = generatedTypeBuilder.addConstant(
+                Types.primitiveType("int", BindingGeneratorUtil.getRestrictions(null)), "myIntConstant", 1);
+
+        Constant constant3 = new ConstantImpl(generatedTypeBuilder, Types.typeForClass(String.class), "myConstant",
+                "myConstantValue");
+        Constant constant4 = new ConstantImpl(generatedTypeBuilder, Types.typeForClass(String.class), "myConstant2",
+                "myConstantValue");
+        Constant constant5 = new ConstantImpl(generatedTypeBuilder, Types.typeForClass(String.class), "myConstant",
+                "myConstantValue2");
+
+        assertNotNull(constant);
+        assertNotNull(constant2);
+        assertNotNull(constant3);
+        assertNotNull(constant4);
+        assertNotNull(constant5);
+        // assertNotNull(constantx);
+        // assertTrue(constant!=constantx);
+
+        assertFalse(constant.equals(null));
+        assertFalse(constant.equals(new Object()));
+        assertTrue(constant.equals(constant));
+        assertTrue(constant.equals(constant3));
+        assertFalse(constant.equals(constant2));
+        assertFalse(constant.equals(constant4));
+        assertFalse(constant.equals(constant5));
+
+        assertTrue(constant.hashCode() == constant.hashCode());
+        assertTrue(constant.hashCode() == constant3.hashCode());
+        assertFalse(constant.hashCode() == constant2.hashCode());
+        assertFalse(constant.hashCode() == constant4.hashCode());
+        assertTrue(constant.hashCode() == constant5.hashCode());
+
+        assertEquals(
+                "Constant [type=Type (java.lang.String), name=myConstant, value=myConstantValue, definingType=my.package.MyName]",
+                constant.toString());
+
+        assertEquals("Type (java.lang.String) myConstant myConstantValue", constant.toFormattedString());
+
+        GeneratedType instance = generatedTypeBuilder.toInstance();
+        List<Constant> constantDefinitions = instance.getConstantDefinitions();
+        assertNotNull(constantDefinitions);
+        assertEquals(2, constantDefinitions.size());
+        assertTrue(constantDefinitions.contains(constant));
+        assertTrue(constantDefinitions.contains(constant2));
+        assertTrue(constantDefinitions.contains(constant3));
+        assertFalse(constantDefinitions.contains(constant4));
+        assertFalse(constantDefinitions.contains(constant5));
+
+        assertEquals("myConstant", constant.getName());
+        assertEquals("myConstantValue", constant.getValue());
+        assertEquals(Types.typeForClass(String.class), constant.getType());
+        assertEquals(generatedTypeBuilder, constant.getDefiningType());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addConstantIllegalArgumentTest() {
+        GeneratedTypeBuilder generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+        generatedTypeBuilder.addConstant(Types.typeForClass(String.class), null, "myConstantValue");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addConstantIllegalArgumentTest2() {
+        GeneratedTypeBuilder generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+        generatedTypeBuilder.addConstant(null, "myConstantName", "myConstantValue");
+    }
+
+    @Test
+    public void generatedTypeBuilderEqualsAndHashCodeTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+        GeneratedTypeBuilderImpl generatedTypeBuilder2 = new GeneratedTypeBuilderImpl("my.package", "MyName");
+        GeneratedTypeBuilderImpl generatedTypeBuilder3 = new GeneratedTypeBuilderImpl("my.package", "MyName2");
+        GeneratedTypeBuilderImpl generatedTypeBuilder4 = new GeneratedTypeBuilderImpl("my.package2", "MyName");
+
+        assertFalse(generatedTypeBuilder.equals(null));
+        assertFalse(generatedTypeBuilder.equals(new Object()));
+        assertTrue(generatedTypeBuilder.equals(generatedTypeBuilder));
+        assertTrue(generatedTypeBuilder.equals(generatedTypeBuilder2));
+
+        assertTrue(generatedTypeBuilder.hashCode() == generatedTypeBuilder.hashCode());
+        assertTrue(generatedTypeBuilder.hashCode() == generatedTypeBuilder2.hashCode());
+        assertFalse(generatedTypeBuilder.hashCode() == generatedTypeBuilder3.hashCode());
+        assertFalse(generatedTypeBuilder.hashCode() == generatedTypeBuilder4.hashCode());
+
+    }
+
+    @Test
+    public void addPropertyTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        GeneratedPropertyBuilder propertyBuilder = generatedTypeBuilder.addProperty("myProperty");
+        GeneratedPropertyBuilder propertyBuilder2 = generatedTypeBuilder.addProperty("myProperty2");
+        // GeneratedPropertyBuilder propertyBuilderNull =
+        // generatedTypeBuilder.addProperty(null);
+
+        assertNotNull(propertyBuilder);
+        assertNotNull(propertyBuilder2);
+        // assertNotNull(propertyBuilderNull);
+
+        assertTrue(generatedTypeBuilder.containsProperty("myProperty"));
+        assertTrue(generatedTypeBuilder.containsProperty("myProperty2"));
+        assertFalse(generatedTypeBuilder.containsProperty("myProperty3"));
+
+        GeneratedType instance = generatedTypeBuilder.toInstance();
+        List<GeneratedProperty> properties = instance.getProperties();
+
+        assertEquals(2, properties.size());
+
+        assertTrue(properties.contains(propertyBuilder.toInstance(instance)));
+        assertTrue(properties.contains(propertyBuilder2.toInstance(instance)));
+        // assertTrue(properties.contains(propertyBuilderNull.toInstance(instance)));
+        assertFalse(properties.contains(new GeneratedPropertyBuilderImpl("myProperty3").toInstance(instance)));
+
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addMethodIllegalArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+        generatedTypeBuilder.addMethod(null);
+    }
+
+    @Test
+    public void addMethodTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        MethodSignatureBuilder methodBuilder = generatedTypeBuilder.addMethod("myMethodName");
+        MethodSignatureBuilder methodBuilder2 = generatedTypeBuilder.addMethod("myMethodName2");
+
+        assertNotNull(methodBuilder);
+        assertNotNull(methodBuilder2);
+
+        assertTrue(generatedTypeBuilder.containsMethod("myMethodName"));
+        assertTrue(generatedTypeBuilder.containsMethod("myMethodName2"));
+        assertFalse(generatedTypeBuilder.containsMethod("myMethodName3"));
+
+        GeneratedType instance = generatedTypeBuilder.toInstance();
+        List<MethodSignature> methodDefinitions = instance.getMethodDefinitions();
+
+        assertEquals(2, methodDefinitions.size());
+
+        assertTrue(methodDefinitions.contains(methodBuilder.toInstance(instance)));
+        assertTrue(methodDefinitions.contains(methodBuilder2.toInstance(instance)));
+        assertFalse(methodDefinitions.contains(new MethodSignatureBuilderImpl("myMethodName3").toInstance(instance)));
+
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addEnumerationIllegalArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addEnumeration(null);
+    }
+
+    @Test
+    public void addEnumerationTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        EnumBuilder enumBuilder = generatedTypeBuilder.addEnumeration("myEnumName");
+        EnumBuilder enumBuilder2 = generatedTypeBuilder.addEnumeration("myEnumName2");
+
+        assertNotNull(enumBuilder);
+        assertNotNull(enumBuilder2);
+
+        GeneratedType instance = generatedTypeBuilder.toInstance();
+        List<Enumeration> enumerations = instance.getEnumerations();
+
+        assertEquals(2, enumerations.size());
+
+        assertTrue(enumerations.contains(enumBuilder.toInstance(instance)));
+        assertTrue(enumerations.contains(enumBuilder2.toInstance(instance)));
+        assertFalse(enumerations.contains(new EnumerationBuilderImpl("my.package", "myEnumName3").toInstance(instance)));
+
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addImplementsTypeIllegalArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addImplementsType(null);
+    }
+
+    @Test
+    public void addImplementsTypeTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        assertEquals(generatedTypeBuilder,
+                generatedTypeBuilder.addImplementsType(Types.typeForClass(Serializable.class)));
+        assertEquals(generatedTypeBuilder, generatedTypeBuilder.addImplementsType(Types.typeForClass(Runnable.class)));
+
+        GeneratedType instance = generatedTypeBuilder.toInstance();
+        List<Type> implementTypes = instance.getImplements();
+
+        assertEquals(2, implementTypes.size());
+
+        assertTrue(implementTypes.contains(Types.typeForClass(Serializable.class)));
+        assertTrue(implementTypes.contains(Types.typeForClass(Runnable.class)));
+        assertFalse(implementTypes.contains(Types.typeForClass(Throwable.class)));
+
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addEnclosingTransferObjectIllegalArgumentTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addEnclosingTransferObject((String) null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void addEnclosingTransferObjectIllegalArgumentTest2() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.addEnclosingTransferObject((GeneratedTOBuilder) null);
+    }
+
+    @Test
+    public void addEnclosingTransferObjectTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        GeneratedTOBuilder enclosingTransferObject = generatedTypeBuilder.addEnclosingTransferObject("myTOName");
+        GeneratedTOBuilder enclosingTransferObject2 = generatedTypeBuilder.addEnclosingTransferObject("myTOName2");
+        assertEquals(generatedTypeBuilder, generatedTypeBuilder.addEnclosingTransferObject(new GeneratedTOBuilderImpl(
+                generatedTypeBuilder.getFullyQualifiedName(), "myTOName3")));
+
+        assertNotNull(enclosingTransferObject);
+        assertNotNull(enclosingTransferObject2);
+
+        GeneratedType instance = generatedTypeBuilder.toInstance();
+        List<GeneratedType> enclosedTypes = instance.getEnclosedTypes();
+
+        assertEquals(3, enclosedTypes.size());
+
+        assertTrue(enclosedTypes.contains(enclosingTransferObject.toInstance()));
+        assertTrue(enclosedTypes.contains(enclosingTransferObject2.toInstance()));
+        assertTrue(enclosedTypes.contains(new GeneratedTOBuilderImpl(generatedTypeBuilder.getFullyQualifiedName(),
+                "myTOName3").toInstance()));
+        assertFalse(enclosedTypes.contains(new GeneratedTOBuilderImpl(generatedTypeBuilder.getFullyQualifiedName(),
+                "myTOName4").toInstance()));
+
+    }
+
+    @Test
+    public void generatedTypeTest() {
+        GeneratedTypeBuilderImpl generatedTypeBuilder = new GeneratedTypeBuilderImpl("my.package", "MyName");
+
+        generatedTypeBuilder.setDescription("My description ...");
+        generatedTypeBuilder.setModuleName("myModuleName");
+        generatedTypeBuilder.setReference("myReference");
+        generatedTypeBuilder.setSchemaPath(SchemaPath.create(true, QName.create("/path")).getPathFromRoot());
+        assertNotNull(generatedTypeBuilder.addComment("My comment.."));
+
+        assertEquals(
+                "GeneratedTransferObject [packageName=my.package, name=MyName, comment=My comment.., annotations=[], implements=[], enclosedTypes=[], constants=[], enumerations=[], properties=, methods=[]]",
+                generatedTypeBuilder.toString());
+
+        GeneratedType instance = generatedTypeBuilder.toInstance();
+
+        assertEquals("My description ...", instance.getDescription());
+        assertEquals("myModuleName", instance.getModuleName());
+        assertEquals("myReference", instance.getReference());
+        assertEquals(SchemaPath.create(true, QName.create("/path")).getPathFromRoot(), instance.getSchemaPath());
+        assertEquals("My comment..", instance.getComment());
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodParameterImplTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodParameterImplTest.java
new file mode 100644 (file)
index 0000000..b63a8b7
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+public class MethodParameterImplTest {
+
+    MethodParameterImpl parameter1, parameter2, parameter3, parameter4;
+    int hash1, hash2, hash3, hash4;
+
+    @Before
+    public void Setup() {
+        String name = "customParameter";
+        Type type = Types.STRING;
+        parameter1 = new MethodParameterImpl(name, type);
+        parameter2 = new MethodParameterImpl(name, type);
+        parameter3 = new MethodParameterImpl(name, null);
+        parameter4 = new MethodParameterImpl(null, type);
+
+        hash1 = parameter1.hashCode();
+        hash2 = parameter2.hashCode();
+        hash3 = parameter3.hashCode();
+        hash4 = parameter4.hashCode();
+    }
+
+    @Test
+    public void testToString() {
+        String toString = parameter1.toString();
+        assertTrue(toString.contains("MethodParameter"));
+    }
+
+    @Test
+    public void testEquals() {
+        assertTrue(parameter1.equals(parameter1));
+        assertTrue(parameter1.equals(parameter2));
+        assertFalse(parameter1.equals("string"));
+        assertFalse(parameter1.equals(null));
+        assertFalse(parameter1.equals(parameter3));
+        assertFalse(parameter2.equals(parameter4));
+        assertFalse(parameter4.equals(parameter2));
+        assertFalse(parameter3.equals(parameter2));
+    }
+
+    @Test
+    public void testHashCode() {
+        assertEquals(hash1,hash2);
+        assertTrue(!(hash1 == hash3));
+        assertTrue(!(hash1 == hash4));
+    }
+}
+
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureBuilderImplTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureBuilderImplTest.java
new file mode 100644 (file)
index 0000000..16f6e03
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+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.sal.binding.model.api.MethodSignature;
+
+public class MethodSignatureBuilderImplTest {
+
+    @Test
+    public void testCreateNewInstance() {
+        final MethodSignatureBuilderImpl signatureBuilderImpl = new MethodSignatureBuilderImpl("testMethod");
+        assertNotNull(signatureBuilderImpl);
+    }
+
+    @Test
+    public void testSetAbstractMethod() {
+        final MethodSignatureBuilderImpl signatureBuilderImpl = new MethodSignatureBuilderImpl("testMethod");
+        signatureBuilderImpl.setAbstract(true);
+        final MethodSignature methodSignature = signatureBuilderImpl.toInstance(null);
+        assertTrue(methodSignature.isAbstract());
+    }
+
+    @Test
+    public void testAddParameterMethod() {
+        final MethodSignatureBuilderImpl signatureBuilderImpl = new MethodSignatureBuilderImpl("testMethod");
+        final GeneratedTypeBuilderImpl ipAddressType = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test", "IpAddress");
+        signatureBuilderImpl.addParameter(ipAddressType, "ipAddress");
+        final MethodSignature methodSignature = signatureBuilderImpl.toInstance(null);
+        assertEquals("ipAddress", methodSignature.getParameters().get(0).getName());
+    }
+
+    @Test
+    public void testHashCodeEqualsToStringMethods() {
+        final MethodSignatureBuilderImpl signatureBuilderImpl = new MethodSignatureBuilderImpl("testMethod");
+        final MethodSignatureBuilderImpl signatureBuilderImpl2 = new MethodSignatureBuilderImpl("testMethod");
+        final MethodSignatureBuilderImpl signatureBuilderImpl3 = new MethodSignatureBuilderImpl("testMethod2");
+        final MethodSignatureBuilderImpl signatureBuilderImpl4 = new MethodSignatureBuilderImpl(null);
+        final MethodSignatureBuilderImpl signatureBuilderImpl5 = signatureBuilderImpl;
+        final MethodSignatureBuilderImpl signatureBuilderImpl6 = new MethodSignatureBuilderImpl("testMethod");
+        final GeneratedTypeBuilderImpl returnType = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test", "Address");
+        signatureBuilderImpl6.setReturnType(returnType);
+
+        assertEquals(signatureBuilderImpl.hashCode(), signatureBuilderImpl2.hashCode());
+
+        assertTrue(signatureBuilderImpl.equals(signatureBuilderImpl2));
+        assertFalse(signatureBuilderImpl.equals(signatureBuilderImpl3));
+        assertFalse(signatureBuilderImpl.equals(signatureBuilderImpl4));
+        assertFalse(signatureBuilderImpl4.equals(signatureBuilderImpl));
+        assertTrue(signatureBuilderImpl.equals(signatureBuilderImpl5));
+        assertFalse(signatureBuilderImpl4.equals("test"));
+        assertFalse(signatureBuilderImpl4.equals(signatureBuilderImpl));
+        assertFalse(signatureBuilderImpl6.equals(signatureBuilderImpl));
+        assertFalse(signatureBuilderImpl.equals(signatureBuilderImpl6));
+
+        assertNotNull(signatureBuilderImpl.toString());
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureBuilderTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureBuilderTest.java
new file mode 100644 (file)
index 0000000..433e94f
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+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.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+
+public class MethodSignatureBuilderTest {
+
+    MethodSignatureBuilder builder1, builder2, builder3, builder4;
+    int hash1, hash2, hash3;
+
+    @Before
+    public void setup() {
+        builder1 = new MethodSignatureBuilderImpl("methodSignature");
+        builder2 = new MethodSignatureBuilderImpl("otherMethodSignature");
+        builder2.setReturnType(Types.STRING);
+        builder3 = new MethodSignatureBuilderImpl(null);
+        builder3.setAbstract(false);
+        builder4 = new MethodSignatureBuilderImpl("otherMethodSignature");
+        builder4.setReturnType(Types.BOOLEAN);
+
+        hash1 = builder1.hashCode();
+        hash2 = builder2.hashCode();
+        hash3 = builder3.hashCode();
+    }
+
+    @Test
+    public void testAddParameter() {
+        Type type = Types.STRING;
+        String name = "customParam";
+        builder1.addParameter(type, name);
+        Type methodType = Types.voidType();
+        MethodSignature signature = builder1.toInstance(methodType);
+        assertNotNull(signature);
+    }
+
+    @Test
+    public void testToString() {
+        String toString = builder1.toString();
+        assertTrue(toString.contains("MethodSignatureBuilderImpl"));
+    }
+
+    @Test
+    public void testHashCode() {
+        assertEquals(hash1, hash1);
+    }
+
+    @Test
+    public void testEquals() {
+        assertTrue(builder1.equals(builder1));
+        assertFalse(builder1.equals(builder2));
+        assertFalse(builder1.equals(null));
+        assertFalse(builder1.equals("string"));
+        assertFalse(builder3.equals(builder2));
+        assertFalse(builder4.equals(builder2));
+    }
+}
diff --git a/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureImplTest.java b/code-generator/binding-generator-util/src/test/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/MethodSignatureImplTest.java
new file mode 100644 (file)
index 0000000..f7ef7b1
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.binding.generator.util.generated.type.builder;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature.Parameter;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+public class MethodSignatureImplTest {
+
+    MethodSignatureImpl signature1, signature2, signature3, signature4;
+    int hash1, hash4;
+
+    @Before
+    public void setup() {
+        Type type = Types.STRING;
+        String name = "customMethod";
+        List<AnnotationType> annotations = new ArrayList<>();
+        String comment = "This is just a comment";
+        AccessModifier accessModifier = AccessModifier.PUBLIC;
+        Type returnType = Types.STRING;
+        List<Parameter> params = new ArrayList<>();
+        boolean isFinal = false;
+        boolean isAbstract = false;
+        boolean isStatic = false;
+
+        signature1 = new MethodSignatureImpl(type, name, annotations, comment,
+                accessModifier, returnType, params, isFinal, isAbstract,
+                isStatic);
+        signature2 = new MethodSignatureImpl(type, name, annotations, comment,
+                accessModifier, returnType, params, isFinal, isAbstract,
+                isStatic);
+        returnType = null;
+        signature3 = new MethodSignatureImpl(type, name, annotations, comment,
+                accessModifier, returnType, params, isFinal, isAbstract,
+                isStatic);
+        name = null;
+        signature4 = new MethodSignatureImpl(type, name, annotations, comment,
+                accessModifier, returnType, params, isFinal, isAbstract,
+                isStatic);
+
+        hash1 = signature1.hashCode();
+        hash4 = signature4.hashCode();
+    }
+
+    @Test
+    public void testToString() {
+        String toString = signature1.toString();
+        assertTrue(toString.contains("MethodSignatureImpl"));
+    }
+
+    @Test
+    public void testHashCode() {
+        assertEquals(hash1, hash1);
+        assertTrue(!(hash1 == hash4));
+    }
+
+    @Test
+    public void testEquals() {
+        assertTrue(signature1.equals(signature1));
+        assertTrue(signature1.equals(signature2));
+        assertFalse(signature1.equals(signature3));
+        assertFalse(signature3.equals(signature1));
+        assertFalse(signature1.equals(null));
+        assertFalse(signature1.equals(signature4));
+        assertFalse(signature4.equals(signature1));
+        assertFalse(signature1.equals(Types.STRING));
+    }
+
+}
diff --git a/code-generator/binding-generator-util/src/test/resources/module.yang b/code-generator/binding-generator-util/src/test/resources/module.yang
new file mode 100644 (file)
index 0000000..928efa6
--- /dev/null
@@ -0,0 +1,22 @@
+module module-name-test {
+
+    namespace "urn:m*o+d,u;l=e.n/a-m@e.t$e#s't.case.1digit";
+    prefix "pref";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-09-10 {
+    }
+    
+    typedef tpdf {
+       type string;
+    }
+    
+    container cont-outter {
+       container cont-inner {
+       }    
+    }
+    
+    
+}
\ No newline at end of file
diff --git a/code-generator/binding-java-api-generator/pom.xml b/code-generator/binding-java-api-generator/pom.xml
new file mode 100644 (file)
index 0000000..541d2f5
--- /dev/null
@@ -0,0 +1,108 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>binding-java-api-generator</artifactId>
+
+    <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>
+                        <Import-Package>
+                            !org.sonatype.plexus.build.incremental,
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+<!--      <plugin>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>enforce</id>
+            <phase>none</phase>
+          </execution>
+        </executions>
+      </plugin> -->
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.xtend</groupId>
+            <artifactId>org.eclipse.xtend.lib</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.sonatype.plexus</groupId>
+            <artifactId>plexus-build-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.codehaus.plexus</groupId>
+            <artifactId>plexus-container-default</artifactId>
+            <version>1.5.6</version>
+            <scope>provided</scope>
+            <exclusions>
+                <!-- plexus-build-api pulls in version 1.5.8, while this pulls in 3.0.20.
+                     Dependency convergence would break if we did not specify this. -->
+                <exclusion>
+                    <groupId>org.codehaus.plexus</groupId>
+                    <artifactId>plexus-utils</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractBigRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractBigRangeGenerator.java
new file mode 100644 (file)
index 0000000..737aadf
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+import com.google.common.collect.Range;
+import java.util.Collection;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+
+/**
+ * Abstract base for generators which require instantiation of boundary values
+ * to check. These are implemented by generating an array constant within the
+ * class, which contains {@link Range} instances, which hold pre-instantiated
+ * boundary values.
+ *
+ * @param <T> type of the class
+ */
+abstract class AbstractBigRangeGenerator<T extends Number & Comparable<T>> extends AbstractRangeGenerator<T> {
+    private static final String RANGE = Range.class.getName();
+
+    protected AbstractBigRangeGenerator(final Class<T> typeClass) {
+        super(typeClass);
+    }
+
+    private StringBuilder itemType() {
+        return new StringBuilder(RANGE).append('<').append(getTypeName()).append('>');
+    }
+
+    private StringBuilder arrayType() {
+        return new StringBuilder(itemType()).append("[]");
+    }
+
+    @Override
+    protected final String generateRangeCheckerImplementation(final String checkerName, @Nonnull final Collection<RangeConstraint> constraints) {
+        final String fieldName = checkerName.toUpperCase() + "_RANGES";
+        final StringBuilder sb = new StringBuilder();
+
+        // Field to hold the Range objects in an array
+        sb.append("private static final ").append(arrayType()).append(' ').append(fieldName).append(";\n");
+
+        // Static initializer block for the array
+        sb.append("static {\n");
+        sb.append("    @SuppressWarnings(\"unchecked\")\n");
+        sb.append("    final ").append(arrayType()).append(" a = (").append(arrayType())
+        .append(") java.lang.reflect.Array.newInstance(").append(RANGE).append(".class, ").append(constraints.size()).append(");\n");
+
+        int i = 0;
+        for (RangeConstraint r : constraints) {
+            final String min = format(getValue(r.getMin()));
+            final String max = format(getValue(r.getMax()));
+
+            sb.append("    a[").append(i++).append("] = ").append(RANGE).append(".closed(").append(min).append(", ").append(max).append(");\n");
+        }
+
+        sb.append("    ").append(fieldName).append(" = a;\n");
+        sb.append("}\n");
+
+        // Static enforcement method
+        sb.append("private static void ").append(checkerName).append("(final ").append(getTypeName()).append(" value) {\n");
+        sb.append("    for (").append(itemType()).append(" r : ").append(fieldName).append(") {\n");
+        sb.append("        if (r.contains(value)) {\n");
+        sb.append("            return;\n");
+        sb.append("        }\n");
+        sb.append("    }\n");
+        sb.append("    throw new IllegalArgumentException(String.format(\"Invalid range: %s, expected: %s.\", value, java.util.Arrays.asList(").append(fieldName).append(")));\n");
+        sb.append("}\n");
+
+        return sb.toString();
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractPrimitiveRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractPrimitiveRangeGenerator.java
new file mode 100644 (file)
index 0000000..a040bee
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Range;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractPrimitiveRangeGenerator<T extends Number & Comparable<T>> extends AbstractRangeGenerator<T> {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractPrimitiveRangeGenerator.class);
+    private final String primitiveName;
+    private final T minValue;
+    private final T maxValue;
+
+    protected AbstractPrimitiveRangeGenerator(final Class<T> typeClass, final String primitiveName, final T minValue, final T maxValue) {
+        super(typeClass);
+        this.primitiveName = Preconditions.checkNotNull(primitiveName);
+        this.minValue = Preconditions.checkNotNull(minValue);
+        this.maxValue = Preconditions.checkNotNull(maxValue);
+    }
+
+    /**
+     * Return the name of the primitive type, as known by the Java language.
+     *
+     * @return Primitive type name
+     */
+    @Nonnull protected final String getPrimitiveName() {
+        return primitiveName;
+    }
+
+    private boolean needsMaximumEnforcement(final T maxToEnforce) {
+        return maxValue.compareTo(maxToEnforce) > 0;
+    }
+
+    private boolean needsMinimumEnforcement(final T minToEnforce) {
+        return minValue.compareTo(minToEnforce) < 0;
+    }
+
+    private Collection<String> createExpressions(final Collection<RangeConstraint> constraints) {
+        final Collection<String> ret = new ArrayList<>(constraints.size());
+
+        for (RangeConstraint r : constraints) {
+            final T min = getValue(r.getMin());
+            final boolean needMin = needsMinimumEnforcement(min);
+
+            final T max = getValue(r.getMax());
+            final boolean needMax = needsMaximumEnforcement(max);
+
+            if (!needMin && !needMax) {
+                LOG.debug("Type {} indicates [{}, {}] does not require enforcement", getTypeName(), min, max);
+                continue;
+            }
+
+            final StringBuilder sb = new StringBuilder();
+            if (needMin) {
+                sb.append("value >= ").append(format(min));
+            }
+            if (needMax) {
+                if (needMin) {
+                    sb.append(" && ");
+                }
+                sb.append("value <= ").append(format(max));
+            }
+
+            ret.add(sb.toString());
+        }
+
+        return ret;
+    }
+
+    private String createRangeString(final Collection<RangeConstraint> constraints) {
+        final List<Range<T>> ranges = new ArrayList<>(constraints.size());
+
+        for (RangeConstraint c : constraints) {
+            ranges.add(Range.closed(getValue(c.getMin()), getValue(c.getMax())));
+        }
+
+        return ranges.toString();
+    }
+
+    @Override
+    protected final String generateRangeCheckerImplementation(final String checkerName, final Collection<RangeConstraint> constraints) {
+        final StringBuilder sb = new StringBuilder();
+        final Collection<String> expressions = createExpressions(constraints);
+
+        sb.append("private static void ").append(checkerName).append("(final ").append(primitiveName).append(" value) {\n");
+
+        if (!expressions.isEmpty()) {
+            for (String exp : expressions) {
+                sb.append("    if (").append(exp).append(") {\n");
+                sb.append("        return;\n");
+                sb.append("    }\n");
+            }
+
+            sb.append("    throw new IllegalArgumentException(String.format(\"Invalid range: %s, expected: ")
+              .append(createRangeString(constraints)).append(".\", value));\n");
+        }
+
+        sb.append("}\n");
+
+        return sb.toString();
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractRangeGenerator.java
new file mode 100644 (file)
index 0000000..8933d94
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import java.util.Collection;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractRangeGenerator<T extends Number & Comparable<T>> {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractRangeGenerator.class);
+    private static final Map<String, AbstractRangeGenerator<?>> GENERATORS;
+
+    private static void addGenerator(final Builder<String, AbstractRangeGenerator<?>> b, final AbstractRangeGenerator<?> generator) {
+        b.put(generator.getTypeClass().getCanonicalName(), generator);
+    }
+
+    static {
+        final Builder<String, AbstractRangeGenerator<?>> b = ImmutableMap.<String, AbstractRangeGenerator<?>> builder();
+        addGenerator(b, new ByteRangeGenerator());
+        addGenerator(b, new ShortRangeGenerator());
+        addGenerator(b, new IntegerRangeGenerator());
+        addGenerator(b, new LongRangeGenerator());
+        addGenerator(b, new BigDecimalRangeGenerator());
+        addGenerator(b, new BigIntegerRangeGenerator());
+        GENERATORS = b.build();
+    }
+
+    private final Class<T> type;
+
+    protected AbstractRangeGenerator(final Class<T> typeClass) {
+        this.type = Preconditions.checkNotNull(typeClass);
+    }
+
+    static AbstractRangeGenerator<?> forType(@Nonnull final Type type) {
+        final ConcreteType javaType = TypeUtils.getBaseYangType(type);
+        return GENERATORS.get(javaType.getFullyQualifiedName());
+    }
+
+    /**
+     * Return the type's class.
+     *
+     * @return A class object
+     */
+    @Nonnull protected final Class<T> getTypeClass() {
+        return type;
+    }
+
+    /**
+     * Return the type's fully-qualified name.
+     *
+     * @return Fully-qualified name
+     */
+    @Nonnull protected final String getTypeName() {
+        return type.getName();
+    }
+
+    /**
+     * Return the value in the native type from a particular Number instance.
+     *
+     * @param value Value as a Number
+     * @return Value in native format.
+     */
+    @Nonnull protected final T getValue(final Number value) {
+        if (type.isInstance(value)) {
+            return type.cast(value);
+        }
+
+        LOG.debug("Converting value {} from {} to {}", value, value.getClass(), type);
+        final T ret = convert(value);
+
+        // Check if the conversion lost any precision by performing conversion the other way around
+        final AbstractRangeGenerator<?> gen = GENERATORS.get(value.getClass().getName());
+        final Number check = gen.convert(ret);
+        if (!value.equals(check)) {
+            LOG.warn("Number class conversion from {} to {} truncated value {} to {}", value.getClass(), type, value, ret);
+        }
+
+        return ret;
+    }
+
+    // FIXME: Once BUG-3399 is fixed, we should never need this
+    @Deprecated
+    protected abstract T convert(final Number value);
+
+    /**
+     * Format a value into a Java-compilable expression which results in the appropriate
+     * type.
+     *
+     * @param value Number value
+     * @return Java language string representation
+     */
+    @Nonnull protected abstract String format(final T value);
+
+    /**
+     * Generate the checker method source code.
+     * @param checkerName Name of the checker method.
+     * @param constraints Restrictions which need to be applied.
+     * @return Method source code.
+     */
+    @Nonnull protected abstract String generateRangeCheckerImplementation(@Nonnull final String checkerName, @Nonnull final Collection<RangeConstraint> constraints);
+
+    private static String rangeCheckerName(final String member) {
+        return "check" + member + "Range";
+    }
+
+    String generateRangeChecker(@Nonnull final String member, @Nonnull final Collection<RangeConstraint> constraints) {
+        Preconditions.checkArgument(!constraints.isEmpty(), "Restrictions may not be empty");
+        return generateRangeCheckerImplementation(rangeCheckerName(member), constraints);
+    }
+
+    String generateRangeCheckerCall(@Nonnull final String member, @Nonnull final String valueReference) {
+        return rangeCheckerName(member) + '(' + valueReference + ");\n";
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractSubIntegerRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AbstractSubIntegerRangeGenerator.java
new file mode 100644 (file)
index 0000000..ef87454
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+abstract class AbstractSubIntegerRangeGenerator<T extends Number & Comparable<T>> extends AbstractPrimitiveRangeGenerator<T> {
+    protected AbstractSubIntegerRangeGenerator(final Class<T> typeClass, final String primitiveName, final T minValue, final T maxValue) {
+        super(typeClass, primitiveName, minValue, maxValue);
+    }
+
+    @Override
+    protected final String format(final T value) {
+        // Make sure the number constant is cast to the corresponding primitive type
+        return '(' + getPrimitiveName() + ')' + value;
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AlphabeticallyTypeMemberComparator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/AlphabeticallyTypeMemberComparator.java
new file mode 100644 (file)
index 0000000..058ba9a
--- /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.sal.java.api.generator;
+
+import java.util.Comparator;
+import org.opendaylight.yangtools.sal.binding.model.api.TypeMember;
+
+/**
+ * Alphabetically type member {@link Comparator} which provides sorting by name for type members
+ * (variables and methods) in generated class.
+ *
+ * @param <T>
+ */
+public class AlphabeticallyTypeMemberComparator<T extends TypeMember> implements Comparator<T>{
+
+    @Override
+    public int compare(T member1, T member2) {
+        return member1.getName().compareTo(member2.getName());
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BaseTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BaseTemplate.xtend
new file mode 100644 (file)
index 0000000..161857f
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * 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.sal.java.api.generator
+
+import com.google.common.base.CharMatcher
+import com.google.common.base.Splitter
+import java.util.Arrays
+import java.util.Collection
+import java.util.HashMap
+import java.util.List
+import java.util.Map
+import java.util.StringTokenizer
+import java.util.regex.Pattern
+import org.opendaylight.yangtools.binding.generator.util.Types
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+
+abstract class BaseTemplate {
+    protected val GeneratedType type;
+    protected val Map<String, String> importMap;
+
+    private static final char NEW_LINE = '\n'
+    private static final CharMatcher NL_MATCHER = CharMatcher.is(NEW_LINE)
+    private static final CharMatcher TAB_MATCHER = CharMatcher.is('\t')
+    private static final Pattern SPACES_PATTERN = Pattern.compile(" +")
+    private static final Splitter NL_SPLITTER = Splitter.on(NL_MATCHER)
+
+    new(GeneratedType _type) {
+        if (_type == null) {
+            throw new IllegalArgumentException("Generated type reference cannot be NULL!")
+        }
+        this.type = _type;
+        this.importMap = new HashMap<String,String>()
+    }
+
+    def packageDefinition() '''package Â«type.packageName»;'''
+
+    final public def generate() {
+        val _body = body()
+        '''
+            Â«packageDefinition»
+            Â«imports»
+
+            Â«_body»
+        '''.toString
+    }
+
+    protected def imports() '''
+        Â«IF !importMap.empty»
+            Â«FOR entry : importMap.entrySet»
+                Â«IF !hasSamePackage(entry.value)»
+                    import Â«entry.value».«entry.key»;
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+
+    '''
+
+    /**
+     * Checks if packages of generated type and imported type is the same
+     *
+     * @param importedTypePackageNam
+     * the package name of imported type
+     * @return true if the packages are the same false otherwise
+     */
+    final private def boolean hasSamePackage(String importedTypePackageName) {
+        return type.packageName.equals(importedTypePackageName);
+    }
+
+    protected abstract def CharSequence body();
+
+    // Helper patterns
+    final protected def fieldName(GeneratedProperty property) '''_«property.name»'''
+
+    final protected def propertyNameFromGetter(MethodSignature getter) {
+        var int prefix;
+        if (getter.name.startsWith("is")) {
+            prefix = 2
+        } else if (getter.name.startsWith("get")) {
+            prefix = 3
+        } else {
+            throw new IllegalArgumentException("Not a getter")
+        }
+        return getter.name.substring(prefix).toFirstLower;
+    }
+
+    /**
+     * Template method which generates the getter method for <code>field</code>
+     *
+     * @param field
+     * generated property with data about field which is generated as the getter method
+     * @return string with the getter method source code in JAVA format
+     */
+    final protected def getterMethod(GeneratedProperty field) {
+        '''
+            public Â«field.returnType.importedName» Â«field.getterMethodName»() {
+                Â«IF field.returnType.importedName.contains("[]")»
+                return Â«field.fieldName» == null ? null : Â«field.fieldName».clone();
+                Â«ELSE»
+                return Â«field.fieldName»;
+                Â«ENDIF»
+            }
+        '''
+    }
+
+    final protected def getterMethodName(GeneratedProperty field) {
+        val prefix = if(field.returnType.equals(Types.BOOLEAN)) "is" else "get"
+        return '''«prefix»«field.name.toFirstUpper»'''
+    }
+
+    /**
+     * Template method which generates the setter method for <code>field</code>
+     *
+     * @param field
+     * generated property with data about field which is generated as the setter method
+     * @return string with the setter method source code in JAVA format
+     */
+    final protected def setterMethod(GeneratedProperty field) '''
+        Â«val returnType = field.returnType.importedName»
+        public Â«type.name» set«field.name.toFirstUpper»(«returnType» value) {
+            this.«field.fieldName» = value;
+            return this;
+        }
+    '''
+
+    final protected def importedName(Type intype) {
+        GeneratorUtil.putTypeIntoImports(type, intype, importMap);
+        GeneratorUtil.getExplicitType(type, intype, importMap)
+    }
+
+    final protected def importedName(Class<?> cls) {
+        importedName(Types.typeForClass(cls))
+    }
+
+    /**
+     * Template method which generates method parameters with their types from <code>parameters</code>.
+     *
+     * @param parameters
+     * group of generated property instances which are transformed to the method parameters
+     * @return string with the list of the method parameters with their types in JAVA format
+     */
+    def final protected asArgumentsDeclaration(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
+        returnType.importedName» Â«parameter.fieldName»«ENDFOR»«ENDIF»'''
+
+    /**
+     * Template method which generates sequence of the names of the class attributes from <code>parameters</code>.
+     *
+     * @param parameters
+     * group of generated property instances which are transformed to the sequence of parameter names
+     * @return string with the list of the parameter names of the <code>parameters</code>
+     */
+    def final protected asArguments(Iterable<GeneratedProperty> parameters) '''«IF !parameters.empty»«FOR parameter : parameters SEPARATOR ", "»«parameter.
+        fieldName»«ENDFOR»«ENDIF»'''
+
+    /**
+     * Template method which generates JAVA comments.
+     *
+     * @param comment string with the comment for whole JAVA class
+     * @return string with comment in JAVA format
+     */
+    def protected CharSequence asJavadoc(String comment) {
+        if(comment == null) return ''
+        var txt = comment
+
+        txt = comment.trim
+        txt = formatToParagraph(txt)
+
+        return '''
+            Â«wrapToDocumentation(txt)»
+        '''
+    }
+
+    def String wrapToDocumentation(String text) {
+        if (text.empty)
+            return ""
+
+        val StringBuilder sb = new StringBuilder("/**")
+        sb.append(NEW_LINE)
+
+        for (String t : NL_SPLITTER.split(text)) {
+            sb.append(" *")
+            if (!t.isEmpty()) {
+                sb.append(' ');
+                sb.append(t)
+            }
+            sb.append(NEW_LINE)
+        }
+        sb.append(" */")
+
+        return sb.toString
+    }
+
+    def protected String formatDataForJavaDoc(GeneratedType type) {
+        val typeDescription = type.getDescription().encodeJavadocSymbols;
+
+        return '''
+            Â«IF !typeDescription.nullOrEmpty»
+            Â«typeDescription»
+            Â«ENDIF»
+        '''.toString
+    }
+
+    private static final CharMatcher AMP_MATCHER = CharMatcher.is('&');
+    private static final CharMatcher GT_MATCHER = CharMatcher.is('>');
+    private static final CharMatcher LT_MATCHER = CharMatcher.is('<');
+
+    def encodeJavadocSymbols(String description) {
+        if (description.nullOrEmpty) {
+            return description;
+        }
+
+        var ret = description.replace("*/", "&#42;&#47;")
+
+        // FIXME: Use Guava's HtmlEscapers once we have it available
+        ret = AMP_MATCHER.replaceFrom(ret, "&amp;");
+        ret = GT_MATCHER.replaceFrom(ret, "&gt;");
+        ret = LT_MATCHER.replaceFrom(ret, "&lt;");
+        return ret;
+    }
+
+    def protected String formatDataForJavaDoc(GeneratedType type, String additionalComment) {
+        val StringBuilder typeDescription = new StringBuilder();
+        if (!type.description.nullOrEmpty) {
+            typeDescription.append(type.description)
+            typeDescription.append(NEW_LINE)
+            typeDescription.append(NEW_LINE)
+            typeDescription.append(NEW_LINE)
+            typeDescription.append(additionalComment)
+        } else {
+            typeDescription.append(additionalComment)
+        }
+
+        return '''
+            Â«typeDescription.toString»
+        '''.toString
+    }
+
+    def asLink(String text) {
+        val StringBuilder sb = new StringBuilder()
+        var tempText = text
+        var char lastChar = ' '
+        var boolean badEnding = false
+
+        if (text.endsWith('.') || text.endsWith(':') || text.endsWith(',')) {
+            tempText = text.substring(0, text.length - 1)
+            lastChar = text.charAt(text.length - 1)
+            badEnding = true
+        }
+        sb.append("<a href = \"")
+        sb.append(tempText)
+        sb.append("\">")
+        sb.append(tempText)
+        sb.append("</a>")
+
+        if(badEnding)
+            sb.append(lastChar)
+
+        return sb.toString
+    }
+
+    protected def formatToParagraph(String text) {
+        if(text == null || text.isEmpty)
+            return text
+
+        var formattedText = text
+        val StringBuilder sb = new StringBuilder();
+        var StringBuilder lineBuilder = new StringBuilder();
+        var boolean isFirstElementOnNewLineEmptyChar = false;
+
+        formattedText = formattedText.encodeJavadocSymbols
+        formattedText = NL_MATCHER.removeFrom(formattedText)
+        formattedText = TAB_MATCHER.removeFrom(formattedText)
+        formattedText = SPACES_PATTERN.matcher(formattedText).replaceAll(" ")
+
+        val StringTokenizer tokenizer = new StringTokenizer(formattedText, " ", true);
+
+        while(tokenizer.hasMoreElements) {
+            val nextElement = tokenizer.nextElement.toString
+
+            if(lineBuilder.length + nextElement.length > 80) {
+                if (lineBuilder.charAt(lineBuilder.length - 1) == ' ') {
+                    lineBuilder.setLength(0)
+                    lineBuilder.append(lineBuilder.substring(0, lineBuilder.length - 1))
+                }
+                if (lineBuilder.charAt(0) == ' ') {
+                    lineBuilder.setLength(0)
+                    lineBuilder.append(lineBuilder.substring(1))
+                }
+
+                sb.append(lineBuilder);
+                lineBuilder.setLength(0)
+                sb.append(NEW_LINE)
+
+                if(nextElement.toString == ' ') {
+                    isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar;
+                }
+            }
+
+            if(isFirstElementOnNewLineEmptyChar) {
+                isFirstElementOnNewLineEmptyChar = !isFirstElementOnNewLineEmptyChar
+            }
+
+            else {
+                lineBuilder.append(nextElement)
+            }
+        }
+        sb.append(lineBuilder)
+        sb.append(NEW_LINE)
+
+        return sb.toString
+    }
+
+    def protected generateToString(Collection<GeneratedProperty> properties) '''
+        Â«IF !properties.empty»
+            @Override
+            public Â«String.importedName» toString() {
+                Â«StringBuilder.importedName» builder = new Â«StringBuilder.importedName»(«type.importedName».class.getSimpleName()).append(" [");
+                boolean first = true;
+
+                Â«FOR property : properties»
+                    if («property.fieldName» != null) {
+                        if (first) {
+                            first = false;
+                        } else {
+                            builder.append(", ");
+                        }
+                        builder.append("«property.fieldName»=");
+                        Â«IF property.returnType.name.contains("[")»
+                            builder.append(«Arrays.importedName».toString(«property.fieldName»));
+                        Â«ELSE»
+                            builder.append(«property.fieldName»);
+                        Â«ENDIF»
+                     }
+                Â«ENDFOR»
+                return builder.append(']').toString();
+            }
+        Â«ENDIF»
+    '''
+
+    def getRestrictions(Type type) {
+        var Restrictions restrictions = null
+        if (type instanceof ConcreteType) {
+            restrictions = type.restrictions
+        } else if (type instanceof GeneratedTransferObject) {
+            restrictions = type.restrictions
+        }
+        return restrictions
+    }
+
+    /**
+     * Template method which generates method parameters with their types from <code>parameters</code>.
+     *
+     * @param parameters
+     * list of parameter instances which are transformed to the method parameters
+     * @return string with the list of the method parameters with their types in JAVA format
+     */
+    def protected generateParameters(List<MethodSignature.Parameter> parameters) '''«
+        IF !parameters.empty»«
+            FOR parameter : parameters SEPARATOR ", "»«
+                parameter.type.importedName» Â«parameter.name»«
+            ENDFOR»«
+        ENDIF
+    Â»'''
+
+    def protected GeneratedProperty findProperty(GeneratedTransferObject gto, String name) {
+        val props = gto.properties
+        for (prop : props) {
+            if (prop.name.equals(name)) {
+                return prop
+            }
+        }
+        val GeneratedTransferObject parent = gto.superType
+        if (parent != null) {
+            return findProperty(parent, name)
+        }
+        return null
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BigDecimalRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BigDecimalRangeGenerator.java
new file mode 100644 (file)
index 0000000..e466ff7
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+final class BigDecimalRangeGenerator extends AbstractBigRangeGenerator<BigDecimal> {
+    BigDecimalRangeGenerator() {
+        super(BigDecimal.class);
+    }
+
+    @Override
+    protected String format(final BigDecimal value) {
+        if (BigDecimal.ZERO.equals(value)) {
+            return "java.math.BigDecimal.ZERO";
+        }
+        if (BigDecimal.ONE.equals(value)) {
+            return "java.math.BigDecimal.ONE";
+        }
+        if (BigDecimal.TEN.equals(value)) {
+            return "java.math.BigDecimal.TEN";
+        }
+
+        // FIXME: can we do something better?
+        return "new java.math.BigDecimal(\"" + value + "\")";
+    }
+
+    @Override
+    protected BigDecimal convert(final Number value) {
+        if (value instanceof BigInteger) {
+            return new BigDecimal((BigInteger)value);
+        } else if (value instanceof Byte) {
+            return new BigDecimal(value.intValue());
+        } else if (value instanceof Short) {
+            return new BigDecimal(value.intValue());
+        } else if (value instanceof Integer) {
+            return new BigDecimal(value.intValue());
+        } else {
+            return BigDecimal.valueOf(value.longValue());
+        }
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BigIntegerRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BigIntegerRangeGenerator.java
new file mode 100644 (file)
index 0000000..cac9671
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+import java.math.BigInteger;
+
+final class BigIntegerRangeGenerator extends AbstractBigRangeGenerator<BigInteger> {
+    BigIntegerRangeGenerator() {
+        super(BigInteger.class);
+    }
+
+    @Override
+    protected String format(final BigInteger value) {
+        if (BigInteger.ZERO.equals(value)) {
+            return "java.math.BigInteger.ZERO";
+        }
+        if (BigInteger.ONE.equals(value)) {
+            return "java.math.BigInteger.ONE";
+        }
+        if (BigInteger.TEN.equals(value)) {
+            return "java.math.BigInteger.TEN";
+        }
+
+        // Check for conversion to long
+        final long l = value.longValue();
+        if (value.equals(BigInteger.valueOf(l))) {
+            return "java.math.BigInteger.valueOf(" + l + "L)";
+        } else {
+            return "new java.math.BigInteger(\"" + value.toString() + "\")";
+        }
+    }
+
+    @Override
+    protected BigInteger convert(final Number value) {
+        return BigInteger.valueOf(value.longValue());
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderGenerator.java
new file mode 100644 (file)
index 0000000..ce5d938
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * 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.sal.java.api.generator;
+
+import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+
+/**
+ * 
+ * Transformator of the data from the virtual form to JAVA programming language.
+ * The result source code represent java class. For generation of the source
+ * code is used the template written in XTEND language.
+ * 
+ */
+public final class BuilderGenerator implements CodeGenerator {
+
+    /**
+     * Constant used as sufix for builder name.
+     */
+    public static final String BUILDER = "Builder";
+
+    /**
+     * Passes via list of implemented types in <code>type</code>.
+     * 
+     * @param type
+     *            JAVA <code>Type</code>
+     * @return boolean value which is true if any of implemented types is of the
+     *         type <code>Augmentable</code>.
+     */
+    @Override
+    public boolean isAcceptable(Type type) {
+        if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+            for (Type t : ((GeneratedType) type).getImplements()) {
+                // "rpc" and "grouping" elements do not implement Augmentable
+                if (t.getFullyQualifiedName().equals(Augmentable.class.getName())) {
+                    return true;
+                } else if (t.getFullyQualifiedName().equals(Augmentation.class.getName())) {
+                    return true;
+                }
+
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Generates JAVA source code for generated type <code>Type</code>. The code
+     * is generated according to the template source code template which is
+     * written in XTEND language.
+     */
+    @Override
+    public String generate(Type type) {
+        if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+            final GeneratedType genType = (GeneratedType) type;
+            final BuilderTemplate template = new BuilderTemplate(genType);
+            return template.generate();
+        }
+        return "";
+    }
+
+    @Override
+    public String getUnitName(Type type) {
+        return type.getName() + BUILDER;
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/BuilderTemplate.xtend
new file mode 100644 (file)
index 0000000..7a8b72a
--- /dev/null
@@ -0,0 +1,779 @@
+/*
+ * 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.sal.java.api.generator
+
+import com.google.common.collect.ImmutableSortedSet
+import java.util.ArrayList
+import java.util.Arrays
+import java.util.Collection
+import java.util.Collections
+import java.util.HashMap
+import java.util.HashSet
+import java.util.LinkedHashSet
+import java.util.List
+import java.util.Map
+import java.util.Set
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl
+import org.opendaylight.yangtools.binding.generator.util.Types
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl
+import org.opendaylight.yangtools.concepts.Builder
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.yang.binding.Augmentable
+import org.opendaylight.yangtools.yang.binding.AugmentationHolder
+import org.opendaylight.yangtools.yang.binding.DataObject
+import org.opendaylight.yangtools.yang.binding.Identifiable
+
+/**
+ * Template for generating JAVA builder classes.
+ */
+
+class BuilderTemplate extends BaseTemplate {
+
+    /**
+     * Constant with the name of the concrete method.
+     */
+    val static GET_AUGMENTATION_METHOD_NAME = "getAugmentation"
+
+    /**
+     * Constant with the suffix for builder classes.
+     */
+    val static BUILDER = 'Builder'
+
+    /**
+     * Constant with the name of the BuilderFor interface
+     */
+     val static BUILDERFOR = Builder.simpleName;
+
+    /**
+     * Constant with suffix for the classes which are generated from the builder classes.
+     */
+    val static IMPL = 'Impl'
+
+    /**
+     * Generated property is set if among methods is found one with the name GET_AUGMENTATION_METHOD_NAME
+     */
+    var GeneratedProperty augmentField
+
+    /**
+     * Set of class attributes (fields) which are derived from the getter methods names
+     */
+    val Set<GeneratedProperty> properties
+
+    private static val METHOD_COMPARATOR = new AlphabeticallyTypeMemberComparator<MethodSignature>();
+
+    /**
+     * Constructs new instance of this class.
+     * @throws IllegalArgumentException if <code>genType</code> equals <code>null</code>
+     */
+    new(GeneratedType genType) {
+        super(genType)
+        this.properties = propertiesFromMethods(createMethods)
+        importMap.put(Builder.simpleName, Builder.package.name)
+    }
+
+    /**
+     * Returns set of method signature instances which contains all the methods of the <code>genType</code>
+     * and all the methods of the implemented interfaces.
+     *
+     * @returns set of method signature instances
+     */
+    def private Set<MethodSignature> createMethods() {
+        val Set<MethodSignature> methods = new LinkedHashSet();
+        methods.addAll(type.methodDefinitions)
+        collectImplementedMethods(methods, type.implements)
+        val Set<MethodSignature> sortedMethods = ImmutableSortedSet.orderedBy(METHOD_COMPARATOR).addAll(methods).build()
+
+        return sortedMethods
+    }
+
+    /**
+     * Adds to the <code>methods</code> set all the methods of the <code>implementedIfcs</code>
+     * and recursively their implemented interfaces.
+     *
+     * @param methods set of method signatures
+     * @param implementedIfcs list of implemented interfaces
+     */
+    def private void collectImplementedMethods(Set<MethodSignature> methods, List<Type> implementedIfcs) {
+        if (implementedIfcs == null || implementedIfcs.empty) {
+            return
+        }
+        for (implementedIfc : implementedIfcs) {
+            if ((implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))) {
+                val ifc = implementedIfc as GeneratedType
+                methods.addAll(ifc.methodDefinitions)
+                collectImplementedMethods(methods, ifc.implements)
+            } else if (implementedIfc.fullyQualifiedName == Augmentable.name) {
+                for (m : Augmentable.methods) {
+                    if (m.name == GET_AUGMENTATION_METHOD_NAME) {
+                        val fullyQualifiedName = m.returnType.name
+                        val pkg = fullyQualifiedName.package
+                        val name = fullyQualifiedName.name
+                        val tmpGenTO = new GeneratedTOBuilderImpl(pkg, name)
+                        val refType = new ReferencedTypeImpl(pkg, name)
+                        val generic = new ReferencedTypeImpl(type.packageName, type.name)
+                        val parametrizedReturnType = Types.parameterizedTypeFor(refType, generic)
+                        tmpGenTO.addMethod(m.name).setReturnType(parametrizedReturnType)
+                        augmentField = tmpGenTO.toInstance.methodDefinitions.first.propertyFromGetter
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns the first element of the list <code>elements</code>.
+     *
+     * @param list of elements
+     */
+    def private <E> first(List<E> elements) {
+        elements.get(0)
+    }
+
+    /**
+     * Returns the name of the package from <code>fullyQualifiedName</code>.
+     *
+     * @param fullyQualifiedName string with fully qualified type name (package + type)
+     * @return string with the package name
+     */
+    def private String getPackage(String fullyQualifiedName) {
+        val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)
+        return if (lastDotIndex == -1) "" else fullyQualifiedName.substring(0, lastDotIndex)
+    }
+
+    /**
+     * Returns the name of tye type from <code>fullyQualifiedName</code>
+     *
+     * @param fullyQualifiedName string with fully qualified type name (package + type)
+     * @return string with the name of the type
+     */
+    def private String getName(String fullyQualifiedName) {
+        val lastDotIndex = fullyQualifiedName.lastIndexOf(Constants.DOT)
+        return if (lastDotIndex == -1) fullyQualifiedName else fullyQualifiedName.substring(lastDotIndex + 1)
+    }
+
+    /**
+     * Creates set of generated property instances from getter <code>methods</code>.
+     *
+     * @param set of method signature instances which should be transformed to list of properties
+     * @return set of generated property instances which represents the getter <code>methods</code>
+     */
+    def private propertiesFromMethods(Collection<MethodSignature> methods) {
+        if (methods == null || methods.isEmpty()) {
+            return Collections.emptySet
+        }
+        val Set<GeneratedProperty> result = new LinkedHashSet
+        for (m : methods) {
+            val createdField = m.propertyFromGetter
+            if (createdField != null) {
+                result.add(createdField)
+            }
+        }
+        return result
+    }
+
+    /**
+     * Creates generated property instance from the getter <code>method</code> name and return type.
+     *
+     * @param method method signature from which is the method name and return type obtained
+     * @return generated property instance for the getter <code>method</code>
+     * @throws IllegalArgumentException<ul>
+     *  <li>if the <code>method</code> equals <code>null</code></li>
+     *  <li>if the name of the <code>method</code> equals <code>null</code></li>
+     *  <li>if the name of the <code>method</code> is empty</li>
+     *  <li>if the return type of the <code>method</code> equals <code>null</code></li>
+     * </ul>
+     */
+    def private GeneratedProperty propertyFromGetter(MethodSignature method) {
+        if (method == null || method.name == null || method.name.empty || method.returnType == null) {
+            throw new IllegalArgumentException("Method, method name, method return type reference cannot be NULL or empty!")
+        }
+        var prefix = "get";
+        if(Types.BOOLEAN.equals(method.returnType)) {
+            prefix = "is";
+        }
+        if (method.name.startsWith(prefix)) {
+            val fieldName = method.getName().substring(prefix.length()).toFirstLower
+            val tmpGenTO = new GeneratedTOBuilderImpl("foo", "foo")
+            tmpGenTO.addProperty(fieldName).setReturnType(method.returnType)
+            return tmpGenTO.toInstance.properties.first
+        }
+    }
+
+    /**
+     * Template method which generates JAVA class body for builder class and for IMPL class.
+     *
+     * @return string with JAVA source code
+     */
+    override body() '''
+        Â«wrapToDocumentation(formatDataForJavaDoc(type))»
+        public class Â«type.name»«BUILDER» implements Â«BUILDERFOR» <«type.importedName»> {
+
+            Â«generateFields(false)»
+
+            Â«generateAugmentField(false)»
+
+            Â«generateConstructorsFromIfcs(type)»
+
+            Â«generateCopyConstructor(false)»
+
+            Â«generateMethodFieldsFrom(type)»
+
+            Â«generateGetters(false)»
+
+            Â«generateSetters»
+
+            public Â«type.name» build() {
+                return new Â«type.name»«IMPL»(this);
+            }
+
+            private static final class Â«type.name»«IMPL» implements Â«type.name» {
+
+                Â«implementedInterfaceGetter»
+
+                Â«generateFields(true)»
+
+                Â«generateAugmentField(true)»
+
+                Â«generateCopyConstructor(true)»
+
+                Â«generateGetters(true)»
+
+                Â«generateHashCode()»
+
+                Â«generateEquals()»
+
+                Â«generateToString(properties)»
+            }
+
+        }
+    '''
+
+    /**
+     * Generate default constructor and constructor for every implemented interface from uses statements.
+     */
+    def private generateConstructorsFromIfcs(Type type) '''
+        public Â«type.name»«BUILDER»() {
+        }
+        Â«IF (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject))»
+            Â«val ifc = type as GeneratedType»
+            Â«FOR impl : ifc.implements»
+                Â«generateConstructorFromIfc(impl)»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    /**
+     * Generate constructor with argument of given type.
+     */
+    def private Object generateConstructorFromIfc(Type impl) '''
+        Â«IF (impl instanceof GeneratedType)»
+            Â«IF !(impl.methodDefinitions.empty)»
+                public Â«type.name»«BUILDER»(«impl.fullyQualifiedName» arg) {
+                    Â«printConstructorPropertySetter(impl)»
+                }
+            Â«ENDIF»
+            Â«FOR implTypeImplement : impl.implements»
+                Â«generateConstructorFromIfc(implTypeImplement)»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    def private Object printConstructorPropertySetter(Type implementedIfc) '''
+        Â«IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»
+            Â«val ifc = implementedIfc as GeneratedType»
+            Â«FOR getter : ifc.methodDefinitions»
+                this._«getter.propertyNameFromGetter» = arg.«getter.name»();
+            Â«ENDFOR»
+            Â«FOR impl : ifc.implements»
+                Â«printConstructorPropertySetter(impl)»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    /**
+     * Generate 'fieldsFrom' method to set builder properties based on type of given argument.
+     */
+    def private generateMethodFieldsFrom(Type type) '''
+        Â«IF (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject))»
+            Â«val ifc = type as GeneratedType»
+            Â«IF ifc.hasImplementsFromUses»
+                Â«val List<Type> done = ifc.getBaseIfcs»
+                Â«generateMethodFieldsFromComment(ifc)»
+                public void fieldsFrom(«DataObject.importedName» arg) {
+                    boolean isValidArg = false;
+                    Â«FOR impl : ifc.getAllIfcs»
+                        Â«generateIfCheck(impl, done)»
+                    Â«ENDFOR»
+                    if (!isValidArg) {
+                        throw new IllegalArgumentException(
+                          "expected one of: Â«ifc.getAllIfcs.toListOfNames» \n" +
+                          "but was: " + arg
+                        );
+                    }
+                }
+            Â«ENDIF»
+        Â«ENDIF»
+    '''
+
+    def private generateMethodFieldsFromComment(GeneratedType type) '''
+        /**
+         *Set fields from given grouping argument. Valid argument is instance of one of following types:
+         * <ul>
+         Â«FOR impl : type.getAllIfcs»
+         * <li>«impl.fullyQualifiedName»</li>
+         Â«ENDFOR»
+         * </ul>
+         *
+         * @param arg grouping object
+         * @throws IllegalArgumentException if given argument is none of valid types
+        */
+    '''
+
+    /**
+     * Method is used to find out if given type implements any interface from uses.
+     */
+    def boolean hasImplementsFromUses(GeneratedType type) {
+        var i = 0
+        for (impl : type.getAllIfcs) {
+            if ((impl instanceof GeneratedType) &&  !((impl as GeneratedType).methodDefinitions.empty)) {
+                i = i + 1
+            }
+        }
+        return i > 0
+    }
+
+    def private generateIfCheck(Type impl, List<Type> done) '''
+        Â«IF (impl instanceof GeneratedType) &&  !((impl as GeneratedType).methodDefinitions.empty)»
+            Â«val implType = impl as GeneratedType»
+            if (arg instanceof Â«implType.fullyQualifiedName») {
+                Â«printPropertySetter(implType)»
+                isValidArg = true;
+            }
+        Â«ENDIF»
+    '''
+
+    def private printPropertySetter(Type implementedIfc) '''
+        Â«IF (implementedIfc instanceof GeneratedType && !(implementedIfc instanceof GeneratedTransferObject))»
+        Â«val ifc = implementedIfc as GeneratedType»
+        Â«FOR getter : ifc.methodDefinitions»
+            this._«getter.propertyNameFromGetter» = ((«implementedIfc.fullyQualifiedName»)arg).«getter.name»();
+        Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    private def List<Type> getBaseIfcs(GeneratedType type) {
+        val List<Type> baseIfcs = new ArrayList();
+        for (ifc : type.implements) {
+            if (ifc instanceof GeneratedType && !(ifc as GeneratedType).methodDefinitions.empty) {
+                baseIfcs.add(ifc)
+            }
+        }
+        return baseIfcs
+    }
+
+    private def Set<Type> getAllIfcs(Type type) {
+        val Set<Type> baseIfcs = new HashSet()
+        if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+            val ifc = type as GeneratedType
+            for (impl : ifc.implements) {
+                if (impl instanceof GeneratedType && !(impl as GeneratedType).methodDefinitions.empty) {
+                    baseIfcs.add(impl)
+                }
+                baseIfcs.addAll(impl.getAllIfcs)
+            }
+        }
+        return baseIfcs
+    }
+
+    private def List<String> toListOfNames(Collection<Type> types) {
+        val List<String> names = new ArrayList
+        for (type : types) {
+            names.add(type.fullyQualifiedName)
+        }
+        return names
+    }
+
+    /**
+     * Template method which generates class attributes.
+     *
+     * @param boolean value which specify whether field is|isn't final
+     * @return string with class attributes and their types
+     */
+    def private generateFields(boolean _final) '''
+        Â«IF properties !== null»
+            Â«FOR f : properties»
+                private«IF _final» final«ENDIF» Â«f.returnType.importedName» Â«f.fieldName»;
+                Â«val restrictions = f.returnType.restrictions»
+                Â«IF !_final && restrictions != null && !(restrictions.lengthConstraints.empty)»
+                    Â«LengthGenerator.generateLengthChecker(f.fieldName.toString, f.returnType, restrictions.lengthConstraints)»
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    def private generateAugmentField(boolean isPrivate) '''
+        Â«IF augmentField != null»
+            Â«IF isPrivate»private Â«ENDIF»«Map.importedName»<«Class.importedName»<? extends Â«augmentField.returnType.importedName»>, Â«augmentField.returnType.importedName»> Â«augmentField.name» = Â«Collections.importedName».emptyMap();
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates setter methods
+     *
+     * @return string with the setter methods
+     */
+    def private generateSetters() '''
+        Â«FOR field : properties SEPARATOR '\n'»
+            Â«val restrictions = field.returnType.restrictions»
+            Â«IF restrictions != null»
+                Â«IF !restrictions.rangeConstraints.nullOrEmpty»
+                    Â«val rangeGenerator = AbstractRangeGenerator.forType(field.returnType)»
+                    Â«rangeGenerator.generateRangeChecker(field.name.toFirstUpper, restrictions.rangeConstraints)»
+
+                Â«ENDIF»
+            Â«ENDIF»
+            public Â«type.name»«BUILDER» set«field.name.toFirstUpper»(«field.returnType.importedName» value) {
+                Â«IF restrictions != null»
+                if (value != null) {
+                    Â«IF !restrictions.rangeConstraints.nullOrEmpty»
+                        Â«val rangeGenerator = AbstractRangeGenerator.forType(field.returnType)»
+                        Â«IF field.returnType instanceof ConcreteType»
+                            Â«rangeGenerator.generateRangeCheckerCall(field.name.toFirstUpper, "value")»
+                        Â«ELSE»
+                            Â«rangeGenerator.generateRangeCheckerCall(field.name.toFirstUpper, "value.getValue()")»
+                        Â«ENDIF»
+                    Â«ENDIF»
+                    Â«generateRestrictions(field, "value")»
+                }
+                Â«ENDIF»
+                this.«field.fieldName» = value;
+                return this;
+            }
+        Â«ENDFOR»
+        Â«IF augmentField != null»
+
+            public Â«type.name»«BUILDER» add«augmentField.name.toFirstUpper»(«Class.importedName»<? extends Â«augmentField.returnType.importedName»> augmentationType, Â«augmentField.returnType.importedName» augmentation) {
+                if (augmentation == null) {
+                    return remove«augmentField.name.toFirstUpper»(augmentationType);
+                }
+
+                if (!(this.«augmentField.name» instanceof Â«HashMap.importedName»)) {
+                    this.«augmentField.name» = new Â«HashMap.importedName»<>();
+                }
+
+                this.«augmentField.name».put(augmentationType, augmentation);
+                return this;
+            }
+
+            public Â«type.name»«BUILDER» remove«augmentField.name.toFirstUpper»(«Class.importedName»<? extends Â«augmentField.returnType.importedName»> augmentationType) {
+                if (this.«augmentField.name» instanceof Â«HashMap.importedName») {
+                    this.«augmentField.name».remove(augmentationType);
+                }
+                return this;
+            }
+        Â«ENDIF»
+    '''
+
+    def private generateRestrictions(GeneratedProperty field, String paramName) '''
+        Â«val Type type = field.returnType»
+        Â«val restrictions = type.getRestrictions»
+        Â«IF restrictions !== null && !restrictions.lengthConstraints.empty»
+            Â«IF type instanceof ConcreteType»
+                Â«LengthGenerator.generateLengthCheckerCall(field.fieldName.toString, paramName)»
+            Â«ELSE»
+                Â«LengthGenerator.generateLengthCheckerCall(field.fieldName.toString, paramName + ".getValue()")»
+            Â«ENDIF»
+        Â«ENDIF»
+    '''
+
+    def private CharSequence generateCopyConstructor(boolean impl) '''
+        Â«IF impl»private«ELSE»public«ENDIF» Â«type.name»«IF impl»«IMPL»«ELSE»«BUILDER»«ENDIF»(«type.name»«IF impl»«BUILDER»«ENDIF» base) {
+            Â«val allProps = new ArrayList(properties)»
+            Â«val isList = implementsIfc(type, Types.parameterizedTypeFor(Types.typeForClass(Identifiable), type))»
+            Â«val keyType = type.getKey»
+            Â«IF isList && keyType != null»
+                Â«val keyProps = new ArrayList((keyType as GeneratedTransferObject).properties)»
+                Â«Collections.sort(keyProps,
+                    [ p1, p2 |
+                        return p1.name.compareTo(p2.name)
+                    ])
+                Â»
+                Â«FOR field : keyProps»
+                    Â«removeProperty(allProps, field.name)»
+                Â«ENDFOR»
+                Â«removeProperty(allProps, "key")»
+                if (base.getKey() == null) {
+                    this._key = new Â«keyType.importedName»(
+                        Â«FOR keyProp : keyProps SEPARATOR ", "»
+                            base.«keyProp.getterMethodName»()
+                        Â«ENDFOR»
+                    );
+                    Â«FOR field : keyProps»
+                        this.«field.fieldName» = base.«field.getterMethodName»();
+                    Â«ENDFOR»
+                } else {
+                    this._key = base.getKey();
+                    Â«FOR field : keyProps»
+                           this.«field.fieldName» = _key.«field.getterMethodName»();
+                    Â«ENDFOR»
+                }
+            Â«ENDIF»
+            Â«FOR field : allProps»
+                this.«field.fieldName» = base.«field.getterMethodName»();
+            Â«ENDFOR»
+            Â«IF augmentField != null»
+                Â«IF impl»
+                    switch (base.«augmentField.name».size()) {
+                    case 0:
+                        this.«augmentField.name» = Â«Collections.importedName».emptyMap();
+                        break;
+                    case 1:
+                        final Â«Map.importedName».Entry<«Class.importedName»<? extends Â«augmentField.returnType.importedName»>, Â«augmentField.returnType.importedName»> e = base.«augmentField.name».entrySet().iterator().next();
+                        this.«augmentField.name» = Â«Collections.importedName».<«Class.importedName»<? extends Â«augmentField.returnType.importedName»>, Â«augmentField.returnType.importedName»>singletonMap(e.getKey(), e.getValue());
+                        break;
+                    default :
+                        this.«augmentField.name» = new Â«HashMap.importedName»<>(base.«augmentField.name»);
+                    }
+                Â«ELSE»
+                    if (base instanceof Â«type.name»«IMPL») {
+                        Â«type.name»«IMPL» impl = («type.name»«IMPL») base;
+                        if (!impl.«augmentField.name».isEmpty()) {
+                            this.«augmentField.name» = new Â«HashMap.importedName»<>(impl.«augmentField.name»);
+                        }
+                    } else if (base instanceof Â«AugmentationHolder.importedName») {
+                        @SuppressWarnings("unchecked")
+                        Â«AugmentationHolder.importedName»<«type.importedName»> casted =(«AugmentationHolder.importedName»<«type.importedName»>) base;
+                        if (!casted.augmentations().isEmpty()) {
+                            this.«augmentField.name» = new Â«HashMap.importedName»<>(casted.augmentations());
+                        }
+                    }
+                Â«ENDIF»
+            Â«ENDIF»
+        }
+    '''
+
+    private def boolean implementsIfc(GeneratedType type, Type impl) {
+        for (Type ifc : type.implements) {
+            if (ifc.equals(impl)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private def Type getKey(GeneratedType type) {
+        for (m : type.methodDefinitions) {
+            if ("getKey".equals(m.name)) {
+                return m.returnType;
+            }
+        }
+        return null;
+    }
+
+    private def void removeProperty(Collection<GeneratedProperty> props, String name) {
+        var GeneratedProperty toRemove = null
+        for (p : props) {
+            if (p.name.equals(name)) {
+                toRemove = p;
+            }
+        }
+        if (toRemove != null) {
+            props.remove(toRemove);
+        }
+    }
+
+    /**
+     * Template method which generate getter methods for IMPL class.
+     *
+     * @return string with getter methods
+     */
+    def private generateGetters(boolean addOverride) '''
+        Â«IF !properties.empty»
+            Â«FOR field : properties SEPARATOR '\n'»
+                Â«IF addOverride»@Override«ENDIF»
+                Â«field.getterMethod»
+            Â«ENDFOR»
+        Â«ENDIF»
+        Â«IF augmentField != null»
+
+            @SuppressWarnings("unchecked")
+            Â«IF addOverride»@Override«ENDIF»
+            public <E extends Â«augmentField.returnType.importedName»> E get«augmentField.name.toFirstUpper»(«Class.importedName»<E> augmentationType) {
+                if (augmentationType == null) {
+                    throw new IllegalArgumentException("Augmentation Type reference cannot be NULL!");
+                }
+                return (E) Â«augmentField.name».get(augmentationType);
+            }
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates the method <code>hashCode()</code>.
+     *
+     * @return string with the <code>hashCode()</code> method definition in JAVA format
+     */
+    def protected generateHashCode() '''
+        Â«IF !properties.empty || augmentField != null»
+            private int hash = 0;
+            private volatile boolean hashValid = false;
+
+            @Override
+            public int hashCode() {
+                if (hashValid) {
+                    return hash;
+                }
+
+                final int prime = 31;
+                int result = 1;
+                Â«FOR property : properties»
+                    Â«IF property.returnType.name.contains("[")»
+                    result = prime * result + ((«property.fieldName» == null) ? 0 : Â«Arrays.importedName».hashCode(«property.fieldName»));
+                    Â«ELSE»
+                    result = prime * result + ((«property.fieldName» == null) ? 0 : Â«property.fieldName».hashCode());
+                    Â«ENDIF»
+                Â«ENDFOR»
+                Â«IF augmentField != null»
+                    result = prime * result + ((«augmentField.name» == null) ? 0 : Â«augmentField.name».hashCode());
+                Â«ENDIF»
+
+                hash = result;
+                hashValid = true;
+                return result;
+            }
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates the method <code>equals()</code>.
+     *
+     * @return string with the <code>equals()</code> method definition in JAVA format
+     */
+    def protected generateEquals() '''
+        Â«IF !properties.empty || augmentField != null»
+            @Override
+            public boolean equals(«Object.importedName» obj) {
+                if (this == obj) {
+                    return true;
+                }
+                if (!(obj instanceof Â«DataObject.importedName»)) {
+                    return false;
+                }
+                if (!«type.importedName».class.equals(((«DataObject.importedName»)obj).getImplementedInterface())) {
+                    return false;
+                }
+                Â«type.importedName» other = («type.importedName»)obj;
+                Â«FOR property : properties»
+                    Â«val fieldName = property.fieldName»
+                    if («fieldName» == null) {
+                        if (other.«property.getterMethodName»() != null) {
+                            return false;
+                        }
+                    Â«IF property.returnType.name.contains("[")»
+                    } else if(!«Arrays.importedName».equals(«fieldName», other.«property.getterMethodName»())) {
+                    Â«ELSE»
+                    } else if(!«fieldName».equals(other.«property.getterMethodName»())) {
+                    Â«ENDIF»
+                        return false;
+                    }
+                Â«ENDFOR»
+                Â«IF augmentField != null»
+                    if (getClass() == obj.getClass()) {
+                        // Simple case: we are comparing against self
+                        Â«type.name»«IMPL» otherImpl = («type.name»«IMPL») obj;
+                        Â«val fieldName = augmentField.name»
+                        if («fieldName» == null) {
+                            if (otherImpl.«fieldName» != null) {
+                                return false;
+                            }
+                        } else if(!«fieldName».equals(otherImpl.«fieldName»)) {
+                            return false;
+                        }
+                    } else {
+                        // Hard case: compare our augments with presence there...
+                        for («Map.importedName».Entry<«Class.importedName»<? extends Â«augmentField.returnType.importedName»>, Â«augmentField.returnType.importedName»> e : Â«augmentField.name».entrySet()) {
+                            if (!e.getValue().equals(other.getAugmentation(e.getKey()))) {
+                                return false;
+                            }
+                        }
+                        // .. and give the other one the chance to do the same
+                        if (!obj.equals(this)) {
+                            return false;
+                        }
+                    }
+                Â«ENDIF»
+                return true;
+            }
+        Â«ENDIF»
+    '''
+
+    def override generateToString(Collection<GeneratedProperty> properties) '''
+        Â«IF !(properties === null)»
+            @Override
+            public Â«String.importedName» toString() {
+                Â«StringBuilder.importedName» builder = new Â«StringBuilder.importedName» ("«type.name» [");
+                boolean first = true;
+
+                Â«FOR property : properties»
+                    if («property.fieldName» != null) {
+                        if (first) {
+                            first = false;
+                        } else {
+                            builder.append(", ");
+                        }
+                        builder.append("«property.fieldName»=");
+                        Â«IF property.returnType.name.contains("[")»
+                            builder.append(«Arrays.importedName».toString(«property.fieldName»));
+                        Â«ELSE»
+                            builder.append(«property.fieldName»);
+                        Â«ENDIF»
+                     }
+                Â«ENDFOR»
+                Â«IF augmentField != null»
+                    if (first) {
+                        first = false;
+                    } else {
+                        builder.append(", ");
+                    }
+                    builder.append("«augmentField.name»=");
+                    builder.append(«augmentField.name».values());
+                Â«ENDIF»
+                return builder.append(']').toString();
+            }
+        Â«ENDIF»
+    '''
+
+    def implementedInterfaceGetter() '''
+    public Â«Class.importedName»<«type.importedName»> getImplementedInterface() {
+        return Â«type.importedName».class;
+    }
+    '''
+
+    private def createDescription(GeneratedType type) {
+        return '''
+        Class that builds {@link Â«type.importedName»} instances.
+
+        @see Â«type.importedName»
+    '''
+    }
+
+    override def protected String formatDataForJavaDoc(GeneratedType type) {
+        val typeDescription = createDescription(type)
+
+        return '''
+            Â«IF !typeDescription.nullOrEmpty»
+            Â«typeDescription»
+            Â«ENDIF»
+        '''.toString
+    }
+}
+
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ByteRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ByteRangeGenerator.java
new file mode 100644 (file)
index 0000000..b4b8612
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+final class ByteRangeGenerator extends AbstractSubIntegerRangeGenerator<Byte> {
+    ByteRangeGenerator() {
+        super(Byte.class, byte.class.getName(), Byte.MIN_VALUE, Byte.MAX_VALUE);
+    }
+
+    @Override
+    protected Byte convert(final Number value) {
+        return value.byteValue();
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend
new file mode 100644 (file)
index 0000000..8107e46
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * 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.sal.java.api.generator
+
+import com.google.common.base.Preconditions
+import com.google.common.collect.ImmutableList
+import com.google.common.collect.Lists
+import com.google.common.io.BaseEncoding
+import java.beans.ConstructorProperties
+import java.util.ArrayList
+import java.util.Arrays
+import java.util.Collections
+import java.util.List
+import java.util.regex.Pattern
+import org.opendaylight.yangtools.binding.generator.util.TypeConstants
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType
+import org.opendaylight.yangtools.sal.binding.model.api.Constant
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
+
+/**
+ * Template for generating JAVA class.
+ */
+class ClassTemplate extends BaseTemplate {
+
+    protected val List<GeneratedProperty> properties
+    protected val List<GeneratedProperty> finalProperties
+    protected val List<GeneratedProperty> parentProperties
+    protected val Iterable<GeneratedProperty> allProperties;
+    protected val Restrictions restrictions
+
+    /**
+     * List of enumeration which are generated as JAVA enum type.
+     */
+    protected val List<Enumeration> enums
+
+    /**
+     * List of constant instances which are generated as JAVA public static final attributes.
+     */
+    protected val List<Constant> consts
+
+    /**
+     * List of generated types which are enclosed inside <code>genType</code>
+     */
+    protected val List<GeneratedType> enclosedGeneratedTypes;
+
+    protected val GeneratedTransferObject genTO;
+
+    private val AbstractRangeGenerator<?> rangeGenerator
+
+    /**
+     * Creates instance of this class with concrete <code>genType</code>.
+     *
+     * @param genType generated transfer object which will be transformed to JAVA class source code
+     */
+    new(GeneratedTransferObject genType) {
+        super(genType)
+        this.genTO = genType
+        this.properties = genType.properties
+        this.finalProperties = GeneratorUtil.resolveReadOnlyPropertiesFromTO(genTO.properties)
+        this.parentProperties = GeneratorUtil.getPropertiesOfAllParents(genTO)
+        this.restrictions = genType.restrictions
+
+        var List<GeneratedProperty> sorted = new ArrayList<GeneratedProperty>();
+        sorted.addAll(properties);
+        sorted.addAll(parentProperties);
+        Collections.sort(sorted, [p1, p2|
+            p1.name.compareTo(p2.name)
+        ]);
+
+        this.allProperties = sorted
+        this.enums = genType.enumerations
+        this.consts = genType.constantDefinitions
+        this.enclosedGeneratedTypes = genType.enclosedTypes
+
+        if (restrictions != null && !restrictions.rangeConstraints.nullOrEmpty) {
+            rangeGenerator = AbstractRangeGenerator.forType(findProperty(genType, "value").returnType)
+            Preconditions.checkNotNull(rangeGenerator)
+        } else {
+            rangeGenerator = null
+        }
+    }
+
+    /**
+     * Generates JAVA class source code (class body only).
+     *
+     * @return string with JAVA class body source code
+     */
+    def CharSequence generateAsInnerClass() {
+        return generateBody(true)
+    }
+
+    override protected body() {
+        generateBody(false);
+    }
+
+    /**
+     * Template method which generates class body.
+     *
+     * @param isInnerClass boolean value which specify if generated class is|isn't inner
+     * @return string with class source code in JAVA format
+     */
+    def protected generateBody(boolean isInnerClass) '''
+        Â«wrapToDocumentation(formatDataForJavaDoc(type))»
+        Â«generateClassDeclaration(isInnerClass)» {
+            Â«suidDeclaration»
+            Â«innerClassesDeclarations»
+            Â«enumDeclarations»
+            Â«constantsDeclarations»
+            Â«generateFields»
+
+            Â«IF restrictions != null»
+                Â«IF !restrictions.lengthConstraints.nullOrEmpty»
+                    Â«LengthGenerator.generateLengthChecker("_value", findProperty(genTO, "value").returnType, restrictions.lengthConstraints)»
+                Â«ENDIF»
+                Â«IF !restrictions.rangeConstraints.nullOrEmpty»
+                    Â«rangeGenerator.generateRangeChecker("_value", restrictions.rangeConstraints)»
+                Â«ENDIF»
+            Â«ENDIF»
+
+            Â«constructors»
+
+            Â«defaultInstance»
+
+            Â«FOR field : properties SEPARATOR "\n"»
+                Â«field.getterMethod»
+                Â«IF !field.readOnly»
+                    Â«field.setterMethod»
+                Â«ENDIF»
+            Â«ENDFOR»
+
+            Â«IF (genTO.isTypedef() && genTO.getBaseType instanceof BitsTypeDefinition)»
+                Â«generateGetValueForBitsTypeDef»
+            Â«ENDIF»
+
+            Â«generateHashCode»
+
+            Â«generateEquals»
+
+            Â«generateToString(genTO.toStringIdentifiers)»
+        }
+
+    '''
+
+    /**
+     * Template method which generates the method <code>getValue()</code> for typedef,
+     * which base type is BitsDefinition.
+     *
+     * @return string with the <code>getValue()</code> method definition in JAVA format
+     */
+    def protected generateGetValueForBitsTypeDef() '''
+
+        public boolean[] getValue() {
+            return new boolean[]{
+            Â«FOR property: genTO.properties SEPARATOR ','»
+                 Â«property.fieldName»
+            Â«ENDFOR»
+            };
+        }
+    '''
+
+    /**
+     * Template method which generates inner classes inside this interface.
+     *
+     * @return string with the source code for inner classes in JAVA format
+     */
+    def protected innerClassesDeclarations() '''
+        Â«IF !enclosedGeneratedTypes.empty»
+            Â«FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
+                Â«IF (innerClass instanceof GeneratedTransferObject)»
+                    Â«val classTemplate = new ClassTemplate(innerClass)»
+                    Â«classTemplate.generateAsInnerClass»
+
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    def protected constructors() '''
+        Â«IF genTO.unionType»
+            Â«genUnionConstructor»
+        Â«ELSE»
+            Â«allValuesConstructor»
+        Â«ENDIF»
+        Â«IF !allProperties.empty»
+            Â«copyConstructor»
+        Â«ENDIF»
+        Â«IF properties.empty && !parentProperties.empty Â»
+            Â«parentConstructor»
+        Â«ENDIF»
+    '''
+
+    def protected allValuesConstructor() '''
+    Â«IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
+        @«ConstructorProperties.importedName»("value")
+    Â«ENDIF»
+    public Â«type.name»(«allProperties.asArgumentsDeclaration») {
+        Â«IF false == parentProperties.empty»
+            super(«parentProperties.asArguments»);
+        Â«ENDIF»
+        Â«FOR p : allProperties»
+            Â«generateRestrictions(type, p.fieldName.toString, p.returnType)»
+        Â«ENDFOR»
+
+        Â«/*
+         * If we have patterns, we need to apply them to the value field. This is a sad
+         * consequence of how this code is structured.
+         */
+        IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
+
+        Â«Preconditions.importedName».checkNotNull(_value, "Supplied value may not be null");
+
+            Â«FOR c : consts»
+                Â«IF c.name == TypeConstants.PATTERN_CONSTANT_NAME && c.value instanceof List<?>»
+                for (Pattern p : patterns) {
+                    Â«Preconditions.importedName».checkArgument(p.matcher(_value).matches(), "Supplied value \"%s\" does not match required pattern \"%s\"", _value, p);
+                }
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+
+        Â«FOR p : properties»
+            Â«IF p.returnType.importedName.contains("[]")»
+                Â«IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name
+                .equals("value")»
+                this.«p.fieldName» = Â«p.fieldName».clone();
+                Â«ELSE»
+                this.«p.fieldName» = Â«p.fieldName» == null ? null : Â«p.fieldName».clone();
+                Â«ENDIF»
+            Â«ELSE»
+            this.«p.fieldName» = Â«p.fieldName»;
+            Â«ENDIF»
+        Â«ENDFOR»
+    }
+
+    '''
+
+    def protected genUnionConstructor() '''
+    Â«FOR p : allProperties»
+        Â«val List<GeneratedProperty> other = new ArrayList(properties)»
+        Â«IF other.remove(p)»
+            Â«genConstructor(p, other)»
+        Â«ENDIF»
+    Â«ENDFOR»
+
+    '''
+
+    def protected genConstructor(GeneratedProperty property, GeneratedProperty... other) '''
+    public Â«type.name»(«property.returnType.importedName + " " + property.name») {
+        Â«IF false == parentProperties.empty»
+            super(«parentProperties.asArguments»);
+        Â«ENDIF»
+
+        Â«generateRestrictions(type, property.fieldName.toString, property.returnType)»
+
+        this.«property.fieldName» = Â«property.name»;
+        Â«FOR p : other»
+            this.«p.fieldName» = null;
+        Â«ENDFOR»
+    }
+    '''
+
+    def private static paramValue(Type returnType, String paramName) {
+        if (returnType instanceof ConcreteType) {
+            return paramName
+        } else {
+            return paramName + ".getValue()"
+        }
+    }
+
+    def private generateRestrictions(Type type, String paramName, Type returnType) '''
+        Â«val restrictions = type.getRestrictions»
+        Â«IF restrictions !== null»
+            Â«IF !restrictions.lengthConstraints.empty || !restrictions.rangeConstraints.empty»
+            if («paramName» != null) {
+                Â«IF !restrictions.lengthConstraints.empty»
+                    Â«LengthGenerator.generateLengthCheckerCall(paramName, paramValue(returnType, paramName))»
+                Â«ENDIF»
+                Â«IF !restrictions.rangeConstraints.empty»
+                    Â«rangeGenerator.generateRangeCheckerCall(paramName, paramValue(returnType, paramName))»
+                Â«ENDIF»
+                }
+            Â«ENDIF»
+        Â«ENDIF»
+    '''
+
+    def protected copyConstructor() '''
+    /**
+     * Creates a copy from Source Object.
+     *
+     * @param source Source object
+     */
+    public Â«type.name»(«type.name» source) {
+        Â«IF false == parentProperties.empty»
+            super(source);
+        Â«ENDIF»
+        Â«FOR p : properties»
+            this.«p.fieldName» = source.«p.fieldName»;
+        Â«ENDFOR»
+    }
+    '''
+
+    def protected parentConstructor() '''
+    /**
+     * Creates a new instance from Â«genTO.superType.importedName»
+     *
+     * @param source Source object
+     */
+    public Â«type.name»(«genTO.superType.importedName» source) {
+            super(source);
+    }
+    '''
+
+    def protected defaultInstance() '''
+        Â«IF genTO.typedef && !allProperties.empty && !genTO.unionType»
+            Â«val prop = allProperties.get(0)»
+            Â«IF !("org.opendaylight.yangtools.yang.binding.InstanceIdentifier".equals(prop.returnType.fullyQualifiedName))»
+            public static Â«genTO.name» getDefaultInstance(String defaultValue) {
+                Â«IF "byte[]".equals(prop.returnType.name)»
+                    Â«BaseEncoding.importedName» baseEncoding = Â«BaseEncoding.importedName».base64();
+                    return new Â«genTO.name»(baseEncoding.decode(defaultValue));
+                Â«ELSEIF "java.lang.String".equals(prop.returnType.fullyQualifiedName)»
+                    return new Â«genTO.name»(defaultValue);
+                Â«ELSEIF allProperties.size > 1»
+                    Â«bitsArgs»
+                Â«ELSEIF "java.lang.Boolean".equals(prop.returnType.fullyQualifiedName)»
+                    return new Â«genTO.name»(Boolean.valueOf(defaultValue));
+                Â«ELSEIF "java.lang.Byte".equals(prop.returnType.fullyQualifiedName)»
+                    return new Â«genTO.name»(Byte.valueOf(defaultValue));
+                Â«ELSEIF "java.lang.Short".equals(prop.returnType.fullyQualifiedName)»
+                    return new Â«genTO.name»(Short.valueOf(defaultValue));
+                Â«ELSEIF "java.lang.Integer".equals(prop.returnType.fullyQualifiedName)»
+                    return new Â«genTO.name»(Integer.valueOf(defaultValue));
+                Â«ELSEIF "java.lang.Long".equals(prop.returnType.fullyQualifiedName)»
+                    return new Â«genTO.name»(Long.valueOf(defaultValue));
+                Â«ELSE»
+                    return new Â«genTO.name»(new Â«prop.returnType.importedName»(defaultValue));
+                Â«ENDIF»
+            }
+            Â«ENDIF»
+        Â«ENDIF»
+    '''
+
+    def protected bitsArgs() '''
+        Â«List.importedName»<«String.importedName»> properties = Â«Lists.importedName».newArrayList(«allProperties.propsAsArgs»);
+        if (!properties.contains(defaultValue)) {
+            throw new Â«IllegalArgumentException.importedName»("invalid default parameter");
+        }
+        int i = 0;
+        return new Â«genTO.name»(
+        Â«FOR prop : allProperties SEPARATOR ","»
+            properties.get(i++).equals(defaultValue) ? Â«Boolean.importedName».TRUE : null
+        Â«ENDFOR»
+        );
+    '''
+
+    def protected propsAsArgs(Iterable<GeneratedProperty> properties) '''
+        Â«FOR prop : properties SEPARATOR ","»
+            "«prop.name»"
+        Â«ENDFOR»
+    '''
+
+    /**
+     * Template method which generates JAVA class declaration.
+     *
+     * @param isInnerClass boolean value which specify if generated class is|isn't inner
+     * @return string with class declaration in JAVA format
+     */
+    def protected generateClassDeclaration(boolean isInnerClass) '''
+        public«
+        IF (isInnerClass)»«
+            " static final "»«
+        ELSEIF (type.abstract)»«
+            " abstract "»«
+        ELSE»«
+            " "»«
+        ENDIF»class Â«type.name»«
+        IF (genTO.superType != null)»«
+            " extends "»«genTO.superType.importedName»«
+        ENDIF»
+        Â«IF (!type.implements.empty)»«
+            " implements "»«
+            FOR type : type.implements SEPARATOR ", "»«
+                type.importedName»«
+            ENDFOR»«
+        ENDIF
+    Â»'''
+
+    /**
+     * Template method which generates JAVA enum type.
+     *
+     * @return string with inner enum source code in JAVA format
+     */
+    def protected enumDeclarations() '''
+        Â«IF !enums.empty»
+            Â«FOR e : enums SEPARATOR "\n"»
+                Â«val enumTemplate = new EnumTemplate(e)»
+                Â«enumTemplate.generateAsInnerClass»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    def protected suidDeclaration() '''
+        Â«IF genTO.SUID != null»
+            private static final long serialVersionUID = Â«genTO.SUID.value»L;
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates JAVA constants.
+     *
+     * @return string with constants in JAVA format
+     */
+    def protected constantsDeclarations() '''
+        Â«IF !consts.empty»
+            Â«FOR c : consts»
+                Â«IF c.name == TypeConstants.PATTERN_CONSTANT_NAME»
+                    Â«val cValue = c.value»
+                    Â«IF cValue instanceof List<?>»
+                        private static final Â«Pattern.importedName»[] Â«Constants.MEMBER_PATTERN_LIST»;
+                        public static final Â«List.importedName»<String> Â«TypeConstants.PATTERN_CONSTANT_NAME» = Â«ImmutableList.importedName».of(«
+                        FOR v : cValue SEPARATOR ", "»«
+                            IF v instanceof String»"«
+                                v»"«
+                            ENDIF»«
+                        ENDFOR»);
+
+                        Â«generateStaticInicializationBlock»
+                    Â«ENDIF»
+                Â«ELSE»
+                    public static final Â«c.type.importedName» Â«c.name» = Â«c.value»;
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates JAVA static initialization block.
+     *
+     * @return string with static initialization block in JAVA format
+     */
+    def protected generateStaticInicializationBlock() '''
+        static {
+            final Â«Pattern.importedName» a[] = new Â«Pattern.importedName»[«TypeConstants.PATTERN_CONSTANT_NAME».size()];
+            int i = 0;
+            for (String regEx : Â«TypeConstants.PATTERN_CONSTANT_NAME») {
+                a[i++] = Pattern.compile(regEx);
+            }
+
+            Â«Constants.MEMBER_PATTERN_LIST» = a;
+        }
+    '''
+
+    /**
+     * Template method which generates JAVA class attributes.
+     *
+     * @return string with the class attributes in JAVA format
+     */
+    def protected generateFields() '''
+        Â«IF !properties.empty»
+            Â«FOR f : properties»
+                private«IF f.readOnly» final«ENDIF» Â«f.returnType.importedName» Â«f.fieldName»;
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates the method <code>hashCode()</code>.
+     *
+     * @return string with the <code>hashCode()</code> method definition in JAVA format
+     */
+    def protected generateHashCode() '''
+        Â«IF !genTO.hashCodeIdentifiers.empty»
+            @Override
+            public int hashCode() {
+                final int prime = 31;
+                int result = 1;
+                Â«FOR property : genTO.hashCodeIdentifiers»
+                    Â«IF property.returnType.name.contains("[")»
+                    result = prime * result + ((«property.fieldName» == null) ? 0 : Â«Arrays.importedName».hashCode(«property.fieldName»));
+                    Â«ELSE»
+                    result = prime * result + ((«property.fieldName» == null) ? 0 : Â«property.fieldName».hashCode());
+                    Â«ENDIF»
+                Â«ENDFOR»
+                return result;
+            }
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates the method <code>equals()</code>.
+     *
+     * @return string with the <code>equals()</code> method definition in JAVA format
+     */
+    def protected generateEquals() '''
+        Â«IF !genTO.equalsIdentifiers.empty»
+            @Override
+            public boolean equals(java.lang.Object obj) {
+                if (this == obj) {
+                    return true;
+                }
+                if (obj == null) {
+                    return false;
+                }
+                if (getClass() != obj.getClass()) {
+                    return false;
+                }
+                Â«type.name» other = («type.name») obj;
+                Â«FOR property : genTO.equalsIdentifiers»
+                    Â«val fieldName = property.fieldName»
+                    if («fieldName» == null) {
+                        if (other.«fieldName» != null) {
+                            return false;
+                        }
+                    Â«IF property.returnType.name.contains("[")»
+                    } else if(!«Arrays.importedName».equals(«fieldName», other.«fieldName»)) {
+                    Â«ELSE»
+                    } else if(!«fieldName».equals(other.«fieldName»)) {
+                    Â«ENDIF»
+                        return false;
+                    }
+                Â«ENDFOR»
+                return true;
+            }
+        Â«ENDIF»
+    '''
+
+    def GeneratedProperty getPropByName(String name) {
+        for (GeneratedProperty prop : allProperties) {
+            if (prop.name.equals(name)) {
+                return prop;
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/Constants.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/Constants.java
new file mode 100644 (file)
index 0000000..a3f07e0
--- /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.sal.java.api.generator;
+
+/**
+ * 
+ * Various constants when generating JAVA source code.
+ * 
+ */
+final class Constants {
+
+    public static final String COMMA = ",";
+    public static final String DOT = ".";
+
+    /**
+     * Name of the class constant which contains list of <code>Pattern</code>
+     * instances.
+     */
+    public static final String MEMBER_PATTERN_LIST = "patterns";
+
+    /**
+     * It doesn't have the sense to create the instances of this class.
+     */
+    private Constants() {
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/EnumGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/EnumGenerator.java
new file mode 100644 (file)
index 0000000..6cee013
--- /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.sal.java.api.generator;
+
+import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+/**
+ * 
+ * Transformator of the data from the virtual form to JAVA source code. The
+ * result source code represents JAVA enumeration. For generation of the source
+ * code is used the template written in XTEND language.
+ * 
+ */
+public class EnumGenerator implements CodeGenerator {
+
+    @Override
+    public boolean isAcceptable(Type type) {
+        return type instanceof Enumeration;
+    }
+
+    /**
+     * Generates JAVA source code for generated type <code>Type</code>. The code
+     * is generated according to the template source code template which is
+     * written in XTEND language.
+     */
+    @Override
+    public String generate(Type type) {
+        if (type instanceof Enumeration) {
+            final Enumeration enums = (Enumeration) type;
+            final EnumTemplate enumTemplate = new EnumTemplate(enums);
+            return enumTemplate.generate();
+        }
+        return "";
+    }
+
+    @Override
+    public String getUnitName(Type type) {
+        return type.getName();
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/EnumTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/EnumTemplate.xtend
new file mode 100644 (file)
index 0000000..92466b2
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 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.sal.java.api.generator
+
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+
+/**
+ * Template for generating JAVA enumeration type.
+ */
+class EnumTemplate extends BaseTemplate {
+
+
+    /**
+     * Enumeration which will be transformed to JAVA source code for enumeration
+     */
+    val Enumeration enums
+
+    /**
+     * Constructs instance of this class with concrete <code>enums</code>.
+     *
+     * @param enums enumeration which will be transformed to JAVA source code
+     */
+    new(Enumeration enums) {
+        super(enums as GeneratedType )
+        this.enums = enums
+    }
+
+
+    /**
+     * Generates only JAVA enumeration source code.
+     *
+     * @return string with JAVA enumeration source code
+     */
+    def generateAsInnerClass() {
+        return body
+    }
+
+    def writeEnumItem(String name, int value, String description) '''
+        Â«asJavadoc(formatToParagraph(description))»
+        Â«name»(«value»)
+    '''
+
+    /**
+     * Template method which generates enumeration body (declaration + enumeration items).
+     *
+     * @return string with the enumeration body
+     */
+    override body() '''
+        Â«wrapToDocumentation(formatDataForJavaDoc(enums))»
+        public enum Â«enums.name» {
+            Â«writeEnumeration(enums)»
+
+
+            int value;
+            private static final java.util.Map<java.lang.Integer, Â«enums.name»> VALUE_MAP;
+
+            static {
+                final com.google.common.collect.ImmutableMap.Builder<java.lang.Integer, Â«enums.name»> b = com.google.common.collect.ImmutableMap.builder();
+                for («enums.name» enumItem : Â«enums.name».values())
+                {
+                    b.put(enumItem.value, enumItem);
+                }
+
+                VALUE_MAP = b.build();
+            }
+
+            private Â«enums.name»(int value) {
+                this.value = value;
+            }
+
+            /**
+             * @return integer value
+             */
+            public int getIntValue() {
+                return value;
+            }
+
+            /**
+             * @param valueArg
+             * @return corresponding Â«enums.name» item
+             */
+            public static Â«enums.name» forValue(int valueArg) {
+                return VALUE_MAP.get(valueArg);
+            }
+        }
+    '''
+
+    def writeEnumeration(Enumeration enumeration)
+    '''
+    Â«FOR v : enumeration.values SEPARATOR ",\n" AFTER ";"»
+    Â«writeEnumItem(v.name, v.value, v.description)»«
+    ENDFOR»
+    '''
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/GeneratorJavaFile.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/GeneratorJavaFile.java
new file mode 100644 (file)
index 0000000..f863d14
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * 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.sal.java.api.generator;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonatype.plexus.build.incremental.BuildContext;
+import org.sonatype.plexus.build.incremental.DefaultBuildContext;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Generates files with JAVA source codes for every specified type.
+ *
+ */
+public final class GeneratorJavaFile {
+
+    private static final Logger LOG = LoggerFactory.getLogger(GeneratorJavaFile.class);
+
+    /**
+     * List of <code>CodeGenerator</code> instances.
+     */
+    private final List<CodeGenerator> generators = new ArrayList<>();
+
+    /**
+     * Set of <code>Type</code> instances for which the JAVA code is generated.
+     */
+    private final Collection<? extends Type> types;
+
+    /**
+     * BuildContext used for instantiating files
+     */
+    private final BuildContext buildContext;
+
+    /**
+     * Creates instance of this class with the set of <code>types</code> for
+     * which the JAVA code is generated.
+     *
+     * The instances of concrete JAVA code generator are created.
+     *
+     * @param buildContext
+     *            build context to use for accessing files
+     * @param types
+     *            set of types for which JAVA code should be generated
+     */
+    public GeneratorJavaFile(final BuildContext buildContext, final Collection<? extends Type> types) {
+        this.buildContext = Preconditions.checkNotNull(buildContext);
+        this.types = Preconditions.checkNotNull(types);
+        generators.add(new InterfaceGenerator());
+        generators.add(new TOGenerator());
+        generators.add(new EnumGenerator());
+        generators.add(new BuilderGenerator());
+    }
+
+    /**
+     * Creates instance of this class with the set of <code>types</code> for
+     * which the JAVA code is generated. Generator instantiated this way uses
+     * the default build context, e.g. it will re-generate any and all files.
+     *
+     * The instances of concrete JAVA code generator are created.
+     *
+     * @param types
+     *            set of types for which JAVA code should be generated
+     */
+    public GeneratorJavaFile(final Collection<? extends Type> types) {
+        this(new DefaultBuildContext(), types);
+    }
+
+    /**
+     * Generates list of files with JAVA source code. Only the suitable code
+     * generator is used to generate the source code for the concrete type.
+     *
+     * @param generatedSourcesDirectory
+     *            directory to which the output source codes should be generated
+     * @return list of output files
+     * @throws IOException
+     *             if the error during writing to the file occurs
+     */
+    public List<File> generateToFile(final File generatedSourcesDirectory) throws IOException {
+        return generateToFile(generatedSourcesDirectory, generatedSourcesDirectory);
+    }
+
+    public List<File> generateToFile(final File generatedSourcesDirectory, final File persistenSourcesDirectory)
+            throws IOException {
+        final List<File> result = new ArrayList<>();
+        for (Type type : types) {
+            if (type != null) {
+                for (CodeGenerator generator : generators) {
+                    File generatedJavaFile = null;
+                    if (type instanceof GeneratedTransferObject
+                            && ((GeneratedTransferObject) type).isUnionTypeBuilder()) {
+                        File packageDir = packageToDirectory(persistenSourcesDirectory, type.getPackageName());
+                        File file = new File(packageDir, generator.getUnitName(type) + ".java");
+                        if (!file.exists()) {
+                            generatedJavaFile = generateTypeToJavaFile(persistenSourcesDirectory, type, generator);
+                        }
+                    } else {
+                        generatedJavaFile = generateTypeToJavaFile(generatedSourcesDirectory, type, generator);
+                    }
+                    if (generatedJavaFile != null) {
+                        result.add(generatedJavaFile);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Generates <code>File</code> for <code>type</code>. All files are stored
+     * to subfolders of base directory <code>parentDir</code>. Subdirectories
+     * are generated according to packages to which the type belongs (e. g. if
+     * type belongs to the package <i>org.pcg</i> then in <code>parentDir</code>
+     * is created directory <i>org</i> which contains <i>pcg</i>).
+     *
+     * @param parentDir
+     *            directory where should be the new file generated
+     * @param type
+     *            JAVA <code>Type</code> for which should be JAVA source code
+     *            generated
+     * @param generator
+     *            code generator which is used for generating of the source code
+     * @return file which contains JAVA source code
+     * @throws IOException
+     *             if the error during writing to the file occurs
+     * @throws IllegalArgumentException
+     *             if <code>type</code> equals <code>null</code>
+     * @throws IllegalStateException
+     *             if string with generated code is empty
+     */
+    private File generateTypeToJavaFile(final File parentDir, final Type type, final CodeGenerator generator)
+            throws IOException {
+        if (parentDir == null) {
+            LOG.warn("Parent Directory not specified, files will be generated "
+                    + "accordingly to generated Type package path.");
+        }
+        if (type == null) {
+            LOG.error("Cannot generate Type into Java File because " + "Generated Type is NULL!");
+            throw new IllegalArgumentException("Generated Type Cannot be NULL!");
+        }
+        if (generator == null) {
+            LOG.error("Cannot generate Type into Java File because " + "Code Generator instance is NULL!");
+            throw new IllegalArgumentException("Code Generator Cannot be NULL!");
+        }
+        final File packageDir = packageToDirectory(parentDir, type.getPackageName());
+
+        if (!packageDir.exists()) {
+            packageDir.mkdirs();
+        }
+
+        if (generator.isAcceptable(type)) {
+            final String generatedCode = generator.generate(type);
+            if (generatedCode.isEmpty()) {
+                throw new IllegalStateException("Generated code should not be empty!");
+            }
+            final File file = new File(packageDir, generator.getUnitName(type) + ".java");
+
+            if (file.exists()) {
+                LOG.warn(
+                        "Naming conflict for type '{}': file with same name already exists and will not be generated.",
+                        type.getFullyQualifiedName());
+                return null;
+            }
+
+            try (final OutputStream stream = buildContext.newFileOutputStream(file)) {
+                try (final Writer fw = new OutputStreamWriter(stream)) {
+                    try (final BufferedWriter bw = new BufferedWriter(fw)) {
+                        bw.write(generatedCode);
+                    }
+                } catch (IOException e) {
+                    LOG.error("Failed to write generate output into {}", file.getPath(), e);
+                    throw e;
+                }
+            }
+            return file;
+
+        }
+        return null;
+    }
+
+    /**
+     * Creates the package directory path as concatenation of
+     * <code>parentDirectory</code> and parsed <code>packageName</code>. The
+     * parsing of <code>packageName</code> is realized as replacement of the
+     * package name dots with the file system separator.
+     *
+     * @param parentDirectory
+     *            <code>File</code> object with reference to parent directory
+     * @param packageName
+     *            string with the name of the package
+     * @return <code>File</code> object which refers to the new directory for
+     *         package <code>packageName</code>
+     */
+    public static File packageToDirectory(final File parentDirectory, final String packageName) {
+        if (packageName == null) {
+            throw new IllegalArgumentException("Package Name cannot be NULL!");
+        }
+
+        final String[] subDirNames = packageName.split("\\.");
+        final StringBuilder dirPathBuilder = new StringBuilder();
+        dirPathBuilder.append(subDirNames[0]);
+        for (int i = 1; i < subDirNames.length; ++i) {
+            dirPathBuilder.append(File.separator);
+            dirPathBuilder.append(subDirNames[i]);
+        }
+        return new File(parentDirectory, dirPathBuilder.toString());
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/GeneratorUtil.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/GeneratorUtil.java
new file mode 100644 (file)
index 0000000..5d1939a
--- /dev/null
@@ -0,0 +1,413 @@
+/*
+ * 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.sal.java.api.generator;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static org.opendaylight.yangtools.sal.java.api.generator.Constants.COMMA;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.yangtools.binding.generator.util.TypeConstants;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.WildcardType;
+
+public final class GeneratorUtil {
+
+    /**
+     * It doesn't have the sense to create the instances of this class.
+     */
+    private GeneratorUtil() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns the map of imports. The map maps the type name to the package
+     * name. To the map are added packages for <code>genType</code> and for all
+     * enclosed types, constants, methods (parameter types, return values),
+     * implemented types.
+     *
+     * @param genType
+     *            generated type for which the map of the imports is created
+     * @return map of the necessary imports
+     * @throws IllegalArgumentException
+     *             if <code>genType</code> equals <code>null</code>
+     */
+    public static Map<String, String> createImports(final GeneratedType genType) {
+        if (genType == null) {
+            throw new IllegalArgumentException("Generated Type cannot be NULL!");
+        }
+        final Map<String, String> imports = new LinkedHashMap<>();
+
+        List<GeneratedType> childGeneratedTypes = genType.getEnclosedTypes();
+        if (!childGeneratedTypes.isEmpty()) {
+            for (GeneratedType genTypeChild : childGeneratedTypes) {
+                imports.putAll(createImports(genTypeChild));
+            }
+        }
+
+        // REGULAR EXPRESSION
+        if (genType instanceof GeneratedTransferObject
+                && isConstantInTO(TypeConstants.PATTERN_CONSTANT_NAME, (GeneratedTransferObject) genType)) {
+            putTypeIntoImports(genType, Types.typeForClass(java.util.regex.Pattern.class), imports);
+            putTypeIntoImports(genType, Types.typeForClass(java.util.Arrays.class), imports);
+            putTypeIntoImports(genType, Types.typeForClass(java.util.ArrayList.class), imports);
+        }
+
+        final List<MethodSignature> methods = genType.getMethodDefinitions();
+        // METHODS
+        if (methods != null) {
+            for (final MethodSignature method : methods) {
+                final Type methodReturnType = method.getReturnType();
+                putTypeIntoImports(genType, methodReturnType, imports);
+                for (final MethodSignature.Parameter methodParam : method.getParameters()) {
+                    putTypeIntoImports(genType, methodParam.getType(), imports);
+                }
+                for (final AnnotationType at : method.getAnnotations()) {
+                    putTypeIntoImports(genType, at, imports);
+                }
+            }
+        }
+
+        // PROPERTIES
+        if (genType instanceof GeneratedTransferObject) {
+            final GeneratedTransferObject genTO = (GeneratedTransferObject) genType;
+            final List<GeneratedProperty> properties = genTO.getProperties();
+            if (properties != null) {
+                for (GeneratedProperty property : properties) {
+                    final Type propertyType = property.getReturnType();
+                    putTypeIntoImports(genType, propertyType, imports);
+                }
+            }
+        }
+
+        return imports;
+    }
+
+    /**
+     * Evaluates if it is necessary to add the package name for
+     * <code>type</code> to the map of imports for <code>parentGenType</code>.
+     * If it is so the package name is saved to the map <code>imports</code>.
+     *
+     * @param parentGenType
+     *            generated type for which is the map of the necessary imports
+     *            built
+     * @param type
+     *            JAVA <code>Type</code> for which is the necessary of the
+     *            package import evaluated
+     * @param imports
+     *            map of the imports for <code>parentGenType</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if the <code>parentGenType</code> equals
+     *             <code>null</code></li>
+     *             <li>if the name of <code>parentGenType</code> equals
+     *             <code>null</code></li>
+     *             <li>if the name of the package of <code>parentGenType</code>
+     *             equals <code>null</code></li>
+     *             <li>if the <code>type</code> equals <code>null</code></li>
+     *             <li>if the name of <code>type</code> equals <code>null</code>
+     *             </li>
+     *             <li>if the name of the package of <code>type</code> equals
+     *             <code>null</code></li>
+     *             </ul>
+     */
+    public static void putTypeIntoImports(final GeneratedType parentGenType, final Type type,
+            final Map<String, String> imports) {
+        checkArgument(parentGenType != null, "Parent Generated Type parameter MUST be specified and cannot be "
+                + "NULL!");
+        checkArgument(parentGenType.getName() != null, "Parent Generated Type name cannot be NULL!");
+        checkArgument(parentGenType.getPackageName() != null,
+                "Parent Generated Type cannot have Package Name referenced as NULL!");
+        checkArgument(type != null, "Type parameter MUST be specified and cannot be NULL!");
+
+        checkArgument(type.getName() != null, "Type name cannot be NULL!");
+        checkArgument(type.getPackageName() != null, "Type cannot have Package Name referenced as NULL!");
+
+        final String typeName = type.getName();
+        final String typePackageName = type.getPackageName();
+        final String parentTypeName = parentGenType.getName();
+        if (typeName.equals(parentTypeName) || typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
+            return;
+        }
+        if (!imports.containsKey(typeName)) {
+            imports.put(typeName, typePackageName);
+        }
+        if (type instanceof ParameterizedType) {
+            final ParameterizedType paramType = (ParameterizedType) type;
+            final Type[] params = paramType.getActualTypeArguments();
+            if (params != null) {
+                for (Type param : params) {
+                    putTypeIntoImports(parentGenType, param, imports);
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks if the constant with the name <code>constName</code> is in the
+     * list of the constant definition for <code>genTO</code>.
+     *
+     * @param constName
+     *            string with the name of constant which is sought
+     * @param genTO
+     *            generated transfer object in which is <code>constName</code>
+     *            sought
+     * @return boolean value
+     *         <ul>
+     *         <li>true - if <code>constName</code> is in the list of the
+     *         constant definition for <code>genTO</code></li>
+     *         <li>false - in other cases</li>
+     *         </ul>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>constName</code> equals <code>null</code></li>
+     *             <li>if <code>genTO</code> equals <code>null</code></li>
+     *             </ul>
+     */
+    public static boolean isConstantInTO(final String constName, final GeneratedTransferObject genTO) {
+        if (constName == null || genTO == null) {
+            throw new IllegalArgumentException();
+        }
+        List<Constant> consts = genTO.getConstantDefinitions();
+        for (Constant cons : consts) {
+            if (cons.getName().equals(constName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Creates the map which maps the type name to package name and contains
+     * only package names for enclosed types of <code>genType</code> and
+     * recursivelly their enclosed types.
+     *
+     * @param genType
+     *            JAVA <code>Type</code> for which is the map created
+     * @return map of the package names for all the enclosed types and
+     *         recursivelly their enclosed types
+     */
+    public static Map<String, String> createChildImports(final GeneratedType genType) {
+        Map<String, String> childImports = new LinkedHashMap<>();
+        List<GeneratedType> childGeneratedTypes = genType.getEnclosedTypes();
+        if (!childGeneratedTypes.isEmpty()) {
+            for (GeneratedType genTypeChild : childGeneratedTypes) {
+                createChildImports(genTypeChild);
+                childImports.put(genTypeChild.getName(), genTypeChild.getPackageName());
+            }
+        }
+        return childImports;
+    }
+
+    /**
+     * Builds the string which contains either the full path to the type
+     * (package name with type) or only type name if the package is among
+     * <code>imports</code>.
+     *
+     * @param parentGenType
+     *            generated type which contains <code>type</code>
+     * @param type
+     *            JAVA <code>Type</code> for which is the string with type info
+     *            generated
+     * @param imports
+     *            map of necessary imports for <code>parentGenType</code>
+     * @return string with type name for <code>type</code> in the full format or
+     *         in the short format
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if the <code>type</code> equals <code>null</code></li>
+     *             <li>if the name of the <code>type</code> equals
+     *             <code>null</code></li>
+     *             <li>if the name of the package of the <code>type</code>
+     *             equals <code>null</code></li>
+     *             <li>if the <code>imports</code> equals <code>null</code></li>
+     *             </ul>
+     */
+    public static String getExplicitType(final GeneratedType parentGenType, final Type type,
+            final Map<String, String> imports) {
+
+        checkArgument(type != null, "Type parameter MUST be specified and cannot be NULL!");
+        checkArgument(type.getName() != null, "Type name cannot be NULL!");
+        checkArgument(type.getPackageName() != null, "Type cannot have Package Name referenced as NULL!");
+        checkArgument(imports != null, "Imports Map cannot be NULL!");
+
+        final String typePackageName = type.getPackageName();
+        final String typeName = type.getName();
+        final String importedPackageName = imports.get(typeName);
+        final StringBuilder builder;
+        if (typePackageName.equals(importedPackageName)) {
+            builder = new StringBuilder(type.getName());
+            addActualTypeParameters(builder, type, parentGenType, imports);
+            if (builder.toString().equals("Void")) {
+                return "void";
+            }
+        } else {
+            builder = new StringBuilder();
+                if (!typePackageName.isEmpty()) {
+                    builder.append(typePackageName + Constants.DOT + type.getName());
+                } else {
+                    builder.append(type.getName());
+                }
+            if (type.equals(Types.voidType())) {
+                return "void";
+            }
+            addActualTypeParameters(builder, type, parentGenType, imports);
+        }
+        return builder.toString();
+
+    }
+
+    /**
+     * Adds actual type parameters from <code>type</code> to
+     * <code>builder</code> if <code>type</code> is
+     * <code>ParametrizedType</code>.
+     *
+     * @param builder
+     *            string builder which contains type name
+     * @param type
+     *            JAVA <code>Type</code> for which is the string with type info
+     *            generated
+     * @param parentGenType
+     *            generated type which contains <code>type</code>
+     * @param imports
+     *            map of necessary imports for <code>parentGenType</code>
+     * @return if <code>type</code> is of the type <code>ParametrizedType</code> <br />
+     *         <li>then <code>builder</code> + actual <code>type</code>
+     *         parameters</li> <li>else only <code>builder</code></li>
+     */
+    private static StringBuilder addActualTypeParameters(final StringBuilder builder, final Type type,
+            final GeneratedType parentGenType, final Map<String, String> imports) {
+        if (type instanceof ParameterizedType) {
+            final ParameterizedType pType = (ParameterizedType) type;
+            final Type[] pTypes = pType.getActualTypeArguments();
+            builder.append("<");
+            builder.append(getParameters(parentGenType, pTypes, imports));
+            builder.append(">");
+        }
+        return builder;
+    }
+
+    /**
+     * Generates the string with all actual type parameters from
+     * <code>pTypes</code>
+     *
+     * @param parentGenType
+     *            generated type for which is the JAVA code generated
+     * @param pTypes
+     *            array of <code>Type</code> instances = actual type parameters
+     * @param availableImports
+     *            map of imports for <code>parentGenType</code>
+     * @return string with all actual type parameters from <code>pTypes</code>
+     */
+    private static String getParameters(final GeneratedType parentGenType, final Type[] pTypes,
+            final Map<String, String> availableImports) {
+        if (pTypes == null || pTypes.length == 0) {
+            return "?";
+        }
+        final StringBuilder builder = new StringBuilder();
+        for (int i = 0; i < pTypes.length; i++) {
+            final Type t = pTypes[i];
+
+            String separator = COMMA;
+            if (i == (pTypes.length - 1)) {
+                separator = "";
+            }
+
+            String wildcardParam = "";
+            if (t.equals(Types.voidType())) {
+                builder.append("java.lang.Void" + separator);
+                continue;
+            } else {
+
+                if (t instanceof WildcardType) {
+                    wildcardParam = "? extends ";
+                }
+
+                builder.append(wildcardParam + getExplicitType(parentGenType, t, availableImports) + separator);
+            }
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Returns the reference to highest (top parent) Generated Transfer Object.
+     *
+     * @param childTransportObject
+     *            is generated transfer object which can be extended by other
+     *            generated transfer object
+     * @return in first case that <code>childTransportObject</code> isn't
+     *         extended then <code>childTransportObject</code> is returned. In
+     *         second case the method is recursive called until first case.
+     * @throws IllegalArgumentException
+     *             if <code>childTransportObject</code> equals <code>null</code>
+     */
+    public static GeneratedTransferObject getTopParrentTransportObject(final GeneratedTransferObject childTransportObject) {
+        if (childTransportObject == null) {
+            throw new IllegalArgumentException("Parameter childTransportObject can't be null.");
+        }
+        if (childTransportObject.getSuperType() == null) {
+            return childTransportObject;
+        } else {
+            return getTopParrentTransportObject(childTransportObject.getSuperType());
+        }
+    }
+
+    /**
+     * Selects from input list of properties only those which have read only
+     * attribute set to true.
+     *
+     * @param properties
+     *            list of properties of generated transfer object
+     * @return subset of <code>properties</code> which have read only attribute
+     *         set to true
+     */
+    public static List<GeneratedProperty> resolveReadOnlyPropertiesFromTO(final List<GeneratedProperty> properties) {
+        List<GeneratedProperty> readOnlyProperties = new ArrayList<GeneratedProperty>();
+        if (properties != null) {
+            for (final GeneratedProperty property : properties) {
+                if (property.isReadOnly()) {
+                    readOnlyProperties.add(property);
+                }
+            }
+        }
+        return readOnlyProperties;
+    }
+
+    /**
+     * Returns the list of the read only properties of all extending generated
+     * transfer object from <code>genTO</code> to highest parent generated
+     * transfer object
+     *
+     * @param genTO
+     *            generated transfer object for which is the list of read only
+     *            properties generated
+     * @return list of all read only properties from actual to highest parent
+     *         generated transfer object. In case when extension exists the
+     *         method is recursive called.
+     */
+    public static List<GeneratedProperty> getPropertiesOfAllParents(final GeneratedTransferObject genTO) {
+        List<GeneratedProperty> propertiesOfAllParents = new ArrayList<GeneratedProperty>();
+        if (genTO.getSuperType() != null) {
+            final List<GeneratedProperty> allPropertiesOfTO = genTO.getSuperType().getProperties();
+            List<GeneratedProperty> readOnlyPropertiesOfTO = resolveReadOnlyPropertiesFromTO(allPropertiesOfTO);
+            propertiesOfAllParents.addAll(readOnlyPropertiesOfTO);
+            propertiesOfAllParents.addAll(getPropertiesOfAllParents(genTO.getSuperType()));
+        }
+        return propertiesOfAllParents;
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/IntegerRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/IntegerRangeGenerator.java
new file mode 100644 (file)
index 0000000..525e385
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+final class IntegerRangeGenerator extends AbstractPrimitiveRangeGenerator<Integer> {
+    IntegerRangeGenerator() {
+        super(Integer.class, int.class.getName(), Integer.MIN_VALUE, Integer.MAX_VALUE);
+    }
+
+    @Override
+    protected String format(final Integer value) {
+        return value.toString();
+    }
+
+    @Override
+    protected Integer convert(final Number value) {
+        return value.intValue();
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/InterfaceGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/InterfaceGenerator.java
new file mode 100644 (file)
index 0000000..d3c6a3f
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.sal.java.api.generator;
+
+/**
+ *
+ * Transformator of the data from the virtual form to JAVA source code. The result source code represents JAVA interface. For
+ * generating of the source code is used the template written in XTEND language.
+ *
+ */
+import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+public final class InterfaceGenerator implements CodeGenerator {
+
+    @Override
+    public boolean isAcceptable(Type type) {
+        return type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)
+                && !(type instanceof Enumeration);
+    }
+
+    /**
+     * Generates JAVA source code for generated type <code>Type</code>. The code
+     * is generated according to the template source code template which is
+     * written in XTEND language.
+     */
+    @Override
+    public String generate(Type type) {
+        if (type instanceof GeneratedType && !(type instanceof GeneratedTransferObject)) {
+            final GeneratedType genType = (GeneratedType) type;
+            final InterfaceTemplate interfaceTemplate = new InterfaceTemplate(genType);
+            return interfaceTemplate.generate();
+        }
+        return "";
+    }
+
+    @Override
+    public String getUnitName(Type type) {
+        return type.getName();
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/InterfaceTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/InterfaceTemplate.xtend
new file mode 100644 (file)
index 0000000..acca70d
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * 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.sal.java.api.generator
+
+import java.util.List
+import org.opendaylight.yangtools.binding.generator.util.TypeConstants
+import org.opendaylight.yangtools.sal.binding.model.api.Constant
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature\rimport org.opendaylight.yangtools.sal.binding.model.api.AnnotationType
+
+/**
+ * Template for generating JAVA interfaces.
+ */
+class InterfaceTemplate extends BaseTemplate {
+
+    /**
+     * List of constant instances which are generated as JAVA public static final attributes.
+     */
+    val List<Constant> consts
+
+    /**
+     * List of method signatures which are generated as method declarations.
+     */
+    val List<MethodSignature> methods
+
+    /**
+     * List of enumeration which are generated as JAVA enum type.
+     */
+    val List<Enumeration> enums
+
+    /**
+     * List of generated types which are enclosed inside <code>genType</code>
+     */
+    val List<GeneratedType> enclosedGeneratedTypes
+
+    /**
+     * Creates the instance of this class which is used for generating the interface file source
+     * code from <code>genType</code>.
+     *
+     * @throws IllegalArgumentException if <code>genType</code> equals <code>null</code>
+     */
+    new(GeneratedType genType) {
+        super(genType)
+        if (genType == null) {
+            throw new IllegalArgumentException("Generated type reference cannot be NULL!")
+        }
+
+        consts = genType.constantDefinitions
+        methods = genType.methodDefinitions
+        enums = genType.enumerations
+        enclosedGeneratedTypes = genType.enclosedTypes
+    }
+
+    /**
+     * Template method which generate the whole body of the interface.
+     *
+     * @return string with code for interface body in JAVA format
+     */
+    override body() '''
+        Â«wrapToDocumentation(formatDataForJavaDoc(type))»
+        public interface Â«type.name»
+            Â«superInterfaces»
+        {
+
+            Â«generateInnerClasses»
+
+            Â«generateEnums»
+
+            Â«generateConstants»
+
+            Â«generateMethods»
+
+        }
+
+    '''
+
+
+    def private generateAnnotations(List<AnnotationType> annotations) '''
+        Â«IF annotations != null && !annotations.empty»
+            Â«FOR annotation : annotations»
+                @«annotation.importedName»
+                Â«IF annotation.parameters != null && !annotation.parameters.empty»
+                (
+                Â«FOR param : annotation.parameters SEPARATOR ","»
+                    Â«param.name»=«param.value»
+                Â«ENDFOR»
+                )
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates the interface name declaration.
+     *
+     * @return string with the code for the interface declaration in JAVA format
+     */
+    def private superInterfaces()
+    '''
+    Â«IF (!type.implements.empty)»
+         extends
+         Â«FOR type : type.implements SEPARATOR ","»
+             Â«type.importedName»
+         Â«ENDFOR»
+     Â« ENDIF»
+     '''
+
+    /**
+     * Template method which generates inner classes inside this interface.
+     *
+     * @return string with the source code for inner classes in JAVA format
+     */
+    def private generateInnerClasses() '''
+        Â«IF !enclosedGeneratedTypes.empty»
+            Â«FOR innerClass : enclosedGeneratedTypes SEPARATOR "\n"»
+                Â«IF (innerClass instanceof GeneratedTransferObject)»
+                    Â«IF innerClass.unionType»
+                        Â«val unionTemplate = new UnionTemplate(innerClass)»
+                        Â«unionTemplate.generateAsInnerClass»
+                        Â«this.importMap.putAll(unionTemplate.importMap)»
+                    Â«ELSE»
+                        Â«val classTemplate = new ClassTemplate(innerClass)»
+                        Â«classTemplate.generateAsInnerClass»
+                        Â«this.importMap.putAll(classTemplate.importMap)»
+                    Â«ENDIF»
+
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates JAVA enum type.
+     *
+     * @return string with inner enum source code in JAVA format
+     */
+    def private generateEnums() '''
+        Â«IF !enums.empty»
+            Â«FOR e : enums SEPARATOR "\n"»
+                Â«val enumTemplate = new EnumTemplate(e)»
+                Â«enumTemplate.generateAsInnerClass»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method wich generates JAVA constants.
+     *
+     * @return string with constants in JAVA format
+     */
+    def private generateConstants() '''
+        Â«IF !consts.empty»
+            Â«FOR c : consts»
+                Â«IF c.name != TypeConstants.PATTERN_CONSTANT_NAME»
+                    public static final Â«c.type.importedName» Â«c.name» = Â«c.value»;
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    /**
+     * Template method which generates the declaration of the methods.
+     *
+     * @return string with the declaration of methods source code in JAVA format
+     */
+    def private generateMethods() '''
+        Â«IF !methods.empty»
+            Â«FOR m : methods SEPARATOR "\n"»
+                Â«m.comment.asJavadoc»
+                Â«m.annotations.generateAnnotations»
+                Â«m.returnType.importedName» Â«m.name»(«m.parameters.generateParameters»);
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+}
+
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/LengthGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/LengthGenerator.java
new file mode 100644 (file)
index 0000000..089eafd
--- /dev/null
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+import com.google.common.collect.Range;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+
+final class LengthGenerator {
+    private LengthGenerator() {
+        throw new UnsupportedOperationException();
+    }
+
+    private static String lengthCheckerName(final String member) {
+        return "check" + member + "Length";
+    }
+
+    private static Collection<String> createExpressions(final Collection<LengthConstraint> constraints) {
+        final Collection<String> ret = new ArrayList<>(constraints.size());
+
+        for (LengthConstraint l : constraints) {
+            final StringBuilder sb = new StringBuilder("length >");
+
+            // We have to deal with restrictions being out of integer's range
+            if (l.getMin().longValue() <= Integer.MAX_VALUE) {
+                sb.append('=');
+            }
+            sb.append(' ').append(l.getMin().intValue());
+
+            final int max = l.getMax().intValue();
+            if (max < Integer.MAX_VALUE) {
+                sb.append(" && length <= ").append(max);
+            }
+
+            ret.add(sb.toString());
+        }
+
+        return ret;
+    }
+
+    private static String createLengthString(final Collection<LengthConstraint> constraints) {
+        final List<Range<BigInteger>> ranges = new ArrayList<>(constraints.size());
+
+        for (LengthConstraint c : constraints) {
+            ranges.add(Range.closed(new BigInteger(c.getMin().toString()), new BigInteger(c.getMax().toString())));
+        }
+
+        return ranges.toString();
+    }
+
+    private static String generateArrayLengthChecker(final String member, final Collection<LengthConstraint> constraints) {
+        final StringBuilder sb = new StringBuilder();
+        final Collection<String> expressions = createExpressions(constraints);
+
+        sb.append("private static void ").append(lengthCheckerName(member)).append("(final byte[] value) {\n");
+
+        if (!expressions.isEmpty()) {
+            sb.append("    final int length = value.length;\n");
+
+            for (String exp : expressions) {
+                sb.append("    if (").append(exp).append(") {\n");
+                sb.append("        return;\n");
+                sb.append("    }\n");
+            }
+
+            sb.append("    throw new IllegalArgumentException(String.format(\"Invalid length: %s, expected: ")
+              .append(createLengthString(constraints)).append(".\", java.util.Arrays.toString(value)));\n");
+        }
+
+        sb.append("}\n");
+
+        return sb.toString();
+    }
+
+    private static String generateStringLengthChecker(final String member, final Collection<LengthConstraint> constraints) {
+        final StringBuilder sb = new StringBuilder();
+        final Collection<String> expressions = createExpressions(constraints);
+
+        sb.append("private static void ").append(lengthCheckerName(member)).append("(final String value) {\n");
+
+        if (!expressions.isEmpty()) {
+            sb.append("    final int length = value.length();\n");
+
+            for (String exp : expressions) {
+                sb.append("    if (").append(exp).append(") {\n");
+                sb.append("        return;\n");
+                sb.append("    }\n");
+            }
+
+            sb.append("    throw new IllegalArgumentException(String.format(\"Invalid length: %s, expected: ")
+              .append(createLengthString(constraints)).append(".\", value));\n");
+        }
+
+        sb.append("}\n");
+
+        return sb.toString();
+    }
+
+    static String generateLengthChecker(final String member, final Type type, final Collection<LengthConstraint> constraints) {
+        if (TypeUtils.getBaseYangType(type).getName().contains("[")) {
+            return generateArrayLengthChecker(member, constraints);
+        } else {
+            return generateStringLengthChecker(member, constraints);
+        }
+    }
+
+    static String generateLengthCheckerCall(@Nullable final String member, @Nonnull final String valueReference) {
+        return lengthCheckerName(member) + '(' + valueReference + ");\n";
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/LongRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/LongRangeGenerator.java
new file mode 100644 (file)
index 0000000..781283f
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+final class LongRangeGenerator extends AbstractPrimitiveRangeGenerator<Long> {
+
+    protected LongRangeGenerator() {
+        super(Long.class, long.class.getName(), Long.MIN_VALUE, Long.MAX_VALUE);
+    }
+
+    @Override
+    protected String format(final Long value) {
+        return value.toString() + 'L';
+    }
+
+    @Override
+    protected Long convert(final Number value) {
+        return value.longValue();
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ShortRangeGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ShortRangeGenerator.java
new file mode 100644 (file)
index 0000000..abe07a5
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+final class ShortRangeGenerator extends AbstractSubIntegerRangeGenerator<Short> {
+    ShortRangeGenerator() {
+        super(Short.class, short.class.getName(), Short.MIN_VALUE, Short.MAX_VALUE);
+    }
+
+    @Override
+    protected Short convert(final Number value) {
+        return value.shortValue();
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/TOGenerator.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/TOGenerator.java
new file mode 100644 (file)
index 0000000..a17927e
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.sal.java.api.generator;
+
+import org.opendaylight.yangtools.sal.binding.model.api.CodeGenerator;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+/**
+ *
+ * Transformator of the data from the virtual form to JAVA source code. The
+ * result source code represents JAVA class. For generating of the source code
+ * is used the template written in XTEND language.
+ *
+ */
+public final class TOGenerator implements CodeGenerator {
+
+    /**
+     * Generates JAVA source code for generated type <code>Type</code>. The code
+     * is generated according to the template source code template which is
+     * written in XTEND language.
+     */
+    @Override
+    public String generate(Type type) {
+        if (type instanceof GeneratedTransferObject) {
+            final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
+            if(genTO.isUnionType()) {
+                final UnionTemplate template = new UnionTemplate(genTO);
+                return template.generate();
+            } else if (genTO.isUnionTypeBuilder()) {
+                final UnionBuilderTemplate template = new UnionBuilderTemplate(genTO);
+                return template.generate();
+            } else {
+                final ClassTemplate template = new ClassTemplate(genTO);
+                return template.generate();
+            }
+        }
+        return "";
+    }
+
+    @Override
+    public boolean isAcceptable(Type type) {
+        return type instanceof GeneratedTransferObject;
+    }
+
+    @Override
+    public String getUnitName(Type type) {
+        return type.getName();
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/TypeUtils.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/TypeUtils.java
new file mode 100644 (file)
index 0000000..928c8e9
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 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.sal.java.api.generator;
+
+import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+/**
+ * Random utility methods for dealing with {@link Type} objects.
+ */
+final class TypeUtils {
+    private static final String VALUE_PROP = "value";
+
+    private TypeUtils() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Given a {@link Type} object lookup the base Java type which sits at the top
+     * of its type hierarchy.
+     *
+     * @param type Input Type object
+     * @return Resolved {@link ConcreteType} instance.
+     */
+    static ConcreteType getBaseYangType(@Nonnull final Type type) {
+        // Already the correct type
+        if (type instanceof ConcreteType) {
+            return (ConcreteType) type;
+        }
+
+        Preconditions.checkArgument(type instanceof GeneratedTransferObject, "Unsupported type %s", type);
+
+        // Need to walk up the GTO chain to the root
+        GeneratedTransferObject rootGto = (GeneratedTransferObject) type;
+        while (rootGto.getSuperType() != null) {
+            rootGto = rootGto.getSuperType();
+        }
+
+        // Look for the 'value' property and return its type
+        for (GeneratedProperty s : rootGto.getProperties()) {
+            if (VALUE_PROP.equals(s.getName())) {
+                return (ConcreteType) s.getReturnType();
+            }
+        }
+
+        // Should never happen
+        throw new IllegalArgumentException(String.format("Type %s root %s properties %s do not include \"%s\"",
+            type, rootGto, rootGto.getProperties(), VALUE_PROP));
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionBuilderTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionBuilderTemplate.xtend
new file mode 100644 (file)
index 0000000..13c9fc3
--- /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.sal.java.api.generator
+
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier
+
+/**
+ * Template for generating JAVA class.
+ */
+class UnionBuilderTemplate extends ClassTemplate {
+
+    /**
+     * Creates instance of this class with concrete <code>genType</code>.
+     *
+     * @param genType generated transfer object which will be transformed to JAVA class source code
+     */
+    new(GeneratedTransferObject genType) {
+        super(genType)
+    }
+
+    def override body() '''
+        Â«wrapToDocumentation(formatDataForJavaDoc(type, getClarification()))»
+        public class Â«type.name» {
+
+            Â«generateMethods»
+
+        }
+    '''
+
+    def private generateMethods() '''
+        Â«FOR method : genTO.methodDefinitions»
+            Â«method.accessModifier.accessModifier»«IF method.static»static«ENDIF»«IF method.final» final«ENDIF» Â«method.
+            returnType.importedName» Â«method.name»(«method.parameters.generateParameters») {
+                throw new Â«UnsupportedOperationException.importedName»("Not yet implemented");
+            }
+        Â«ENDFOR»
+    '''
+
+    def private String getAccessModifier(AccessModifier modifier) {
+        switch (modifier) {
+            case AccessModifier.PUBLIC: return "public "
+            case AccessModifier.PROTECTED: return "protected "
+            case AccessModifier.PRIVATE: return "private "
+            default: return ""
+        }
+    }
+
+    def private String getClarification() {
+        return
+        '''
+        The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+        In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+
+        The reason behind putting it under src/main/java is:
+        This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+        loss of user code.
+        '''
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/UnionTemplate.xtend
new file mode 100644 (file)
index 0000000..78c2cd0
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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.sal.java.api.generator
+
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
+import java.beans.ConstructorProperties
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration
+import static org.opendaylight.yangtools.binding.generator.util.Types.*
+
+/**
+ * Template for generating JAVA class.
+ */
+class UnionTemplate extends ClassTemplate {
+
+    /**
+     * Creates instance of this class with concrete <code>genType</code>.
+     *
+     * @param genType generated transfer object which will be transformed to JAVA class source code
+     */
+    new(GeneratedTransferObject genType) {
+        super(genType)
+    }
+
+    override constructors() '''
+        Â«unionConstructorsParentProperties»
+        Â«unionConstructors»
+        Â«IF !allProperties.empty»
+            Â«copyConstructor»
+        Â«ENDIF»
+        Â«IF properties.empty && !parentProperties.empty»
+            Â«parentConstructor»
+        Â«ENDIF»
+    '''
+
+    private def unionConstructors() '''
+        Â«FOR property : finalProperties SEPARATOR "\n"»
+            Â«val propRet = property.returnType»
+            Â«val isCharArray = "char[]".equals(propRet.name)»
+            Â«IF isCharArray»
+                /**
+                 * Constructor provided only for using in JMX. Don't use it for
+                 * construction new object of this union type.
+                 */
+                @«ConstructorProperties.importedName»("«property.name»")
+                public Â«type.name»(«propRet.importedName» Â«property.fieldName») {
+                    Â«String.importedName» defVal = new Â«String.importedName»(«property.fieldName»);
+                    Â«type.name» defInst = Â«typeBuilder()».getDefaultInstance(defVal);
+                    Â«FOR other : finalProperties»
+                        Â«IF other.name.equals("value")»
+                            Â«IF other.returnType.importedName.contains("[]")»
+                            this.«other.fieldName» = Â«other.fieldName» == null ? null : Â«other.fieldName».clone();
+                            Â«ELSE»
+                            this.«other.fieldName» = Â«other.fieldName»;
+                            Â«ENDIF»
+                        Â«ELSE»
+                            this.«other.fieldName» = defInst.«other.fieldName»;
+                        Â«ENDIF»
+                    Â«ENDFOR»
+                }
+            Â«ELSE»
+                Â«val propertyAndTopParentProperties = parentProperties + #[property]»
+                public Â«type.name»(«propertyAndTopParentProperties.asArgumentsDeclaration») {
+                    super(«parentProperties.asArguments»);
+                    this.«property.fieldName» = Â«property.fieldName»;
+                    Â«FOR other : finalProperties»
+                        Â«IF property != other»
+                            Â«IF "value".equals(other.name)»
+                                Â«IF "java.lang.String".equals(propRet.fullyQualifiedName)»
+                                    Â«Â«Â« type string
+                                    this.«other.fieldName» = Â«property.fieldName».toCharArray();
+                                Â«ELSEIF "byte[]".equals(propRet.name)»
+                                    Â«Â«Â« type binary
+                                    this.«other.fieldName» = new Â«String.importedName»(«property.fieldName»).toCharArray();
+                                Â«ELSEIF propRet.fullyQualifiedName.startsWith("java.lang") || propRet instanceof Enumeration»
+                                    Â«Â«Â« type int*, uint or enumeration*
+                                    this.«other.fieldName» = Â«property.fieldName».toString().toCharArray();
+                                Â«ELSEIF propRet instanceof GeneratedTransferObject && (propRet as GeneratedTransferObject).unionType»
+                                    Â«Â«Â« union type
+                                    this.«other.fieldName» = Â«property.fieldName».getValue();
+                                Â«ELSEIF propRet instanceof GeneratedTransferObject // Is it a GeneratedTransferObject
+                                        && (propRet as GeneratedTransferObject).typedef  // Is it a typedef
+                                        && (propRet as GeneratedTransferObject).properties != null
+                                        && !(propRet as GeneratedTransferObject).properties.empty
+                                        && ((propRet as GeneratedTransferObject).properties.size == 1)
+                                        && (propRet as GeneratedTransferObject).properties.get(0).name.equals("value")
+                                        && BOOLEAN.equals((propRet as GeneratedTransferObject).properties.get(0).returnType)» // And the property value is of type boolean
+                                    Â«Â«Â« generated boolean typedef
+                                    this.«other.fieldName» = Â«property.fieldName».isValue().toString().toCharArray();
+                                Â«ELSE»
+                                    Â«Â«Â« generated type
+                                    this.«other.fieldName» = Â«property.fieldName».getValue().toString().toCharArray();
+                                Â«ENDIF»
+                            Â«ELSE»
+                                this.«other.fieldName» = null;
+                            Â«ENDIF»
+                        Â«ENDIF»
+                    Â«ENDFOR»
+                }
+            Â«ENDIF»
+        Â«ENDFOR»
+    '''
+    
+    def typeBuilder() {
+        val outerCls = getOuterClassName(type);
+        if(outerCls !== null) {
+            return outerCls + type.name + "Builder"
+        }
+        return type.name + "Builder"
+    }
+
+    private def unionConstructorsParentProperties() '''
+        Â«FOR property : parentProperties SEPARATOR "\n"»
+            public Â«type.name»(«property.returnType.importedName» Â«property.fieldName») {
+                super(«property.fieldName»);
+            }
+        Â«ENDFOR»
+    '''
+
+    override protected copyConstructor() '''
+        /**
+         * Creates a copy from Source Object.
+         *
+         * @param source Source object
+         */
+        public Â«type.name»(«type.name» source) {
+            Â«IF !parentProperties.empty»
+                super(source);
+            Â«ENDIF»
+            Â«IF !properties.empty»
+                Â«FOR p : properties»
+                    Â«IF p.returnType.importedName.contains("[]")»
+                    this.«p.fieldName» = source.«p.fieldName» == null ? null : source.«p.fieldName».clone();
+                    Â«ELSE»
+                    this.«p.fieldName» = source.«p.fieldName»;
+                    Â«ENDIF»
+                Â«ENDFOR»
+            Â«ENDIF»
+        }
+    '''
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/YangModuleInfoTemplate.xtend b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/YangModuleInfoTemplate.xtend
new file mode 100644 (file)
index 0000000..6469370
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+ * 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.sal.java.api.generator
+
+import java.io.InputStream
+import java.io.IOException
+import java.text.DateFormat
+import java.text.SimpleDateFormat
+
+import java.util.Collections
+import java.util.Date
+import java.util.HashSet
+import java.util.LinkedHashMap
+import java.util.Map
+import java.util.Set
+import java.util.TreeMap
+
+import org.opendaylight.yangtools.binding.generator.util.Types
+import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType
+import org.opendaylight.yangtools.sal.binding.model.api.Type
+import org.opendaylight.yangtools.sal.binding.model.api.WildcardType
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo
+import org.opendaylight.yangtools.yang.model.api.Module
+import org.opendaylight.yangtools.yang.model.api.SchemaContext
+
+import com.google.common.collect.ImmutableSet
+import static org.opendaylight.yangtools.yang.binding.BindingMapping.*
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider
+import com.google.common.base.Preconditions
+
+class YangModuleInfoTemplate {
+
+    val Module module
+    val SchemaContext ctx
+    val Map<String, String> importMap = new LinkedHashMap()
+
+    @Property
+    val String packageName;
+
+    @Property
+    val String modelBindingProviderName;
+
+    new(Module module, SchemaContext ctx) {
+        Preconditions.checkArgument(module != null, "Module must not be null.");
+        this.module = module
+        this.ctx = ctx
+        _packageName = getRootPackageName(module.getQNameModule());
+        _modelBindingProviderName = '''«packageName».«MODEL_BINDING_PROVIDER_CLASS_NAME»''';
+    }
+
+    def String generate() {
+        val body = '''
+            public final class Â«MODULE_INFO_CLASS_NAME» implements Â«YangModuleInfo.importedName» {
+
+                private static final Â«YangModuleInfo.importedName» INSTANCE = new Â«MODULE_INFO_CLASS_NAME»();
+
+                private final Â«String.importedName» name = "«module.name»";
+                private final Â«String.importedName» namespace = "«module.namespace.toString»";
+                Â«val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
+                private final Â«String.importedName» revision = "«df.format(module.revision)»";
+                private final Â«String.importedName» resourcePath = "«sourcePath»";
+
+                private final Â«Set.importedName»<YangModuleInfo> importedModules;
+
+                public static Â«YangModuleInfo.importedName» getInstance() {
+                    return INSTANCE;
+                }
+
+                Â«classBody(module, MODULE_INFO_CLASS_NAME)»
+            }
+        '''
+        return '''
+            package Â«packageName» ;
+            Â«imports»
+            Â«body»
+        '''.toString
+    }
+
+    def String generateModelProvider() {
+        '''
+            package Â«packageName»;
+
+            public final class Â«MODEL_BINDING_PROVIDER_CLASS_NAME» implements Â«YangModelBindingProvider.name» {
+
+                public Â«YangModuleInfo.name» getModuleInfo() {
+                    return Â«MODULE_INFO_CLASS_NAME».getInstance();
+                }
+            }
+        '''
+
+    }
+
+    private def CharSequence classBody(Module m, String className) '''
+        private Â«className»() {
+            Â«IF !m.imports.empty || !m.submodules.empty»
+                Â«Set.importedName»<«YangModuleInfo.importedName»> set = new Â«HashSet.importedName»<>();
+            Â«ENDIF»
+            Â«IF !m.imports.empty»
+                Â«FOR imp : m.imports»
+                    Â«val name = imp.moduleName»
+                    Â«val rev = imp.revision»
+                    Â«IF rev == null»
+                        Â«val Set<Module> modules = ctx.modules»
+                        Â«val TreeMap<Date, Module> sorted = new TreeMap()»
+                        Â«FOR module : modules»
+                            Â«IF module.name.equals(name)»
+                                Â«sorted.put(module.revision, module)»
+                            Â«ENDIF»
+                        Â«ENDFOR»
+                        set.add(«getRootPackageName(sorted.lastEntry().value.QNameModule)».«MODULE_INFO_CLASS_NAME».getInstance());
+                    Â«ELSE»
+                        set.add(«getRootPackageName((ctx.findModuleByName(name, rev).QNameModule))».«MODULE_INFO_CLASS_NAME».getInstance());
+                    Â«ENDIF»
+                Â«ENDFOR»
+            Â«ENDIF»
+            Â«IF !m.submodules.empty»
+                Â«FOR submodule : m.submodules»
+                    set.add(«getClassName(submodule.name)»Info.getInstance());
+                Â«ENDFOR»
+            Â«ENDIF»
+            Â«IF m.imports.empty && m.submodules.empty»
+                importedModules = Â«Collections.importedName».emptySet();
+            Â«ELSE»
+                importedModules = Â«ImmutableSet.importedName».copyOf(set);
+            Â«ENDIF»
+
+            Â«InputStream.importedName» stream = Â«MODULE_INFO_CLASS_NAME».class.getResourceAsStream(resourcePath);
+            if (stream == null) {
+                throw new IllegalStateException("Resource '" + resourcePath + "' is missing");
+            }
+            try {
+                stream.close();
+            } catch («IOException.importedName» e) {
+            // Resource leak, but there is nothing we can do
+            }
+        }
+
+        @Override
+        public Â«String.importedName» getName() {
+            return name;
+        }
+
+        @Override
+        public Â«String.importedName» getRevision() {
+            return revision;
+        }
+
+        @Override
+        public Â«String.importedName» getNamespace() {
+            return namespace;
+        }
+
+        @Override
+        public Â«InputStream.importedName» getModuleSourceStream() throws IOException {
+            Â«InputStream.importedName» stream = Â«MODULE_INFO_CLASS_NAME».class.getResourceAsStream(resourcePath);
+            if (stream == null) {
+                throw new Â«IOException.importedName»("Resource " + resourcePath + " is missing");
+            }
+            return stream;
+        }
+
+        @Override
+        public Â«Set.importedName»<«YangModuleInfo.importedName»> getImportedModules() {
+            return importedModules;
+        }
+
+        @Override
+        public Â«String.importedName» toString() {
+            Â«StringBuilder.importedName» sb = new Â«StringBuilder.importedName»(this.getClass().getCanonicalName());
+            sb.append("[");
+            sb.append("name = " + name);
+            sb.append(", namespace = " + namespace);
+            sb.append(", revision = " + revision);
+            sb.append(", resourcePath = " + resourcePath);
+            sb.append(", imports = " + importedModules);
+            sb.append("]");
+            return sb.toString();
+        }
+
+        Â«generateSubInfo(m)»
+
+    '''
+
+    def getSourcePath() {
+        return "/" + module.moduleSourcePath.replace(java.io.File.separatorChar, '/')
+    }
+
+    private def imports() '''
+        Â«IF !importMap.empty»
+            Â«FOR entry : importMap.entrySet»
+                Â«IF entry.value != getRootPackageName(module.QNameModule)»
+                    import Â«entry.value».«entry.key»;
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    final protected def importedName(Class<?> cls) {
+        val Type intype = Types.typeForClass(cls)
+        putTypeIntoImports(intype);
+        getExplicitType(intype)
+    }
+
+    final def void putTypeIntoImports(Type type) {
+        val String typeName = type.getName();
+        val String typePackageName = type.getPackageName();
+        if (typePackageName.startsWith("java.lang") || typePackageName.isEmpty()) {
+            return;
+        }
+        if (!importMap.containsKey(typeName)) {
+            importMap.put(typeName, typePackageName);
+        }
+        if (type instanceof ParameterizedType) {
+            val Type[] params = type.getActualTypeArguments()
+            if (params != null) {
+                for (Type param : params) {
+                    putTypeIntoImports(param);
+                }
+            }
+        }
+    }
+
+    final def String getExplicitType(Type type) {
+        val String typePackageName = type.getPackageName();
+        val String typeName = type.getName();
+        val String importedPackageName = importMap.get(typeName);
+        var StringBuilder builder;
+        if (typePackageName.equals(importedPackageName)) {
+            builder = new StringBuilder(type.getName());
+            addActualTypeParameters(builder, type);
+            if (builder.toString().equals("Void")) {
+                return "void";
+            }
+        } else {
+            builder = new StringBuilder();
+            if (typePackageName.startsWith("java.lang")) {
+                builder.append(type.getName());
+            } else {
+                if (!typePackageName.isEmpty()) {
+                    builder.append(typePackageName + Constants.DOT + type.getName());
+                } else {
+                    builder.append(type.getName());
+                }
+            }
+            if (type.equals(Types.voidType())) {
+                return "void";
+            }
+            addActualTypeParameters(builder, type);
+        }
+        return builder.toString();
+    }
+
+    final def StringBuilder addActualTypeParameters(StringBuilder builder, Type type) {
+        if (type instanceof ParameterizedType) {
+            val Type[] pTypes = type.getActualTypeArguments();
+            builder.append('<');
+            builder.append(getParameters(pTypes));
+            builder.append('>');
+        }
+        return builder;
+    }
+
+    final def String getParameters(Type[] pTypes) {
+        if (pTypes == null || pTypes.length == 0) {
+            return "?";
+        }
+        val StringBuilder builder = new StringBuilder();
+
+        var int i = 0;
+        for (pType : pTypes) {
+            val Type t = pTypes.get(i)
+
+            var String separator = ",";
+            if (i == (pTypes.length - 1)) {
+                separator = "";
+            }
+
+            var String wildcardParam = "";
+            if (t.equals(Types.voidType())) {
+                builder.append("java.lang.Void" + separator);
+            } else {
+
+                if (t instanceof WildcardType) {
+                    wildcardParam = "? extends ";
+                }
+
+                builder.append(wildcardParam + getExplicitType(t) + separator);
+                i = i + 1
+            }
+        }
+        return builder.toString();
+    }
+
+    private def generateSubInfo(Module module) '''
+        Â«FOR submodule : module.submodules»
+            private static final class Â«getClassName(submodule.name)»Info implements Â«YangModuleInfo.importedName» {
+
+                private static final Â«YangModuleInfo.importedName» INSTANCE = new Â«getClassName(submodule.name)»Info();
+
+                private final Â«String.importedName» name = "«submodule.name»";
+                private final Â«String.importedName» namespace = "«submodule.namespace.toString»";
+                Â«val DateFormat df = new SimpleDateFormat("yyyy-MM-dd")»
+                private final Â«String.importedName» revision = "«df.format(submodule.revision)»";
+                private final Â«String.importedName» resourcePath = "/«submodule.moduleSourcePath.replace(java.io.File.separatorChar, '/')»";
+
+                private final Â«Set.importedName»<YangModuleInfo> importedModules;
+
+                public static Â«YangModuleInfo.importedName» getInstance() {
+                    return INSTANCE;
+                }
+
+                Â«classBody(submodule, getClassName(submodule.name + "Info"))»
+            }
+        Â«ENDFOR»
+    '''
+
+}
diff --git a/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/package-info.java b/code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/package-info.java
new file mode 100644 (file)
index 0000000..c952c6c
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.sal.java.api.generator;
\ No newline at end of file
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/AugmentToUsesInAugmentCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/AugmentToUsesInAugmentCompilationTest.java
new file mode 100644 (file)
index 0000000..41521a7
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_BAR;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_BAZ;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_FOO;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertFilesCount;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertImplementsIfc;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testAugmentation;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.collect.ImmutableSet;
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class AugmentToUsesInAugmentCompilationTest extends BaseCompilationTest {
+
+    @Test
+    public void testAugmentToUsesInAugment() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "augment-uses-to-augment");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-uses-to-augment");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/augment-uses-to-augment");
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
+        generator.generateToFile(sourcesOutputDir);
+
+        // Test if all sources are generated from 'module foo'
+        File fooParent = new File(sourcesOutputDir, NS_FOO);
+        assertFilesCount(fooParent, 4);
+        assertTrue(new File(fooParent, "IgpLinkAttributes.java").exists());
+        assertTrue(new File(fooParent, "Link1.java").exists());
+        assertTrue(new File(fooParent, "Link1Builder.java").exists());
+
+        // Test if all sources are generated from 'module bar'
+        File barParent = new File(sourcesOutputDir, NS_BAR);
+        assertFilesCount(barParent, 7);
+        assertTrue(new File(barParent, "BarData.java").exists());
+        assertTrue(new File(barParent, "NetworkTopology.java").exists());
+        assertTrue(new File(barParent, "NetworkTopologyBuilder.java").exists());
+        assertTrue(new File(barParent, "Link.java").exists());
+        assertTrue(new File(barParent, "LinkAttributes.java").exists());
+
+        File networkParent = new File(barParent, "network");
+        assertFilesCount(networkParent, 1);
+        File topologyParent = new File(networkParent, "topology");
+        assertFilesCount(topologyParent, 3);
+        assertTrue(new File(topologyParent, "Topology.java").exists());
+        assertTrue(new File(topologyParent, "TopologyBuilder.java").exists());
+        assertTrue(new File(topologyParent, "TopologyKey.java").exists());
+
+        File linkParent = new File(barParent, "link");
+        assertFilesCount(linkParent, 3);
+        assertTrue(new File(linkParent, "Link.java").exists());
+        assertTrue(new File(linkParent, "LinkBuilder.java").exists());
+        assertTrue(new File(linkParent, "LinkKey.java").exists());
+
+        // Test if all sources are generated from 'module baz'
+        File bazParent = new File(sourcesOutputDir, NS_BAZ);
+        assertFilesCount(bazParent, 4);
+        assertTrue(new File(bazParent, "IgpLinkAttributes1.java").exists());
+        assertTrue(new File(bazParent, "IgpLinkAttributes1Builder.java").exists());
+        assertTrue(new File(bazParent, "LinkAttributes.java").exists());
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+
+        try {
+            Class<?> link1Class = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.Link1", true, loader);
+            String augmentableNode = BASE_PKG + ".urn.opendaylight.bar.rev131008.link.Link";
+            testAugmentation(link1Class, augmentableNode);
+
+            Class<?> igpLinkAttributesClass = Class.forName(BASE_PKG
+                    + ".urn.opendaylight.foo.rev131008.IgpLinkAttributes", true, loader);
+            assertImplementsIfc(link1Class, igpLinkAttributesClass);
+        } catch (ClassNotFoundException e) {
+            throw new AssertionError("Class for augment wasn't generated");
+        }
+
+        try {
+            Class<?> igpLinkAttributes1Class = Class.forName(BASE_PKG
+                    + ".urn.opendaylight.baz.rev131008.IgpLinkAttributes1", true, loader);
+            String augmentableNode = BASE_PKG + ".urn.opendaylight.foo.rev131008.igp.link.attributes.IgpLinkAttributes";
+            testAugmentation(igpLinkAttributes1Class, augmentableNode);
+
+            Class<?> linkAttributesClass = Class.forName(BASE_PKG + ".urn.opendaylight.baz.rev131008.LinkAttributes",
+                    true, loader);
+            assertImplementsIfc(igpLinkAttributes1Class, linkAttributesClass);
+        } catch (ClassNotFoundException e) {
+            throw new AssertionError("Class for augment wasn't generated");
+        }
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/BaseCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/BaseCompilationTest.java
new file mode 100644 (file)
index 0000000..8d8e843
--- /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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.*;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public abstract class BaseCompilationTest {
+
+    protected YangParserImpl parser;
+    protected BindingGenerator bindingGenerator;
+
+    @BeforeClass
+    public static void createTestDirs() {
+        if (TEST_DIR.exists()) {
+            deleteTestDir(TEST_DIR);
+        }
+        assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
+        assertTrue(COMPILER_OUTPUT_DIR.mkdirs());
+    }
+
+    @Before
+    public void init() {
+        parser = new YangParserImpl();
+        bindingGenerator = new BindingGeneratorImpl();
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/Bug1276Test.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/Bug1276Test.java
new file mode 100644 (file)
index 0000000..9e2bfb6
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsConstructor;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.collect.ImmutableSet;
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Previous construction of union constructor
+ *
+ * <code>
+ * public IpAddress(Arg1 _arg1) {
+ *     super();
+ *     this._arg1 = _arg1;
+ *     this._arg2 = null;
+ *     this._value = null;
+ * }
+ * </code>
+ *
+ * was incorrect and setting
+ *
+ * <code>this._value == null</code>
+ *
+ * was replaced with setting _value to correct value, for example:
+ *
+ * <code>this._value = arg1.getValue()</code> or
+ * <code>this._value = _arg1.getValue().toString().toCharArray()</code>
+ *
+ */
+public class Bug1276Test extends BaseCompilationTest {
+
+    @Test
+    public void test() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug1276");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug1276");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/bug1276", sourcesOutputDir);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        Class<?> ipAddressClass = Class.forName(BASE_PKG + ".test.yang.union.rev140715.IpAddress", true, loader);
+        Class<?> ipv4AddressClass = Class.forName(BASE_PKG + ".test.yang.union.rev140715.Ipv4Address", true, loader);
+        Class<?> hostClass = Class.forName(BASE_PKG + ".test.yang.union.rev140715.Host", true, loader);
+
+        Constructor<?> ipAddressConstructor = assertContainsConstructor(ipAddressClass, ipv4AddressClass);
+        Constructor<?> ipv4addressConstructor = assertContainsConstructor(ipv4AddressClass, String.class);
+        Constructor<?> hostConstructor = assertContainsConstructor(hostClass, ipAddressClass);
+
+        // test IpAddress with Ipv4Address argument
+        Object ipv4address = ipv4addressConstructor.newInstance("192.168.0.1");
+        Object ipAddress = ipAddressConstructor.newInstance(ipv4address);
+        Method getValue = ipAddressClass.getDeclaredMethod("getValue");
+        char[] expected = "192.168.0.1".toCharArray();
+        Object actual = getValue.invoke(ipAddress);
+        assertTrue(actual instanceof char[]);
+        assertTrue(Arrays.equals(expected, (char[]) actual));
+
+        // test Host with IpAddress argument
+        Object host = hostConstructor.newInstance(ipAddress);
+        getValue = hostClass.getDeclaredMethod("getValue");
+        actual = getValue.invoke(host);
+        assertTrue(actual instanceof char[]);
+        assertTrue(Arrays.equals(expected, (char[]) actual));
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    private void generateTestSources(final String resourceDirPath, final File sourcesOutputDir) throws Exception {
+        final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
+        generator.generateToFile(sourcesOutputDir);
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/Bug532Test.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/Bug532Test.java
new file mode 100644 (file)
index 0000000..df865df
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.List;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Test correct functionality of copy constructor of generated builder classes.
+ */
+public class Bug532Test extends BaseCompilationTest {
+
+    @Test
+    public void test() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug532");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug532");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/list-gen", sourcesOutputDir);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        Class<?> linksKeyClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.LinksKey", true, loader);
+        Class<?> linksClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.Links", true, loader);
+        Class<?> linksBuilderClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.LinksBuilder", true,
+                loader);
+        Class<?> levelClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.links.Level", true, loader);
+        Class<?> nodeClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.links.Node", true, loader);
+        Class<?> nodeListClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.links.NodeList", true,
+                loader);
+
+        // init default values
+        Byte expectedId = Byte.valueOf("5");
+        String expectedName = "test-link";
+        Integer expectedSize = Integer.valueOf(10);
+        Object expectedLevel = Mockito.mock(levelClass);
+        Integer expectedLinksId = Integer.valueOf(11);
+        Object expectedNode = Mockito.mock(nodeClass);
+        List<?> expectedNodeList = Lists.newArrayList(Mockito.mock(nodeListClass), Mockito.mock(nodeListClass));
+        Constructor<?> keyConstructor = linksKeyClass.getDeclaredConstructor(Byte.class, String.class, Integer.class);
+        Object expectedKey = keyConstructor.newInstance(expectedId, expectedName, expectedSize);
+
+        // create Links object
+        Object linksBuilder = linksBuilderClass.newInstance();
+        linksBuilderClass.getDeclaredMethod("setKey", linksKeyClass).invoke(linksBuilder, expectedKey);
+        linksBuilderClass.getDeclaredMethod("setLevel", levelClass).invoke(linksBuilder, expectedLevel);
+        linksBuilderClass.getDeclaredMethod("setLinksId", Integer.class).invoke(linksBuilder, expectedLinksId);
+        linksBuilderClass.getDeclaredMethod("setNode", nodeClass).invoke(linksBuilder, expectedNode);
+        linksBuilderClass.getDeclaredMethod("setNodeList", List.class).invoke(linksBuilder, expectedNodeList);
+        Object links = linksBuilderClass.getDeclaredMethod("build").invoke(linksBuilder);
+
+        // create LinksBuilder object with constructor with Links object
+        // argument
+        Constructor<?> linksBuilderConstructor = linksBuilderClass.getDeclaredConstructor(linksClass);
+        assertNotNull(linksBuilderConstructor);
+        Object linksBuilderTested = linksBuilderConstructor.newInstance(links);
+
+        // get values from LinksBuilder
+        Object actualKey = linksBuilderClass.getDeclaredMethod("getKey").invoke(linksBuilderTested);
+        Object actualId = linksBuilderClass.getDeclaredMethod("getId").invoke(linksBuilderTested);
+        Object actualName = linksBuilderClass.getDeclaredMethod("getName").invoke(linksBuilderTested);
+        Object actualSize = linksBuilderClass.getDeclaredMethod("getSize").invoke(linksBuilderTested);
+        Object actualLevel = linksBuilderClass.getDeclaredMethod("getLevel").invoke(linksBuilderTested);
+        Object actualLinksId = linksBuilderClass.getDeclaredMethod("getLinksId").invoke(linksBuilderTested);
+        Object actualNode = linksBuilderClass.getDeclaredMethod("getNode").invoke(linksBuilderTested);
+        Object actualNodeList = linksBuilderClass.getDeclaredMethod("getNodeList").invoke(linksBuilderTested);
+
+        // test
+        assertEquals(expectedKey, actualKey);
+        assertEquals(expectedId, actualId);
+        assertEquals(expectedName, actualName);
+        assertEquals(expectedSize, actualSize);
+        assertEquals(expectedLevel, actualLevel);
+        assertEquals(expectedLinksId, actualLinksId);
+        assertEquals(expectedNode, actualNode);
+        assertEquals(expectedNodeList, actualNodeList);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    private void generateTestSources(final String resourceDirPath, final File sourcesOutputDir) throws Exception {
+        final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
+        generator.generateToFile(sourcesOutputDir);
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CascadeUsesCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CascadeUsesCompilationTest.java
new file mode 100644 (file)
index 0000000..004bfc7
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+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 static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_BAR;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_BAZ;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_FOO;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertFilesCount;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertImplementsIfc;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.collect.ImmutableSet;
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class CascadeUsesCompilationTest extends BaseCompilationTest {
+
+    @Test
+    public void testCascadeUsesCompilation() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "cascade-uses");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "cascade-uses");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/cascade-uses");
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
+        generator.generateToFile(sourcesOutputDir);
+
+        // Test if all sources are generated from module foo
+        File parent = new File(sourcesOutputDir, NS_FOO);
+        assertFilesCount(parent, 5);
+        File fooData = new File(parent, "FooData.java");
+        File foo_gr1 = new File(parent, "FooGr1.java");
+        File nodes = new File(parent, "Nodes.java");
+        File nodesBuilder = new File(parent, "NodesBuilder.java");
+        assertTrue(fooData.exists());
+        assertTrue(foo_gr1.exists());
+        assertTrue(nodes.exists());
+        assertTrue(nodesBuilder.exists());
+
+        // Test if all sources are generated from module bar
+        parent = new File(sourcesOutputDir, NS_BAR);
+        assertFilesCount(parent, 2);
+        File barGr1 = new File(parent, "BarGr1.java");
+        File barGr2 = new File(parent, "BarGr2.java");
+        assertTrue(barGr1.exists());
+        assertTrue(barGr2.exists());
+
+        // Test if all sources are generated from module baz
+        parent = new File(sourcesOutputDir, NS_BAZ);
+        assertFilesCount(parent, 1);
+        File bazGr1 = new File(parent, "BazGr1.java");
+        assertTrue(bazGr1.exists());
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        Class<?> nodesClass = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.Nodes", true,
+                loader);
+        Class<?> nodesBuilderClass = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.NodesBuilder", true,
+                loader);
+        Class<?> fooGr1Class = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.FooGr1", true, loader);
+        Class<?> barGr2Class = Class.forName(BASE_PKG + ".urn.opendaylight.bar.rev131008.BarGr2", true, loader);
+        Class<?> barGr1Class = Class.forName(BASE_PKG + ".urn.opendaylight.bar.rev131008.BarGr1", true, loader);
+        Class<?> bazGr1Class = Class.forName(BASE_PKG + ".urn.opendaylight.baz.rev131008.BazGr1", true, loader);
+
+        // test generated interface from 'container nodes'
+        assertImplementsIfc(nodesClass, fooGr1Class);
+        assertImplementsIfc(nodesClass, barGr2Class);
+
+        // test generated builder for 'container nodes'
+        assertFalse(nodesBuilderClass.isInterface());
+        Constructor<?>[] nodesBuilderConstructors = nodesBuilderClass.getConstructors();
+        assertEquals(6, nodesBuilderConstructors.length);
+
+        // test generation of builder constructors from uses in 'container nodes'
+        Constructor<?> defaultConstructor = null;
+        Constructor<?> usesFooGr1 = null;
+        Constructor<?> usesBarGr2 = null;
+        Constructor<?> usesBarGr1 = null;
+        Constructor<?> usesBazGr1 = null;
+        for (Constructor<?> c : nodesBuilderConstructors) {
+            Class<?>[] params = c.getParameterTypes();
+            if (params.length == 0) {
+                defaultConstructor = c;
+            } else {
+                assertEquals(1, params.length);
+                if (params[0].equals(fooGr1Class)) {
+                    usesFooGr1 = c;
+                } else if (params[0].equals(barGr2Class)) {
+                    usesBarGr2 = c;
+                } else if (params[0].equals(barGr1Class)) {
+                    usesBarGr1 = c;
+                } else if (params[0].equals(bazGr1Class)) {
+                    usesBazGr1 = c;
+                }
+            }
+        }
+        assertNotNull(defaultConstructor);
+        assertNotNull(usesFooGr1);
+        assertNotNull(usesBarGr2);
+        assertNotNull(usesBarGr1);
+        assertNotNull(usesBazGr1);
+
+        Method fieldsFromMethod = null;
+        for (Method m : nodesBuilderClass.getDeclaredMethods()) {
+            String methodName = m.getName();
+            if ("fieldsFrom".equals(methodName)) {
+                fieldsFromMethod = m;
+            }
+        }
+        assertNotNull(fieldsFromMethod);
+        assertEquals(1, fieldsFromMethod.getParameterTypes().length);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/ClassCodeGeneratorTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/ClassCodeGeneratorTest.java
new file mode 100644 (file)
index 0000000..e2b65e8
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+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 java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.java.api.generator.TOGenerator;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+public class ClassCodeGeneratorTest {
+
+    private final static List<File> testModels = new ArrayList<File>();
+
+    @BeforeClass
+    public static void loadTestResources() throws URISyntaxException {
+        final File listModelFile = new File(ClassCodeGeneratorTest.class
+                .getResource("/list-composite-key.yang").toURI());
+        testModels.add(listModelFile);
+    }
+
+    @Test
+    public void compositeKeyClassTest() throws IOException {
+        final YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(testModels);
+
+        assertNotNull(context);
+        final BindingGenerator bindingGen = new BindingGeneratorImpl();
+        final List<Type> genTypes = bindingGen.generateTypes(context);
+
+        assertTrue(genTypes != null);
+        assertEquals(7, genTypes.size());
+
+        int genTypesCount = 0;
+        int genTOsCount = 0;
+        for (final Type type : genTypes) {
+            if (type instanceof GeneratedType
+                    && !(type instanceof GeneratedTransferObject)) {
+                genTypesCount++;
+            } else if (type instanceof GeneratedTransferObject) {
+                final GeneratedTransferObject genTO = (GeneratedTransferObject) type;
+
+                if (genTO.getName().equals("CompositeKeyListKey")) {
+                    final List<GeneratedProperty> properties = genTO
+                            .getProperties();
+                    int propertyCount = 0;
+                    for (final GeneratedProperty prop : properties) {
+                        if (prop.getName().equals("key1")) {
+                            propertyCount++;
+                        } else if (prop.getName().equals("key2")) {
+                            propertyCount++;
+                        }
+                    }
+
+                    final TOGenerator clsGen = new TOGenerator();
+                    final String outputStr = clsGen.generate(genTO);
+
+                    assertNotNull(outputStr);
+                    assertTrue(outputStr.contains("public CompositeKeyListKey(java.lang.Byte _key1, java.lang.String _key2)"));
+
+                    assertEquals(2, propertyCount);
+                    genTOsCount++;
+                } else if (genTO.getName().equals("InnerListKey")) {
+                    final List<GeneratedProperty> properties = genTO
+                            .getProperties();
+                    assertEquals(1, properties.size());
+                    genTOsCount++;
+                }
+            }
+        }
+
+        assertEquals(5, genTypesCount);
+        assertEquals(2, genTOsCount);
+    }
+
+    /**
+     * Test for testing of false scenario.
+     *
+     * Test tests value types. Value types are not allowed to have default constructor.
+     */
+    @Test
+    public void defaultConstructorNotPresentInValueTypeTest() {
+        final GeneratedTOBuilder toBuilder = new GeneratedTOBuilderImpl(
+                "simple.pack", "DefCtor");
+
+        GeneratedPropertyBuilder propBuilder = toBuilder.addProperty("foo");
+        propBuilder.setReturnType(Types.typeForClass(String.class));
+        propBuilder.setReadOnly(false);
+
+        propBuilder = toBuilder.addProperty("bar");
+        propBuilder.setReturnType(Types.typeForClass(Integer.class));
+        propBuilder.setReadOnly(false);
+
+        final GeneratedTransferObject genTO = toBuilder.toInstance();
+
+        final TOGenerator clsGen = new TOGenerator();
+        final String outputStr = clsGen.generate(genTO);
+
+        assertNotNull(outputStr);
+        assertFalse(outputStr.contains("public DefCtor()"));
+    }
+
+    @Test
+    public void toStringTest() {
+        final GeneratedTOBuilder toBuilder = new GeneratedTOBuilderImpl(
+                "simple.pack", "DefCtor");
+
+        GeneratedPropertyBuilder propBuilder = toBuilder.addProperty("foo");
+        propBuilder.setReturnType(Types.typeForClass(String.class));
+        propBuilder.setReadOnly(false);
+        toBuilder.addToStringProperty(propBuilder);
+
+        propBuilder = toBuilder.addProperty("bar");
+        propBuilder.setReturnType(Types.typeForClass(Integer.class));
+        propBuilder.setReadOnly(false);
+        toBuilder.addToStringProperty(propBuilder);
+        final GeneratedTransferObject genTO = toBuilder.toInstance();
+        final TOGenerator clsGen = new TOGenerator();
+        assertNotNull(clsGen.generate(genTO));
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTest.java
new file mode 100644 (file)
index 0000000..7d45f8f
--- /dev/null
@@ -0,0 +1,659 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_BAR;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_BAZ;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_FOO;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_TEST;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsConstructor;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsField;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsMethod;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsRestrictionCheck;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertFilesCount;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertImplementsIfc;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertImplementsParameterizedIfc;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Range;
+import java.io.File;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.WildcardType;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.annotations.RoutingContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Test correct code generation.
+ *
+ */
+public class CompilationTest extends BaseCompilationTest {
+
+    /*
+     * Java 8 allows JaCoCo to hook onto interfaces, as well as
+     * generating a default implementation. We only want to check
+     * abstract methods.
+     */
+    private static Collection<Method> abstractMethods(final Class<?> clazz) {
+        // Filter out
+        return Collections2.filter(Arrays.asList(clazz.getDeclaredMethods()), new Predicate<Method>() {
+            @Override
+            public boolean apply(final Method input) {
+                return Modifier.isAbstract(input.getModifiers());
+            }
+        });
+    }
+
+    @Test
+    public void testListGeneration() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "list-gen");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "list-gen");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/list-gen", sourcesOutputDir);
+
+        // Test if all sources are generated
+        File parent = new File(sourcesOutputDir, NS_TEST);
+        final File keyArgs = new File(parent, "KeyArgs.java");
+        final File links = new File(parent, "Links.java");
+        final File linksBuilder = new File(parent, "LinksBuilder.java");
+        final File linksKey = new File(parent, "LinksKey.java");
+        final File testData = new File(parent, "TestData.java");
+        assertTrue(keyArgs.exists());
+        assertTrue(links.exists());
+        assertTrue(linksBuilder.exists());
+        assertTrue(linksKey.exists());
+        assertTrue(testData.exists());
+        assertFilesCount(parent, 6);
+
+        parent = new File(sourcesOutputDir, NS_TEST + FS + "links");
+        final File level = new File(parent, "Level.java");
+        final File linkGroup = new File(parent, "LinkGroup.java");
+        final File node = new File(parent, "Node.java");
+        final File nodeBuilder = new File(parent, "NodeBuilder.java");
+        final File nodeList = new File(parent, "NodeList.java");
+        final File nodeListBuilder = new File(parent, "NodeListBuilder.java");
+        final File nodesType = new File(parent, "NodesType.java");
+        assertTrue(level.exists());
+        assertTrue(linkGroup.exists());
+        assertTrue(node.exists());
+        assertTrue(nodeBuilder.exists());
+        assertTrue(nodeList.exists());
+        assertTrue(nodeListBuilder.exists());
+        assertTrue(nodesType.exists());
+        assertFilesCount(parent, 7);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        final ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        final Class<?> keyArgsClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.KeyArgs", true, loader);
+        final Class<?> linksClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.Links", true, loader);
+        final Class<?> linksKeyClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.LinksKey", true, loader);
+
+        // Test generated 'grouping key-args'
+        assertTrue(keyArgsClass.isInterface());
+        assertContainsMethod(keyArgsClass, String.class, "getName");
+        assertContainsMethod(keyArgsClass, Integer.class, "getSize");
+        assertEquals(2, abstractMethods(keyArgsClass).size());
+
+        // Test generated 'list links'
+        assertTrue(linksClass.isInterface());
+        assertImplementsIfc(linksClass, keyArgsClass);
+        // TODO: anyxml
+        assertEquals(6, abstractMethods(linksClass).size());
+
+        // Test list key constructor arguments ordering
+        assertContainsConstructor(linksKeyClass, Byte.class, String.class, Integer.class);
+        // Test serialVersionUID generation
+        final Field suid = assertContainsField(linksKeyClass, "serialVersionUID", Long.TYPE);
+        suid.setAccessible(true);
+        assertEquals(-8829501012356283881L, suid.getLong(null));
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void testAugmentUnderUsesGeneration() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "augment-under-uses");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "augment-under-uses");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/augment-under-uses", sourcesOutputDir);
+
+        // Test if all sources were generated from 'module foo'
+        File parent = new File(sourcesOutputDir, NS_FOO);
+        assertTrue(new File(parent, "Object.java").exists());
+        assertTrue(new File(parent, "ClosedObject.java").exists());
+        assertTrue(new File(parent, "OpenObject.java").exists());
+        assertTrue(new File(parent, "ExplicitRouteObject.java").exists());
+        assertTrue(new File(parent, "PathKeySubobject.java").exists());
+        assertFilesCount(parent, 9);
+
+        parent = new File(parent, "object");
+        assertTrue(new File(parent, "Nodes.java").exists());
+        assertTrue(new File(parent, "NodesBuilder.java").exists());
+        assertFilesCount(parent, 2);
+
+        parent = new File(sourcesOutputDir, NS_FOO + FS + "closed");
+        assertFilesCount(parent, 1);
+
+        parent = new File(parent, "object");
+        assertTrue(new File(parent, "Link1.java").exists());
+        assertTrue(new File(parent, "Link1Builder.java").exists());
+        assertFilesCount(parent, 2);
+
+        parent = new File(sourcesOutputDir, NS_FOO + FS + "open");
+        assertFilesCount(parent, 1);
+
+        parent = new File(parent, "object");
+        assertTrue(new File(parent, "Nodes1.java").exists());
+        assertTrue(new File(parent, "Nodes1Builder.java").exists());
+        assertFilesCount(parent, 3);
+
+        parent = new File(parent, "nodes");
+        assertTrue(new File(parent, "Links.java").exists());
+        assertTrue(new File(parent, "LinksBuilder.java").exists());
+        assertFilesCount(parent, 2);
+
+        parent = new File(sourcesOutputDir, NS_FOO + FS + "explicit");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "route");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "object");
+        assertTrue(new File(parent, "Subobjects.java").exists());
+        assertTrue(new File(parent, "SubobjectsBuilder.java").exists());
+        assertFilesCount(parent, 3);
+
+        parent = new File(parent, "subobjects");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "subobject");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "type");
+        assertTrue(new File(parent, "PathKey.java").exists());
+        assertTrue(new File(parent, "PathKeyBuilder.java").exists());
+        assertFilesCount(parent, 3);
+
+        parent = new File(parent, "path");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "key");
+        assertTrue(new File(parent, "PathKey.java").exists());
+        assertTrue(new File(parent, "PathKeyBuilder.java").exists());
+        assertFilesCount(parent, 2);
+
+        // Test if all sources were generated from 'module bar'
+        parent = new File(sourcesOutputDir, NS_BAR);
+        assertTrue(new File(parent, "BasicExplicitRouteSubobjects.java").exists());
+        assertTrue(new File(parent, "ExplicitRouteSubobjects.java").exists());
+        assertTrue(new File(parent, "RouteSubobjects.java").exists());
+        assertFilesCount(parent, 5);
+
+        parent = new File(parent, "route");
+        assertFilesCount(parent, 1);
+        parent = new File(new File(sourcesOutputDir, NS_BAR), "basic");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "explicit");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "route");
+        assertFilesCount(parent, 1);
+
+        parent = new File(parent, "subobjects");
+        assertFilesCount(parent, 2);
+        assertTrue(new File(parent, "SubobjectType.java").exists());
+
+        parent = new File(parent, "subobject");
+        assertFilesCount(parent, 1);
+
+        parent = new File(parent, "type");
+        assertTrue(new File(parent, "IpPrefix.java").exists());
+        assertTrue(new File(parent, "IpPrefixBuilder.java").exists());
+        assertTrue(new File(parent, "Label.java").exists());
+        assertTrue(new File(parent, "LabelBuilder.java").exists());
+        assertFilesCount(parent, 4);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void testAugmentOfAugmentGeneration() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "aug-of-aug");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "aug-of-aug");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/augment-of-augment", sourcesOutputDir);
+
+        // Test if all sources were generated from 'module foo'
+        File parent = new File(sourcesOutputDir, NS_FOO);
+        final File fooListener = new File(parent, "FooListener.java");
+        File pathAttributes = new File(parent, "PathAttributes.java");
+        final File update = new File(parent, "Update.java");
+        final File updateBuilder = new File(parent, "UpdateBuilder.java");
+        assertTrue(fooListener.exists());
+        assertTrue(pathAttributes.exists());
+        assertTrue(update.exists());
+        assertTrue(updateBuilder.exists());
+        assertFilesCount(parent, 6);
+
+        parent = new File(sourcesOutputDir, NS_FOO + FS + "path");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "attributes");
+        assertFilesCount(parent, 2);
+        final File origin = new File(parent, "Origin.java");
+        final File originBuilder = new File(parent, "OriginBuilder.java");
+        assertTrue(origin.exists());
+        assertTrue(originBuilder.exists());
+
+        parent = new File(sourcesOutputDir, NS_FOO + FS + "update");
+        assertFilesCount(parent, 2);
+        pathAttributes = new File(parent, "PathAttributes.java");
+        final File pathAttributesBuilder = new File(parent, "PathAttributesBuilder.java");
+        assertTrue(pathAttributes.exists());
+        assertTrue(pathAttributesBuilder.exists());
+
+        // Test if all sources were generated from 'module bar'
+        parent = new File(sourcesOutputDir, NS_BAR);
+        final File destination = new File(parent, "Destination.java");
+        final File pathAttributes1 = new File(parent, "PathAttributes1.java");
+        final File pathAttributes1Builder = new File(parent, "PathAttributes1Builder.java");
+        assertTrue(destination.exists());
+        assertTrue(pathAttributes1.exists());
+        assertTrue(pathAttributes1Builder.exists());
+        assertFilesCount(parent, 5);
+
+        parent = new File(sourcesOutputDir, NS_BAR + FS + "destination");
+        assertFilesCount(parent, 2);
+        final File destinationType = new File(parent, "DestinationType.java");
+        assertTrue(destinationType.exists());
+
+        parent = new File(parent, "destination");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "type");
+        assertFilesCount(parent, 2);
+        final File destinationIpv4 = new File(parent, "DestinationIp.java");
+        final File destinationIpv4Builder = new File(parent, "DestinationIpBuilder.java");
+        assertTrue(destinationIpv4.exists());
+        assertTrue(destinationIpv4Builder.exists());
+
+        parent = new File(sourcesOutputDir, NS_BAR + FS + "update");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "path");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "attributes");
+        final File mpUnreachNlri = new File(parent, "MpUnreachNlri.java");
+        final File mpUnreachNlriBuilder = new File(parent, "MpUnreachNlriBuilder.java");
+        assertTrue(mpUnreachNlri.exists());
+        assertTrue(mpUnreachNlriBuilder.exists());
+        assertFilesCount(parent, 3);
+
+        parent = new File(parent, "mp");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "unreach");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "nlri");
+        final File withdrawnRoutes = new File(parent, "WithdrawnRoutes.java");
+        final File withdrawnRoutesBuilder = new File(parent, "WithdrawnRoutesBuilder.java");
+        assertTrue(withdrawnRoutes.exists());
+        assertTrue(withdrawnRoutesBuilder.exists());
+        assertFilesCount(parent, 2);
+
+        // Test if all sources were generated from 'module baz'
+        parent = new File(sourcesOutputDir, NS_BAZ);
+        assertFilesCount(parent, 2);
+        final File linkstateDestination = new File(parent, "LinkstateDestination.java");
+        assertTrue(linkstateDestination.exists());
+
+        parent = new File(sourcesOutputDir, NS_BAZ + FS + "update");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "path");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "attributes");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "mp");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "unreach");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "nlri");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "withdrawn");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "routes");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "destination");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "type");
+        final File destinationLinkstate = new File(parent, "DestinationLinkstate.java");
+        final File destinationLinkstateBuilder = new File(parent, "DestinationLinkstateBuilder.java");
+        assertTrue(destinationLinkstate.exists());
+        assertTrue(destinationLinkstateBuilder.exists());
+        assertFilesCount(parent, 3);
+        parent = new File(parent, "destination");
+        assertFilesCount(parent, 1);
+        parent = new File(parent, "linkstate");
+        final File links = new File(parent, "Links.java");
+        final File linksBuilder = new File(parent, "LinksBuilder.java");
+        assertTrue(links.exists());
+        assertTrue(linksBuilder.exists());
+        assertFilesCount(parent, 3);
+        parent = new File(parent, "links");
+        final File source = new File(parent, "Source.java");
+        final File sourceBuilder = new File(parent, "SourceBuilder.java");
+        assertTrue(source.exists());
+        assertTrue(sourceBuilder.exists());
+        assertFilesCount(parent, 3);
+        parent = new File(parent, "source");
+        final File address = new File(parent, "Address.java");
+        final File addressBuilder = new File(parent, "AddressBuilder.java");
+        assertTrue(address.exists());
+        assertTrue(addressBuilder.exists());
+        assertFilesCount(parent, 2);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void testLeafReturnTypes() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "leaf-return-types");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "leaf-return-types");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/leaf-return-types", sourcesOutputDir);
+
+        final File parent = new File(sourcesOutputDir, NS_TEST);
+        assertTrue(new File(parent, "TestData.java").exists());
+        assertTrue(new File(parent, "Nodes.java").exists());
+        assertTrue(new File(parent, "NodesBuilder.java").exists());
+        assertTrue(new File(parent, "Alg.java").exists());
+        assertTrue(new File(parent, "NodesIdUnionBuilder.java").exists());
+        assertFilesCount(parent, 5);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        final String pkg = BASE_PKG + ".urn.opendaylight.test.rev131008";
+        final ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        final Class<?> nodesClass = Class.forName(pkg + ".Nodes", true, loader);
+        final Class<?> builderClass = Class.forName(pkg + ".NodesBuilder", true, loader);
+
+        // Test methods return type
+        final byte[] b = new byte[] {};
+        assertContainsMethod(nodesClass, b.getClass(), "getIdBinary");
+        assertContainsMethod(nodesClass, pkg + ".Nodes$IdBits", "getIdBits", loader);
+        assertContainsMethod(nodesClass, Boolean.class, "isIdBoolean");
+        assertContainsMethod(nodesClass, BigDecimal.class, "getIdDecimal64");
+        assertContainsMethod(nodesClass, Boolean.class, "isIdEmpty");
+        assertContainsMethod(nodesClass, pkg + ".Nodes$IdEnumeration", "getIdEnumeration", loader);
+        testReturnTypeIdentityref(nodesClass, "getIdIdentityref", pkg + ".Alg");
+        testReturnTypeInstanceIdentitifer(loader, nodesClass, "getIdInstanceIdentifier");
+        assertContainsMethod(nodesClass, Byte.class, "getId8");
+        assertContainsMethod(nodesClass, Short.class, "getId16");
+        assertContainsMethod(nodesClass, Integer.class, "getId32");
+        assertContainsMethod(nodesClass, Long.class, "getId64");
+        assertContainsMethod(nodesClass, Long.class, "getIdLeafref");
+        assertContainsMethod(nodesClass, String.class, "getIdString");
+        assertContainsMethod(nodesClass, Short.class, "getIdU8");
+        assertContainsMethod(nodesClass, Integer.class, "getIdU16");
+        assertContainsMethod(nodesClass, Long.class, "getIdU32");
+        assertContainsMethod(nodesClass, BigInteger.class, "getIdU64");
+        assertContainsMethod(nodesClass, pkg + ".Nodes$IdUnion", "getIdUnion", loader);
+
+        final Object builderObj = builderClass.newInstance();
+
+        Method m = assertContainsMethod(builderClass, builderClass, "setIdBinary", b.getClass());
+        final List<Range<Integer>> lengthConstraints = new ArrayList<>();
+        lengthConstraints.add(Range.closed(1, 10));
+        byte[] arg = new byte[] {};
+        String expectedMsg = String.format("Invalid length: %s, expected: %s.", Arrays.toString(arg), lengthConstraints);
+        assertContainsRestrictionCheck(builderObj, m, expectedMsg, arg);
+
+        m = assertContainsMethod(builderClass, builderClass, "setIdDecimal64", BigDecimal.class);
+        final List<Range<BigDecimal>> rangeConstraints = new ArrayList<>();
+        rangeConstraints.add(Range.closed(new BigDecimal("1.5"), new BigDecimal("5.5")));
+        Object arg1 = new BigDecimal("1.4");
+        expectedMsg = String.format("Invalid range: %s, expected: %s.", arg1, rangeConstraints);
+        assertContainsRestrictionCheck(builderObj, m, expectedMsg, arg1);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void testGenerationContextReferenceExtension() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "context-reference");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "context-reference");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/context-reference", sourcesOutputDir);
+
+        // Test if all sources are generated
+        final File fooParent = new File(sourcesOutputDir, NS_FOO);
+        assertFilesCount(fooParent, 3);
+        assertTrue(new File(fooParent, "FooData.java").exists());
+        assertTrue(new File(fooParent, "Nodes.java").exists());
+        assertTrue(new File(fooParent, "NodesBuilder.java").exists());
+
+        final File barParent = new File(sourcesOutputDir, NS_BAR);
+        assertFilesCount(barParent, 1);
+        assertTrue(new File(barParent, "IdentityClass.java").exists());
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        final ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        final Class<?> nodesClass = Class.forName(BASE_PKG + ".urn.opendaylight.foo.rev131008.Nodes", true, loader);
+        final Class<?> identityClass = Class
+                .forName(BASE_PKG + ".urn.opendaylight.bar.rev131008.IdentityClass", true, loader);
+
+        // test identity
+        try {
+            identityClass.getConstructor();
+            final Class<?> baseIdentity = Class.forName("org.opendaylight.yangtools.yang.binding.BaseIdentity", true, loader);
+            assertEquals(baseIdentity, identityClass.getSuperclass());
+        } catch (final NoSuchMethodException e) {
+            throw new AssertionError("IdentityClass must have no-arg constructor");
+        }
+
+        // Test annotation
+        try {
+            final Method getId = nodesClass.getMethod("getId");
+            final Annotation[] annotations = getId.getAnnotations();
+            assertEquals(1, annotations.length);
+            final Annotation routingContext = annotations[0];
+            assertEquals(RoutingContext.class, routingContext.annotationType());
+        } catch (final NoSuchMethodException e) {
+            throw new AssertionError("Method getId() not found");
+        }
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void compilationTest() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "yang");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "yang");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/yang", sourcesOutputDir);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void testBug586() 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);
+    }
+
+    /**
+     * Test handling nested uses-augmentations.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testBug1172() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug1172");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug1172");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/bug1172", sourcesOutputDir);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    /**
+     * Test if class generated for node from grouping implements ChildOf.
+     *
+     * @throws Exception
+     */
+    @Test
+    public void testBug1377() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "bug1377");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "bug1377");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/bug1377", sourcesOutputDir);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        final ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        final Class<?> outputActionClass = Class.forName(BASE_PKG
+                + ".urn.test.foo.rev140717.action.action.output.action._case.OutputAction", true, loader);
+        final Class<?> actionClass = Class.forName(BASE_PKG + ".urn.test.foo.rev140717.Action", true, loader);
+
+        // Test generated 'container output-action'
+        assertTrue(outputActionClass.isInterface());
+        assertImplementsParameterizedIfc(outputActionClass, ChildOf.class.toString(), actionClass.getCanonicalName());
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    @Test
+    public void classNamesColisionTest() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "class-name-collision");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "class-name-collision");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/class-name-collision", sourcesOutputDir);
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    private void generateTestSources(final String resourceDirPath, final File sourcesOutputDir) throws Exception {
+        final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        Collections.sort(types, new Comparator<Type>() {
+            @Override
+            public int compare(final Type o1, final Type o2) {
+                return o2.getName().compareTo(o1.getName());
+            }
+        });
+        final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
+        generator.generateToFile(sourcesOutputDir);
+    }
+
+    private static void testReturnTypeIdentityref(final Class<?> clazz, final String methodName, final String returnTypeStr) throws Exception {
+        Method method;
+        java.lang.reflect.Type returnType;
+        try {
+            method = clazz.getMethod(methodName);
+            assertEquals(java.lang.Class.class, method.getReturnType());
+            returnType = method.getGenericReturnType();
+            assertTrue(returnType instanceof ParameterizedType);
+            final ParameterizedType pt = (ParameterizedType) returnType;
+            final java.lang.reflect.Type[] parameters = pt.getActualTypeArguments();
+            assertEquals(1, parameters.length);
+            final java.lang.reflect.Type parameter = parameters[0];
+            assertTrue(parameter instanceof WildcardType);
+            final WildcardType wildcardType = (WildcardType) parameter;
+            assertEquals("? extends " + returnTypeStr, wildcardType.toString());
+        } catch (final NoSuchMethodException e) {
+            throw new AssertionError("Method '" + methodName + "' not found");
+        }
+    }
+
+    private static void testReturnTypeInstanceIdentitifer(final ClassLoader loader, final Class<?> clazz, final String methodName)
+            throws Exception {
+        Method method;
+        Class<?> rawReturnType;
+        java.lang.reflect.Type returnType;
+        try {
+            method = clazz.getMethod(methodName);
+            rawReturnType = Class.forName("org.opendaylight.yangtools.yang.binding.InstanceIdentifier", true, loader);
+            assertEquals(rawReturnType, method.getReturnType());
+            returnType = method.getGenericReturnType();
+            assertTrue(returnType instanceof ParameterizedType);
+            final ParameterizedType pt = (ParameterizedType) returnType;
+            final java.lang.reflect.Type[] parameters = pt.getActualTypeArguments();
+            assertEquals(1, parameters.length);
+            final java.lang.reflect.Type parameter = parameters[0];
+            assertTrue(parameter instanceof WildcardType);
+            final WildcardType wildcardType = (WildcardType) parameter;
+            assertEquals("?", wildcardType.toString());
+        } catch (final NoSuchMethodException e) {
+            throw new AssertionError("Method '" + methodName + "' not found");
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTestUtils.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTestUtils.java
new file mode 100644 (file)
index 0000000..118fa94
--- /dev/null
@@ -0,0 +1,428 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+
+public class CompilationTestUtils {
+    public static final String FS = File.separator;
+    static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
+
+    static final String TEST_PATH = "target" + FS + "test";
+    static final File TEST_DIR = new File(TEST_PATH);
+
+    static final String GENERATOR_OUTPUT_PATH = TEST_PATH + FS + "src";
+    static final File GENERATOR_OUTPUT_DIR = new File(GENERATOR_OUTPUT_PATH);
+    static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
+    static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
+
+    static final String AUGMENTATION = "interface org.opendaylight.yangtools.yang.binding.Augmentation";
+
+    static final String BASE_PATH = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1";
+    static final String NS_TEST = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "test" + FS + "rev131008";
+    static final String NS_FOO = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "foo" + FS + "rev131008";
+    static final String NS_BAR = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "bar" + FS + "rev131008";
+    static final String NS_BAZ = BASE_PATH + FS + "urn" + FS + "opendaylight" + FS + "baz" + FS + "rev131008";
+
+    /**
+     * Method to clean resources. It is manually called at the end of each test
+     * instead of marking it with @After annotation to prevent removing
+     * generated code if test fails.
+     */
+    static void cleanUp(final File... resourceDirs) {
+        for (File resourceDir : resourceDirs) {
+            if (resourceDir.exists()) {
+                deleteTestDir(resourceDir);
+            }
+        }
+    }
+
+    /**
+     * Asserts that class contains field with fiven name and type.
+     *
+     * @param clazz
+     *            class to test
+     * @param name
+     *            field name
+     * @param type
+     *            field type
+     * @return field with given name if present in class
+     */
+    static Field assertContainsField(final Class<?> clazz, final String name, final Class<?> type) {
+        try {
+            Field f = clazz.getDeclaredField(name);
+            assertEquals(type, f.getType());
+            return f;
+        } catch (NoSuchFieldException e) {
+            throw new AssertionError("Field " + name + " does not exist in class " + clazz.getSimpleName());
+        }
+    }
+
+    /**
+     * Asserts that class contains field with given name and value. Method tries
+     * to create new instance of class and get value of field. If class
+     * constructor contains any arguments, class is instantiated with null
+     * values.
+     *
+     * @param clazz
+     *            class to test
+     * @param name
+     *            name of field
+     * @param returnType
+     *            return type of field
+     * @param expectedValue
+     *            expected value of field
+     * @param constructorArgs
+     *            constructor arguments of class to test
+     */
+    static void assertContainsFieldWithValue(final Class<?> clazz, final String name, final Class<?> returnType, final Object expectedValue,
+            final Class<?>... constructorArgs) {
+        Object[] initargs = null;
+        if (constructorArgs != null && constructorArgs.length > 0) {
+            initargs = new Object[constructorArgs.length];
+            for (int i = 0; i < constructorArgs.length; i++) {
+                initargs[i] = null;
+            }
+        }
+        assertContainsFieldWithValue(clazz, name, returnType, expectedValue, constructorArgs, initargs);
+    }
+
+    /**
+     * Asserts that class contains field with given name, return type and value.
+     *
+     * @param clazz
+     *            class to test
+     * @param name
+     *            name of field
+     * @param returnType
+     *            return type of field
+     * @param expectedValue
+     *            expected value of field
+     * @param constructorArgs
+     *            array of constructor arguments classes
+     * @param initargs
+     *            array of constructor values
+     */
+    static void assertContainsFieldWithValue(final Class<?> clazz, final String name, final Class<?> returnType, final Object expectedValue,
+            final Class<?>[] constructorArgs, final Object... initargs) {
+        Field f = assertContainsField(clazz, name, returnType);
+        f.setAccessible(true);
+
+        final Object obj;
+        if ((f.getModifiers() & Modifier.STATIC) == 0) {
+            try {
+                Constructor<?> c = clazz.getDeclaredConstructor(constructorArgs);
+                obj = c.newInstance(initargs);
+            } catch (Exception e) {
+                throw new AssertionError("Failed to instantiate object for " + clazz, e);
+            }
+        } else {
+            obj = null;
+        }
+
+        try {
+            assertEquals(expectedValue, f.get(obj));
+        } catch (IllegalArgumentException | IllegalAccessException e) {
+            throw new AssertionError("Failed to get field " + name + " of class " + clazz, e);
+        }
+    }
+
+    /**
+     * Asserts that class contains constructor with parameter types.
+     *
+     * @param clazz
+     *            class to test
+     * @param args
+     *            array of argument classes
+     */
+    static Constructor<?> assertContainsConstructor(final Class<?> clazz, final Class<?>... args) {
+        try {
+            return clazz.getDeclaredConstructor(args);
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError("Constructor with args " + Arrays.toString(args) + " does not exists in class "
+                    + clazz.getSimpleName());
+        }
+    }
+
+    /**
+     * Asserts that class contains method with given name, return type and
+     * parameter types.
+     *
+     * @param clazz
+     *            class to test
+     * @param returnType
+     *            method return type
+     * @param name
+     *            method name
+     * @param args
+     *            array of parameter type classes
+     * @return method with given name, return type and parameter types
+     */
+    static Method assertContainsMethod(final Class<?> clazz, final Class<?> returnType, final String name, final Class<?>... args) {
+        try {
+            Method m = clazz.getDeclaredMethod(name, args);
+            assertEquals(returnType, m.getReturnType());
+            return m;
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError("Method " + name + " with args " + Arrays.toString(args)
+                    + " does not exists in class " + clazz.getSimpleName());
+        }
+    }
+
+    /**
+     * Asserts that class contains method with given name and return type.
+     *
+     * @param clazz
+     *            class to test
+     * @param returnTypeStr
+     *            name of method return type
+     * @param name
+     *            method name
+     * @param loader
+     *            current class loader
+     */
+    static void assertContainsMethod(final Class<?> clazz, final String returnTypeStr, final String name, final ClassLoader loader) {
+        Class<?> returnType;
+        try {
+            returnType = Class.forName(returnTypeStr, true, loader);
+            Method method = clazz.getMethod(name);
+            assertEquals(returnType, method.getReturnType());
+        } catch (ClassNotFoundException e) {
+            throw new AssertionError("Return type of method '" + name + "' not found");
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError("Method " + name + " does not exists in class " + clazz.getSimpleName());
+        }
+    }
+
+    /**
+     * Asserts that class contains hashCode, equals and toString methods.
+     *
+     * @param clazz
+     *            class to test
+     */
+    static void assertContainsDefaultMethods(final Class<?> clazz) {
+        assertContainsMethod(clazz, Integer.TYPE, "hashCode");
+        assertContainsMethod(clazz, Boolean.TYPE, "equals", Object.class);
+        assertContainsMethod(clazz, String.class, "toString");
+    }
+
+    /**
+     * Asserts that constructor contains check for illegal argument.
+     *
+     * @param constructor
+     *            constructor to invoke
+     * @param errorMsg
+     *            expected error message
+     * @param args
+     *            constructor arguments
+     * @throws Exception
+     */
+    static void assertContainsRestrictionCheck(final Constructor<?> constructor, final String errorMsg, final Object... args)
+            throws Exception {
+        try {
+            constructor.newInstance(args);
+            fail("constructor invocation should fail");
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            assertTrue(cause instanceof IllegalArgumentException);
+            assertEquals(errorMsg, cause.getMessage());
+        }
+    }
+
+    /**
+     * Asserts that method contains check for illegal argument.
+     *
+     * @param obj
+     *            object to test (can be null, if method is static)
+     * @param method
+     *            method to invoke
+     * @param errorMsg
+     *            expected error message
+     * @param args
+     *            constructor arguments
+     * @throws Exception
+     */
+    static void assertContainsRestrictionCheck(final Object obj, final Method method, final String errorMsg, final Object... args)
+            throws Exception {
+        try {
+            method.invoke(obj, args);
+            fail("method invocation should fail");
+        } catch (InvocationTargetException e) {
+            Throwable cause = e.getCause();
+            assertTrue(cause instanceof IllegalArgumentException);
+            assertEquals(errorMsg, cause.getMessage());
+        }
+    }
+
+    /**
+     * Asserts that class implements given interface.
+     *
+     * @param clazz
+     *            source to test
+     * @param ifc
+     *            expected interface
+     */
+    static void assertImplementsIfc(final Class<?> clazz, final Class<?> ifc) {
+        Class<?>[] interfaces = clazz.getInterfaces();
+        List<Class<?>> ifcsList = Arrays.asList(interfaces);
+        if (!ifcsList.contains(ifc)) {
+            throw new AssertionError(clazz + " should implement " + ifc);
+        }
+    }
+
+    /**
+     * Test if interface generated from augment extends Augmentation interface
+     * with correct generic type.
+     *
+     * @param clazz
+     *            interface generated from augment
+     * @param genericTypeName
+     *            fully qualified name of expected parameter type
+     */
+    static void testAugmentation(final Class<?> clazz, final String genericTypeName) {
+        assertImplementsParameterizedIfc(clazz, AUGMENTATION, genericTypeName);
+    }
+
+    /**
+     * Asserts that class implements interface with given name and generic type
+     * parameter.
+     *
+     * @param clazz
+     *            class to test
+     * @param ifcName
+     *            name of interface
+     * @param genericTypeName
+     *            name of generic type
+     */
+    static void assertImplementsParameterizedIfc(final Class<?> clazz, final String ifcName, final String genericTypeName) {
+        ParameterizedType ifcType = null;
+        for (java.lang.reflect.Type ifc : clazz.getGenericInterfaces()) {
+            if (ifc instanceof ParameterizedType) {
+                ParameterizedType pt = (ParameterizedType) ifc;
+                if (ifcName.equals(pt.getRawType().toString())) {
+                    ifcType = pt;
+                }
+            }
+        }
+        assertNotNull(ifcType);
+
+        java.lang.reflect.Type[] typeArguments = ifcType.getActualTypeArguments();
+        assertEquals(1, typeArguments.length);
+        assertEquals("interface " + genericTypeName, typeArguments[0].toString());
+    }
+
+    /**
+     * Test if source code is compilable.
+     *
+     * @param sourcesOutputDir
+     *            directory containing source files
+     * @param compiledOutputDir
+     *            compiler output directory
+     */
+    static void testCompilation(final File sourcesOutputDir, final File compiledOutputDir) {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
+        List<File> filesList = getJavaFiles(sourcesOutputDir);
+        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
+        Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
+        boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
+        assertTrue("Compilation failed", compiled);
+    }
+
+    /**
+     * Asserts that directory contains exactly given count of files.
+     *
+     * @param dir
+     *            directory to test
+     * @param count
+     *            expected count of files in directory
+     */
+    static void assertFilesCount(final File dir, final int count) {
+        File[] dirContent = dir.listFiles();
+        if (dirContent == null) {
+            throw new AssertionError("File " + dir + " doesn't exists or it's not a directory");
+        } else {
+            assertEquals("Unexpected count of generated files", count, dirContent.length);
+        }
+    }
+
+    /**
+     * Search recursively given directory for *.java files.
+     *
+     * @param directory
+     *            directory to search
+     * @return List of java files found
+     */
+    private static List<File> getJavaFiles(final File directory) {
+        List<File> result = new ArrayList<>();
+        File[] filesToRead = directory.listFiles();
+        if (filesToRead != null) {
+            for (File file : filesToRead) {
+                if (file.isDirectory()) {
+                    result.addAll(getJavaFiles(file));
+                } else {
+                    String absPath = file.getAbsolutePath();
+                    if (absPath.endsWith(".java")) {
+                        result.add(file);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    static List<File> getSourceFiles(final String path) throws Exception {
+        final URI resPath = BaseCompilationTest.class.getResource(path).toURI();
+        final File sourcesDir = new File(resPath);
+        if (sourcesDir.exists()) {
+            final List<File> sourceFiles = new ArrayList<>();
+            final File[] fileArray = sourcesDir.listFiles();
+            if (fileArray == null) {
+                throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
+            }
+            sourceFiles.addAll(Arrays.asList(fileArray));
+            return sourceFiles;
+        } else {
+            throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
+        }
+    }
+
+    static void deleteTestDir(final File file) {
+        if (file.isDirectory()) {
+            File[] filesToDelete = file.listFiles();
+            if (filesToDelete != null) {
+                for (File f : filesToDelete) {
+                    deleteTestDir(f);
+                }
+            }
+        }
+        if (!file.delete()) {
+            throw new RuntimeException("Failed to clean up after test");
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/EndodingInJavaDocTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/EndodingInJavaDocTest.java
new file mode 100644 (file)
index 0000000..330b28e
--- /dev/null
@@ -0,0 +1,42 @@
+package org.opendaylight.yangtools.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.collect.ImmutableSet;
+import java.io.File;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Test if generated classes from yang file is compilable, generated javadoc comments contains
+ * symbols as javadoc comment tag, which caused of compilation problem.
+ */
+public class EndodingInJavaDocTest extends BaseCompilationTest {
+
+    @Test
+    public void testAugmentToUsesInAugment() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "encoding-javadoc");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "encoding-javadoc");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/encoding-javadoc");
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
+        generator.generateToFile(sourcesOutputDir);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/GeneratorJavaFileTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/GeneratorJavaFileTest.java
new file mode 100644 (file)
index 0000000..8105ea1
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.BindingTypes;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+
+public class GeneratorJavaFileTest {
+    private static final String FS = File.separator;
+    private static final String PATH = "target/test/test-dir";
+
+    @Test
+    public void test() throws IOException {
+        final Set<GeneratedType> types = new HashSet<GeneratedType>();
+        GeneratedType t1 = createGeneratedType("org.opendaylight.controller.gen", "Type1");
+        GeneratedType t2 = createGeneratedType("org.opendaylight.controller.gen", "Type2");
+        GeneratedType t3 = createGeneratedType("org.opendaylight.controller.gen", "Type3");
+        types.add(t1);
+        types.add(t2);
+        types.add(t3);
+        GeneratedTypeBuilder gtb = new GeneratedTypeBuilderImpl("org.opendaylight.controller.gen", "Type4");
+        gtb.addImplementsType(Types.augmentableTypeFor(gtb));
+        types.add(gtb.toInstance());
+        GeneratorJavaFile generator = new GeneratorJavaFile(types);
+        generator.generateToFile(new File(PATH));
+
+        String[] files = new File(PATH + FS + "org" + FS + "opendaylight" + FS + "controller" + FS + "gen").list();
+        List<String> filesList = Arrays.asList(files);
+
+        // assertEquals(5, files.length);
+        assertTrue(filesList.contains("Type1.java"));
+        assertTrue(filesList.contains("Type2.java"));
+        assertTrue(filesList.contains("Type3.java"));
+        assertTrue(filesList.contains("Type4.java"));
+        assertTrue(filesList.contains("Type4Builder.java"));
+    }
+
+    private static GeneratedType createGeneratedType(final String pkgName, final String name) {
+        GeneratedTypeBuilder builder = new GeneratedTypeBuilderImpl(pkgName, name);
+        builder.addImplementsType(BindingTypes.DATA_OBJECT);
+        return builder.toInstance();
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/NestedGroupingCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/NestedGroupingCompilationTest.java
new file mode 100644 (file)
index 0000000..d2fb5a8
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_TEST;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertFilesCount;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertImplementsIfc;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.collect.ImmutableSet;
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Test correct code generation.
+ *
+ */
+public class NestedGroupingCompilationTest extends BaseCompilationTest {
+
+    @Test
+    public void testListGeneration() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "nested-grouping");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "nested-grouping");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        generateTestSources("/compilation/nested-grouping", sourcesOutputDir);
+
+        // Test if all sources are generated
+        File parent = new File(sourcesOutputDir, NS_TEST);
+        File foo = new File(parent, "Foo.java");
+        File fooBuilder = new File(parent, "FooBuilder.java");
+        File testData = new File(parent, "TestData.java");
+        File fooDir = new File(parent, "foo");
+        assertTrue(foo.exists());
+        assertTrue(fooBuilder.exists());
+        assertTrue(testData.exists());
+        assertTrue(fooDir.exists());
+        assertFilesCount(parent, 4);
+
+        parent = new File(parent, "foo");
+        File bar = new File(parent, "Bar.java");
+        assertTrue(bar.exists());
+        assertFilesCount(parent, 1);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        Class<?> fooClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.Foo", true, loader);
+        Class<?> barClass = Class.forName(BASE_PKG + ".urn.opendaylight.test.rev131008.foo.Bar", true, loader);
+
+        // Test generated 'foo'
+        assertTrue(fooClass.isInterface());
+        assertImplementsIfc(fooClass, barClass);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    private void generateTestSources(final String resourceDirPath, final File sourcesOutputDir) throws Exception {
+        final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
+        generator.generateToFile(sourcesOutputDir);
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/TypedefCompilationTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/TypedefCompilationTest.java
new file mode 100644 (file)
index 0000000..57e94f4
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.BASE_PKG;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.NS_FOO;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsConstructor;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsDefaultMethods;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsField;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsFieldWithValue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsMethod;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertContainsRestrictionCheck;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.assertFilesCount;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Range;
+import java.io.File;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Test correct code generation.
+ *
+ */
+public class TypedefCompilationTest extends BaseCompilationTest {
+    private static final String VAL = "_value";
+    private static final String GET_VAL = "getValue";
+    private static final String UNITS = "_UNITS";
+
+    @Test
+    public void test() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "typedef");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "typedef");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/typedef");
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(ImmutableSet.copyOf(types));
+        generator.generateToFile(sourcesOutputDir);
+
+        File parent = new File(sourcesOutputDir, NS_FOO);
+        File bitsExt = new File(parent, "BitsExt.java");
+        File int32Ext0 = new File(parent, "Int32Ext0.java");
+        File int32Ext1 = new File(parent, "Int32Ext1.java");
+        File int32Ext2 = new File(parent, "Int32Ext2.java");
+        File myDecimalType = new File(parent, "MyDecimalType.java");
+        File stringExt1 = new File(parent, "StringExt1.java");
+        File stringExt2 = new File(parent, "StringExt2.java");
+        File stringExt3 = new File(parent, "StringExt3.java");
+        File unionExt1 = new File(parent, "UnionExt1.java");
+        File unionExt2 = new File(parent, "UnionExt2.java");
+        File unionExt3 = new File(parent, "UnionExt3.java");
+        File unionExt4 = new File(parent, "UnionExt4.java");
+        assertTrue(bitsExt.exists());
+        assertTrue(int32Ext0.exists());
+        assertTrue(int32Ext1.exists());
+        assertTrue(int32Ext2.exists());
+        assertTrue(myDecimalType.exists());
+        assertTrue(stringExt1.exists());
+        assertTrue(stringExt2.exists());
+        assertTrue(stringExt3.exists());
+        assertTrue(unionExt1.exists());
+        assertTrue(unionExt2.exists());
+        assertTrue(unionExt3.exists());
+        assertTrue(unionExt4.exists());
+        assertFilesCount(parent, 33);
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        String pkg = BASE_PKG + ".urn.opendaylight.foo.rev131008";
+        ClassLoader loader = new URLClassLoader(new URL[] { compiledOutputDir.toURI().toURL() });
+        Class<?> bitsExtClass = Class.forName(pkg + ".BitsExt", true, loader);
+        Class<?> int32Ext1Class = Class.forName(pkg + ".Int32Ext1", true, loader);
+        Class<?> int32Ext2Class = Class.forName(pkg + ".Int32Ext2", true, loader);
+        Class<?> myDecimalTypeClass = Class.forName(pkg + ".MyDecimalType", true, loader);
+        Class<?> myDecimalType2Class = Class.forName(pkg + ".MyDecimalType2", true, loader);
+        Class<?> stringExt1Class = Class.forName(pkg + ".StringExt1", true, loader);
+        Class<?> stringExt2Class = Class.forName(pkg + ".StringExt2", true, loader);
+        Class<?> stringExt3Class = Class.forName(pkg + ".StringExt3", true, loader);
+        Class<?> unionExt1Class = Class.forName(pkg + ".UnionExt1", true, loader);
+        Class<?> unionExt2Class = Class.forName(pkg + ".UnionExt2", true, loader);
+        Class<?> unionExt3Class = Class.forName(pkg + ".UnionExt3", true, loader);
+        Class<?> unionExt4Class = Class.forName(pkg + ".UnionExt4", true, loader);
+
+        // typedef bits-ext
+        assertFalse(bitsExtClass.isInterface());
+        assertContainsField(bitsExtClass, "_pc", Boolean.class);
+        assertContainsField(bitsExtClass, "_bpc", Boolean.class);
+        assertContainsField(bitsExtClass, "_dpc", Boolean.class);
+        assertContainsField(bitsExtClass, "_lbpc", Boolean.class);
+        assertContainsField(bitsExtClass, "_spc", Boolean.class);
+        assertContainsField(bitsExtClass, "_sfmof", Boolean.class);
+        assertContainsField(bitsExtClass, "_sfapc", Boolean.class);
+        assertContainsFieldWithValue(bitsExtClass, "serialVersionUID", Long.TYPE, -2922917845344851623L, Boolean.class,
+                Boolean.class, Boolean.class, Boolean.class, Boolean.class, Boolean.class, Boolean.class);
+
+        // assertEquals(8, bitsExtClass.getDeclaredFields());
+        Constructor<?> expectedConstructor = assertContainsConstructor(bitsExtClass, Boolean.class, Boolean.class,
+                Boolean.class, Boolean.class, Boolean.class, Boolean.class, Boolean.class);
+        assertContainsConstructor(bitsExtClass, bitsExtClass);
+        assertEquals(2, bitsExtClass.getConstructors().length);
+        Method defInst = assertContainsMethod(bitsExtClass, bitsExtClass, "getDefaultInstance", String.class);
+        assertContainsDefaultMethods(bitsExtClass);
+        // assertEquals(11, bitsExtClass.getDeclaredMethods().length);
+
+        Object obj = expectedConstructor.newInstance(null, null, null, null, null, new Boolean("true"), null);
+        assertEquals(obj, defInst.invoke(null, "sfmof"));
+
+        // typedef int32-ext1
+        assertFalse(int32Ext1Class.isInterface());
+        assertContainsField(int32Ext1Class, VAL, Integer.class);
+        assertContainsFieldWithValue(int32Ext1Class, "serialVersionUID", Long.TYPE, 5351634010010233292L, Integer.class);
+        // assertEquals(3, int32Ext1Class.getDeclaredFields().length);
+
+        expectedConstructor = assertContainsConstructor(int32Ext1Class, Integer.class);
+        assertContainsConstructor(int32Ext1Class, int32Ext1Class);
+        assertEquals(2, int32Ext1Class.getConstructors().length);
+        assertContainsDefaultMethods(int32Ext1Class);
+        assertContainsMethod(int32Ext1Class, Integer.class, GET_VAL);
+        defInst = assertContainsMethod(int32Ext1Class, int32Ext1Class, "getDefaultInstance", String.class);
+        // assertEquals(6, int32Ext1Class.getDeclaredMethods().length);
+
+        List<Range<Integer>> rangeConstraints = new ArrayList<>();
+        rangeConstraints.add(Range.closed(new Integer("2"), new Integer("2147483647")));
+        Object arg = new Integer("1");
+        String expectedMsg = String.format("Invalid range: %s, expected: %s.", arg, rangeConstraints);
+        assertContainsRestrictionCheck(expectedConstructor, expectedMsg, arg);
+        obj = expectedConstructor.newInstance(new Integer("159"));
+        assertEquals(obj, defInst.invoke(null, "159"));
+
+        // typedef int32-ext2
+        assertFalse(int32Ext2Class.isInterface());
+        assertContainsFieldWithValue(int32Ext2Class, UNITS, String.class, "mile", Integer.class);
+        assertContainsFieldWithValue(int32Ext2Class, "serialVersionUID", Long.TYPE, 317831889060130988L, Integer.class);
+        // assertEquals(3, int32Ext2Class.getDeclaredFields().length);
+        expectedConstructor = assertContainsConstructor(int32Ext2Class, Integer.class);
+        assertContainsConstructor(int32Ext2Class, int32Ext2Class);
+        assertContainsConstructor(int32Ext2Class, int32Ext1Class);
+        assertEquals(3, int32Ext2Class.getDeclaredConstructors().length);
+        assertContainsMethod(int32Ext2Class, String.class, "toString");
+        defInst = assertContainsMethod(int32Ext2Class, int32Ext2Class, "getDefaultInstance", String.class);
+        // assertEquals(3, int32Ext2Class.getDeclaredMethods().length);
+
+        rangeConstraints.clear();
+        rangeConstraints.add(Range.closed(new Integer("3"), new Integer("9")));
+        rangeConstraints.add(Range.closed(new Integer("11"), new Integer("2147483647")));
+        arg = new Integer("10");
+        expectedMsg = String.format("Invalid range: %s, expected: %s.", arg, rangeConstraints);
+        assertContainsRestrictionCheck(expectedConstructor, expectedMsg, arg);
+        obj = expectedConstructor.newInstance(new Integer("2147483647"));
+        assertEquals(obj, defInst.invoke(null, "2147483647"));
+
+        // typedef string-ext1
+        assertFalse(stringExt1Class.isInterface());
+        assertContainsField(stringExt1Class, VAL, String.class);
+        assertContainsField(stringExt1Class, "patterns", Pattern[].class);
+        assertContainsField(stringExt1Class, "PATTERN_CONSTANTS", List.class);
+        assertContainsFieldWithValue(stringExt1Class, "serialVersionUID", Long.TYPE, 6943827552297110991L, String.class);
+        // assertEquals(5, stringExt1Class.getDeclaredFields().length);
+        expectedConstructor = assertContainsConstructor(stringExt1Class, String.class);
+        assertContainsConstructor(stringExt1Class, stringExt1Class);
+        assertEquals(2, stringExt1Class.getDeclaredConstructors().length);
+        assertContainsMethod(stringExt1Class, String.class, GET_VAL);
+        defInst = assertContainsMethod(stringExt1Class, stringExt1Class, "getDefaultInstance", String.class);
+        assertContainsDefaultMethods(stringExt1Class);
+        // assertEquals(6, stringExt1Class.getDeclaredMethods().length);
+
+        List<Range<Integer>> lengthConstraints = new ArrayList<>();
+        lengthConstraints.add(Range.closed(5, 11));
+        arg = "abcd";
+        expectedMsg = String.format("Invalid length: %s, expected: %s.", arg, lengthConstraints);
+        assertContainsRestrictionCheck(expectedConstructor, expectedMsg, arg);
+
+        obj = expectedConstructor.newInstance("abcde");
+        assertEquals(obj, defInst.invoke(null, "abcde"));
+
+        // typedef string-ext2
+        assertFalse(stringExt2Class.isInterface());
+        assertContainsFieldWithValue(stringExt2Class, "serialVersionUID", Long.TYPE, 8100233177432072092L, String.class);
+        // assertEquals(2, stringExt2Class.getDeclaredFields().length);
+        expectedConstructor = assertContainsConstructor(stringExt2Class, String.class);
+        assertContainsConstructor(stringExt2Class, stringExt2Class);
+        assertContainsConstructor(stringExt2Class, stringExt1Class);
+        assertEquals(3, stringExt2Class.getDeclaredConstructors().length);
+        defInst = assertContainsMethod(stringExt2Class, stringExt2Class, "getDefaultInstance", String.class);
+        // assertEquals(2, stringExt2Class.getDeclaredMethods().length);
+
+        lengthConstraints.clear();
+        lengthConstraints.add(Range.closed(6, 10));
+        arg = "abcde";
+        expectedMsg = String.format("Invalid length: %s, expected: %s.", arg, lengthConstraints);
+        assertContainsRestrictionCheck(expectedConstructor, expectedMsg, arg);
+        obj = expectedConstructor.newInstance("abcdef");
+        assertEquals(obj, defInst.invoke(null, "abcdef"));
+
+        // typedef string-ext3
+        assertFalse(stringExt3Class.isInterface());
+        assertContainsFieldWithValue(stringExt3Class, "serialVersionUID", Long.TYPE, -2751063130555484180L,
+                String.class);
+        // assertEquals(1, stringExt3Class.getDeclaredFields().length);
+        expectedConstructor = assertContainsConstructor(stringExt3Class, String.class);
+        assertContainsConstructor(stringExt3Class, stringExt3Class);
+        assertContainsConstructor(stringExt3Class, stringExt2Class);
+        assertEquals(3, stringExt3Class.getDeclaredConstructors().length);
+        defInst = assertContainsMethod(stringExt3Class, stringExt3Class, "getDefaultInstance", String.class);
+        // assertEquals(1, stringExt3Class.getDeclaredMethods().length);
+
+        obj = expectedConstructor.newInstance("bbbbbb");
+        assertEquals(obj, defInst.invoke(null, "bbbbbb"));
+
+        // typedef my-decimal-type
+        assertFalse(myDecimalTypeClass.isInterface());
+        assertContainsField(myDecimalTypeClass, VAL, BigDecimal.class);
+        assertContainsFieldWithValue(myDecimalTypeClass, "serialVersionUID", Long.TYPE, 3143735729419861095L,
+                BigDecimal.class);
+        // assertEquals(3, myDecimalTypeClass.getDeclaredFields().length);
+        assertContainsMethod(myDecimalTypeClass, BigDecimal.class, "getValue");
+        expectedConstructor = assertContainsConstructor(myDecimalTypeClass, BigDecimal.class);
+        assertContainsConstructor(myDecimalTypeClass, myDecimalTypeClass);
+        assertEquals(2, myDecimalTypeClass.getDeclaredConstructors().length);
+        assertContainsMethod(myDecimalTypeClass, BigDecimal.class, GET_VAL);
+        assertContainsDefaultMethods(myDecimalTypeClass);
+        defInst = assertContainsMethod(myDecimalTypeClass, myDecimalTypeClass, "getDefaultInstance", String.class);
+        // assertEquals(6, myDecimalTypeClass.getDeclaredMethods().length);
+
+        List<Range<BigDecimal>> decimalRangeConstraints = new ArrayList<>();
+        decimalRangeConstraints.add(Range.closed(new BigDecimal("1.5"), new BigDecimal("5.5")));
+        arg = new BigDecimal("1.4");
+        expectedMsg = String.format("Invalid range: %s, expected: %s.", arg, decimalRangeConstraints);
+        assertContainsRestrictionCheck(expectedConstructor, expectedMsg, arg);
+        obj = expectedConstructor.newInstance(new BigDecimal("3.14"));
+        assertEquals(obj, defInst.invoke(null, "3.14"));
+
+        // typedef my-decimal-type2
+        assertFalse(myDecimalType2Class.isInterface());
+        assertContainsField(myDecimalType2Class, VAL, BigDecimal.class);
+        assertContainsFieldWithValue(myDecimalType2Class, "serialVersionUID", Long.TYPE, -672265764962082714L, BigDecimal.class);
+        // assertEquals(3, myDecimalType2Class.getDeclaredFields().length);
+        assertContainsMethod(myDecimalType2Class, BigDecimal.class, "getValue");
+        expectedConstructor = assertContainsConstructor(myDecimalType2Class, BigDecimal.class);
+        assertContainsConstructor(myDecimalType2Class, myDecimalType2Class);
+        assertEquals(2, myDecimalType2Class.getDeclaredConstructors().length);
+        assertContainsMethod(myDecimalType2Class, BigDecimal.class, GET_VAL);
+        assertContainsDefaultMethods(myDecimalType2Class);
+        defInst = assertContainsMethod(myDecimalType2Class, myDecimalType2Class, "getDefaultInstance", String.class);
+        // assertEquals(6, myDecimalType2Class.getDeclaredMethods().length);
+
+        List<Range<BigDecimal>> decimal2RangeConstraints = new ArrayList<>();
+        decimal2RangeConstraints.add(Range.closed(new BigDecimal("0"), new BigDecimal("1")));
+        arg = new BigDecimal("1.4");
+        expectedMsg = String.format("Invalid range: %s, expected: %s.", arg, decimal2RangeConstraints);
+        assertContainsRestrictionCheck(expectedConstructor, expectedMsg, arg);
+        obj = expectedConstructor.newInstance(new BigDecimal("0.14"));
+        assertEquals(obj, defInst.invoke(null, "0.14"));
+
+        // typedef union-ext1
+        assertFalse(unionExt1Class.isInterface());
+        assertContainsField(unionExt1Class, "_int16", Short.class);
+        assertContainsField(unionExt1Class, "_int32", Integer.class);
+        assertContainsFieldWithValue(unionExt1Class, "serialVersionUID", Long.TYPE, -5610530488718168882L,
+                new Class<?>[] { Short.class }, Short.valueOf("1"));
+        // assertEquals(4, unionExt1Class.getDeclaredFields().length);
+        assertContainsMethod(unionExt1Class, Short.class, "getInt16");
+        assertContainsMethod(unionExt1Class, Integer.class, "getInt32");
+        assertContainsConstructor(unionExt1Class, Short.class);
+        assertContainsConstructor(unionExt1Class, Integer.class);
+        assertContainsConstructor(unionExt1Class, unionExt1Class);
+        assertEquals(4, unionExt1Class.getDeclaredConstructors().length);
+        assertContainsDefaultMethods(unionExt1Class);
+
+        // typedef union-ext2
+        assertFalse(unionExt2Class.isInterface());
+        assertContainsFieldWithValue(unionExt2Class, "serialVersionUID", Long.TYPE, -8833407459073585206L,
+                new Class<?>[] { Short.class }, Short.valueOf("1"));
+        // assertEquals(1, unionExt2Class.getDeclaredFields().length);
+        // assertEquals(0, unionExt2Class.getDeclaredMethods().length);
+        assertContainsConstructor(unionExt2Class, Short.class);
+        assertContainsConstructor(unionExt2Class, Integer.class);
+        assertContainsConstructor(unionExt2Class, unionExt2Class);
+        assertContainsConstructor(unionExt2Class, unionExt1Class);
+        assertEquals(5, unionExt2Class.getDeclaredConstructors().length);
+
+        // typedef union-ext3
+        assertFalse(unionExt3Class.isInterface());
+        assertContainsField(unionExt3Class, "_string", String.class);
+        assertContainsField(unionExt3Class, "_unionExt2", unionExt2Class);
+        assertContainsFieldWithValue(unionExt3Class, UNITS, String.class, "object id", new Class<?>[] { String.class },
+                "");
+        assertContainsFieldWithValue(unionExt3Class, "serialVersionUID", Long.TYPE, 4347887914884631036L,
+                new Class<?>[] { String.class }, "");
+        // assertEquals(5, unionExt3Class.getDeclaredFields().length);
+        assertContainsMethod(unionExt3Class, String.class, "getString");
+        assertContainsMethod(unionExt3Class, unionExt2Class, "getUnionExt2");
+        assertContainsConstructor(unionExt3Class, String.class);
+        assertContainsConstructor(unionExt3Class, unionExt2Class);
+        assertContainsConstructor(unionExt3Class, unionExt3Class);
+        assertEquals(4, unionExt3Class.getDeclaredConstructors().length);
+        assertContainsDefaultMethods(unionExt3Class);
+
+        // typedef union-ext4
+        assertFalse(unionExt4Class.isInterface());
+        assertContainsField(unionExt4Class, "_unionExt3", unionExt3Class);
+        assertContainsField(unionExt4Class, "_int32Ext2", int32Ext2Class);
+        assertContainsField(unionExt4Class, "_empty", Boolean.class);
+        assertContainsField(unionExt4Class, "_myDecimalType", myDecimalTypeClass);
+        assertContainsFieldWithValue(unionExt4Class, "serialVersionUID", Long.TYPE, 4299836385615211130L,
+                new Class<?>[] { Boolean.class }, false);
+        // assertEquals(6, unionExt4Class.getDeclaredFields().length);
+        assertContainsMethod(unionExt4Class, unionExt3Class, "getUnionExt3");
+        assertContainsMethod(unionExt4Class, int32Ext2Class, "getInt32Ext2");
+        assertContainsMethod(unionExt4Class, Boolean.class, "isEmpty");
+        assertContainsMethod(unionExt4Class, myDecimalTypeClass, "getMyDecimalType");
+        assertContainsConstructor(unionExt4Class, unionExt3Class);
+        assertContainsConstructor(unionExt4Class, int32Ext2Class);
+        assertContainsConstructor(unionExt4Class, Boolean.class);
+        assertContainsConstructor(unionExt4Class, myDecimalTypeClass);
+        assertContainsConstructor(unionExt4Class, unionExt4Class);
+        assertEquals(6, unionExt4Class.getDeclaredConstructors().length);
+        assertContainsDefaultMethods(unionExt4Class);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/UnionTypedefUnusedImportTest.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/UnionTypedefUnusedImportTest.java
new file mode 100644 (file)
index 0000000..ffe2c80
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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.sal.java.api.generator.test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.COMPILER_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.FS;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.GENERATOR_OUTPUT_PATH;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
+import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+public class UnionTypedefUnusedImportTest extends BaseCompilationTest {
+
+    @Test
+    public void testUnionTypedefUnusedImport() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "union-typedef");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdir());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "union-typedef");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdir());
+
+        final List<File> sourceFiles = getSourceFiles("/compilation/union-typedef");
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        final List<Type> types = bindingGenerator.generateTypes(context);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(new HashSet<>(types));
+        generator.generateToFile(sourcesOutputDir);
+        final boolean isUsedImport = containsImport("org.opendaylight.yang.gen.v1.org.opendaylight.yangtools.union.typedef.rev130208.TypedefUnion");
+        assertFalse(String.format("Class shouldn't contain import for this type '%s'", types.get(1).getName()),
+                isUsedImport);
+
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    private static String readFile(final String path, final Charset encoding) throws IOException {
+        byte[] encoded = Files.readAllBytes(Paths.get(path));
+        return new String(encoded, encoding);
+    }
+
+    private static boolean containsImport(final String fullImport) throws URISyntaxException, IOException {
+        final String filePath = GENERATOR_OUTPUT_PATH + FS + "union-typedef" + FS + "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1" + FS + "org" + FS + "opendaylight" + FS + "yangtools" + FS + "union" + FS + "typedef" + FS + "rev141124" + FS + "TypedefUnionBuilder.java";
+        final String fileContent = readFile(filePath, StandardCharsets.UTF_8);
+
+        if (fileContent.contains(fullImport)) {
+            return true;
+        }
+        return false;
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/package-info.java b/code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/package-info.java
new file mode 100644 (file)
index 0000000..b7b712b
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+  * 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.sal.java.api.generator.test;
\ No newline at end of file
diff --git a/code-generator/binding-java-api-generator/src/test/resources/abstract-topology.yang b/code-generator/binding-java-api-generator/src/test/resources/abstract-topology.yang
new file mode 100644 (file)
index 0000000..29e3603
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * 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
+ */
+// vi: set smarttab sw=4 tabstop=4:
+module abstract-topology {
+       yang-version 1;
+    namespace "";
+    prefix "tp";
+
+       import ietf-inet-types { prefix "inet"; }
+    import abstract-prefixes { prefix "abs-pref"; }
+    
+       organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+               This module contains the definitions of elements that creates network 
+               topology i.e. definition of network nodes and links. This module is
+               not designed to be used solely for network representation. This module
+               SHOULD be used as base module in defining the network topology.
+       ";
+
+    revision "2013-02-08" {
+               reference " WILL BE DEFINED LATER";
+       }
+
+    revision "2013-03-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+    
+    revision "2012-02-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    typedef topology-id-ref {
+       type leafref {
+               path "/tp:topology/tp:topology-id";
+       }
+       description "This type is used for leafs that reference topology identifier instance.";
+    }
+
+       typedef network-node-id-ref {
+               type leafref {
+                       path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id";
+               }
+               description "This type is used for leafs that reference network node instance.";
+       }
+
+       typedef link-id-ref {
+               type leafref {
+                       path "/tp:topology/tp:network-links/tp:network-link/tp:link-id";
+               }
+               description "This type is used for leafs that reference network link instance.";
+       }
+
+       container topology {
+        description "
+                       This is the model of abstract topology which contains only Network
+                       Nodes and Network Links. Each topology MUST be identified by
+                       unique topology-id for reason that the store could contain many
+                       topologies.
+               ";
+
+        leaf topology-id {
+            type inet:uri;
+            description "
+                               It is presumed that datastore will contain many topologies. To
+                               distinguish between topologies it is vital to have UNIQUE
+                               topology identifier.
+                       ";
+        }
+
+        container network-nodes {
+               list network-node {
+                   description "The list of network nodes defined for topology.";
+
+                       key "node-id";
+
+                       leaf node-id {
+                               type inet:uri;
+                               description "The Topology identifier of network-node.";
+                       }
+
+                   container attributes {
+                                       description "
+                                               Additional attributes that can Network Node contains.
+                                       ";
+                               }
+               }
+        }
+        
+        container network-links {
+               list network-link {
+                   description "
+                                       The Network Link which is defined by Local (Source) and
+                                       Remote (Destination) Network Nodes. Every link MUST be
+                                       defined either by identifier and his local and remote
+                                       Network Nodes (in real applications it is common that many
+                                       links are originated from one node and end up in same
+                                       remote node). To ensure that we would always know to
+                                       distinguish between links, every link SHOULD have
+                                       identifier.
+                               ";
+                       key "link-id";
+
+                       leaf link-id {
+                               type inet:uri;
+                               description "";
+                       }
+
+                   container source {
+                                       leaf node-id {
+                                               type node-id-ref;
+                                               description "Source node identifier.";
+                                       }
+                               }
+
+                               container destination {
+                                       leaf node-id {
+                                               type node-id-ref;
+                                               description "Destination node identifier.";
+                                       }
+                               }
+
+                               container attributes {
+                                       description "Aditional attributes that can Network Link contains.";
+                               }
+                   }
+        }
+    }
+
+    //TODO: add base operations
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/bar.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/bar.yang
new file mode 100644 (file)
index 0000000..90ce18a
--- /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
+ */
+module bar {
+    yang-version 1;
+    namespace "urn:opendaylight:bar";
+    prefix "bar";
+
+    import foo { prefix fo; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    augment "/fo:update/fo:path-attributes" {
+        container mp-unreach-nlri {
+            container withdrawn-routes {
+                uses destination;
+            }
+        }
+    }
+
+    grouping destination {
+        choice destination-type {
+            case destination-ip {
+                leaf-list prefixes {
+                    type string;
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/baz.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/baz.yang
new file mode 100644 (file)
index 0000000..d3fad40
--- /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
+ */
+module baz {
+    yang-version 1;
+    namespace "urn:opendaylight:baz";
+    prefix "baz";
+
+    import foo { prefix fo; revision-date 2013-10-08; }
+    import bar { prefix br; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    augment "/fo:update/fo:path-attributes/br:mp-unreach-nlri/br:withdrawn-routes/br:destination-type" {
+        case destination-linkstate {
+            uses linkstate-destination;
+            container links {
+                container source {
+                    container address {}
+                }
+            }
+        }
+    }
+
+    grouping linkstate-destination {
+        leaf nlri-type {
+            type string;
+        }
+        leaf protocol-id {
+            type string;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-of-augment/foo.yang
new file mode 100644 (file)
index 0000000..af19e06
--- /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:opendaylight:foo";
+    prefix "foo";
+
+    revision "2013-10-08" {
+    }
+
+    grouping path-attributes {
+        container origin {
+            leaf value {
+                type string;
+            }
+        }
+    }
+
+    notification update {
+        container path-attributes {
+            uses path-attributes;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/bar.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/bar.yang
new file mode 100644 (file)
index 0000000..7dee386
--- /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
+ */
+module bar {
+    yang-version 1;
+    namespace "urn:opendaylight:bar";
+    prefix "bar";
+
+    revision "2013-10-08" {
+    }
+
+    grouping basic-explicit-route-subobjects {
+        choice subobject-type {
+            case ip-prefix {
+            }
+            case label {
+            }
+        }
+    }
+
+    grouping explicit-route-subobjects {
+        uses basic-explicit-route-subobjects;
+    }
+
+    grouping route-subobjects {
+        container links {
+            container link {
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-under-uses/foo.yang
new file mode 100644 (file)
index 0000000..f1cb5f8
--- /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
+ */
+module foo {
+    yang-version 1;
+    namespace "urn:opendaylight:foo";
+    prefix "foo";
+
+    import bar { prefix b; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    grouping object {
+        container nodes {
+        }
+    }
+
+    grouping open-object {
+        uses object {
+            augment "nodes" {
+                container links {
+                    leaf id {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+    grouping closed-object {
+        uses b:route-subobjects {
+            augment "links/link" {
+                leaf id {
+                    type string;
+                }
+            }
+        }
+    }
+
+    grouping explicit-route-object {
+        list subobjects {
+            leaf loose {
+                type boolean;
+            }
+            uses b:explicit-route-subobjects {
+                augment "subobject-type" {
+                    case path-key {
+                        container path-key {
+                            uses path-key-subobject;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    grouping path-key-subobject {
+        leaf path-key {
+            type string;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/bar.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/bar.yang
new file mode 100644 (file)
index 0000000..069fbe1
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * 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:opendaylight.bar";
+    prefix "bar";
+       
+       description "bar - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+       reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+
+    revision "2013-10-08" {
+    }
+
+    container network-topology {
+               description "network-topology - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+               reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+               
+        list topology {
+                       description "topology - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                       reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+                       
+            key "topology-id";
+            leaf topology-id {
+                               description "topology-id - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                               reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+                type int32;
+            }
+            uses link;
+        }
+    }
+
+    grouping link {
+        list link {
+                       description "Link - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                       reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+            key "link-id";
+            uses link-attributes;
+        }
+    }
+
+    grouping link-attributes {
+        leaf link-id {
+                       description "Link-attributes - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                       reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+            type int8;
+        }
+    }
+       
+       leaf inclusion-rulez {
+               description "Specified rulez description.";
+               reference "RFC 6020 http://technet.com";
+               
+               type string;
+       }
+
+       leaf inclusion-rule {
+        description "Specify how inheritance will work for this label";
+        default include;
+
+        type enumeration {
+            enum include {
+                description 
+                    "This label will be included normally in the 
+                     matching. This seems to be a little bit longer comment. I hear you very weel my darling.
+                                        Network topology is the arrangement of the various elements (links, nodes, etc.) of any other builder nodes types.";
+            }
+            enum exclude {
+                description 
+                    "This label will be excluded from the 
+                    matching.  This allows removing labels that
+                    would have otherwise been included because of
+                    inheritence rules.";
+            }
+        }
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/baz.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/baz.yang
new file mode 100644 (file)
index 0000000..4bdc209
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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 baz {
+    yang-version 1;
+    namespace "urn:opendaylight.baz";
+    prefix "baz";
+
+    import foo {
+        prefix "fo";
+        revision-date 2013-10-08;
+    }
+
+    import bar {
+        prefix "br";
+        revision-date 2013-10-08;
+    }
+       
+       description "Baz - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+       reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+
+    revision "2013-10-08" {
+    }
+
+
+
+    augment "/br:network-topology/br:topology/br:link/fo:igp-link-attributes" {
+        uses link-attributes;
+    }
+
+    grouping link-attributes {
+        container ospf-link-attributes {
+                       description "Ospf-link-attributes - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                       reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+            leaf multi-topology-id {
+                               description "Multi-topology-id - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                               reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+                               
+                type uint8 {
+                    range "0..127";
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/augment-uses-to-augment/foo.yang
new file mode 100644 (file)
index 0000000..5fa313e
--- /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
+ */
+module foo {
+    yang-version 1;
+    namespace "urn:opendaylight.foo";
+    prefix "foo";
+
+    import bar {
+        prefix "br";
+        revision-date 2013-10-08;
+    }
+       
+       description "Foo - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+       reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+
+    revision "2013-10-08" {
+    }
+
+
+    augment "/br:network-topology/br:topology/br:link" {
+        uses igp-link-attributes;
+    }
+
+    grouping igp-link-attributes {
+        container igp-link-attributes {
+                       description "Igp-link-attributes - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                       reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+               
+            leaf name {
+                               description "Name - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                               reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+                type string;
+            }
+            leaf-list flag {
+                               description "Flag - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                               reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+                type string;
+            }
+            leaf metric {
+                               description "Metric - Network topology is the arrangement of the various elements (links, nodes, etc.) of a computer network.[1][2] Essentially, it is the topological[3] structure of a network, and may be depicted physically or logically. Physical topology is the placement of the various components of a network, including device location and cable installation, while logical topology illustrates how data flows within a network, regardless of its physical design. Distances between nodes, physical interconnections, transmission rates, or signal types may differ between two networks, yet their topologies may be identical.";
+                               reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+                type uint32 {
+                    range "0..16777215"  {
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/bug1172/nested-uses-augment.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/bug1172/nested-uses-augment.yang
new file mode 100644 (file)
index 0000000..7377e94
--- /dev/null
@@ -0,0 +1,40 @@
+module nested-uses-augment {
+    yang-version 1;
+    namespace "odl:test:nua";
+    prefix "nua";
+
+    revision "2014-07-11" {
+    }
+
+    grouping machine-types {
+        container types {
+            choice machine-type {
+            }
+        }
+    }
+
+    grouping machine-ext {
+        uses machine-types {
+            augment "types/machine-type" {
+                case type-a {
+                    leaf id {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+    grouping machine-ext2 {
+        uses machine-ext {
+            augment "types/machine-type" {
+                case type-b {
+                    leaf name {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/bug1276/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/bug1276/foo.yang
new file mode 100644 (file)
index 0000000..9f77227
--- /dev/null
@@ -0,0 +1,62 @@
+ module foo {
+
+   namespace "test:yang:union";
+   prefix "foo";
+
+   revision 2014-07-15 {
+   }
+
+
+   typedef ip-address {
+     type union {
+       type ipv4-address;
+       type ipv6-address;
+     }
+   }
+
+   typedef ipv4-address {
+     type string {
+       pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '(%[\p{N}\p{L}]+)?';
+     }
+   }
+
+   typedef ipv6-address {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(%[\p{N}\p{L}]+)?';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(%.+)?';
+     }
+   }
+
+   typedef domain-name {
+     type string {
+       pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+            +  '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+            +  '|\.';
+       length "1..253";
+     }
+   }
+
+   typedef host {
+     type union {
+       type ip-address;
+       type domain-name;
+     }
+   }
+
+    typedef int-type {
+        type union {
+            type binary;
+            type int8;
+        }
+    }
+
+ }
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/bug1377/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/bug1377/foo.yang
new file mode 100644 (file)
index 0000000..b31a891
--- /dev/null
@@ -0,0 +1,21 @@
+module foo {
+  namespace "urn:test:foo";
+  prefix foo;
+
+  revision 2014-07-17 {
+  }
+
+
+    grouping action {
+        choice action {
+            case output-action-case {
+                container output-action {
+                    leaf id {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+}
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;
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/bar.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/bar.yang
new file mode 100644 (file)
index 0000000..17daeb8
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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:opendaylight:bar";
+    prefix "bar";
+
+    import baz { prefix bz; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    grouping bar_gr1 {
+        leaf bar1 {
+            type int8;
+        }
+        leaf bar2 {
+            type int16;
+        }
+    }
+
+    grouping bar_gr2 {
+        leaf bar3 {
+            type int32;
+        }
+        uses bar_gr1;
+        uses bz:baz_gr1;
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/baz.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/baz.yang
new file mode 100644 (file)
index 0000000..8e5b015
--- /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
+ */
+module baz {
+    yang-version 1;
+    namespace "urn:opendaylight:baz";
+    prefix "baz";
+
+    revision "2013-10-08" {
+    }
+
+    grouping baz_gr1 {
+        leaf baz1 {
+            type uint8;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/cascade-uses/foo.yang
new file mode 100644 (file)
index 0000000..a491786
--- /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
+ */
+module foo {
+    yang-version 1;
+    namespace "urn:opendaylight:foo";
+    prefix "foo";
+
+    import bar { prefix br; revision-date 2013-10-08; }
+
+    revision "2013-10-08" {
+    }
+
+    grouping foo_gr1 {
+        container foo_gr1 {
+        }
+        leaf foo2 {
+            type binary;
+        }
+    }
+
+    container nodes {
+        uses foo_gr1;
+        uses "br:bar_gr2";
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/class-name-collision/class-name-collision b/code-generator/binding-java-api-generator/src/test/resources/compilation/class-name-collision/class-name-collision
new file mode 100644 (file)
index 0000000..6325820
--- /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
+ */
+module class-name-collision {
+    yang-version 1;
+    namespace "urn:class:name:collision";
+    prefix "bar";
+
+    revision "2014-04-28" {
+
+    }
+
+    list string {
+    }
+
+    list string-builder {
+    }
+
+    list class {
+    }
+
+    list set {
+    }
+
+    list map {
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/class-name-collision/configuration b/code-generator/binding-java-api-generator/src/test/resources/compilation/class-name-collision/configuration
new file mode 100644 (file)
index 0000000..10058ab
--- /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 configuration {
+    yang-version 1;
+    namespace "urn:configuration";
+    prefix "bar";
+
+    revision "2014-04-30" {
+    }
+
+    container configuration {
+        list class {
+            key "name";
+            leaf name {
+                type string;
+            }
+            leaf value {
+                type string;
+            }
+       }
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/class-name-collision/other-module b/code-generator/binding-java-api-generator/src/test/resources/compilation/class-name-collision/other-module
new file mode 100644 (file)
index 0000000..46964be
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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 other-module {
+    yang-version 1;
+    namespace "urn:other-module";
+    prefix "bar";
+
+    revision "2014-04-29" {
+    }
+
+    list foo {
+    }
+
+    list boo {
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/context-reference/bar.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/context-reference/bar.yang
new file mode 100644 (file)
index 0000000..6f39ed3
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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:opendaylight:bar";
+    prefix "b";
+
+    revision "2013-10-08" {
+    }
+
+    identity identity-class {
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/context-reference/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/context-reference/foo.yang
new file mode 100644 (file)
index 0000000..a016f82
--- /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
+ */
+module foo {
+    yang-version 1;
+    namespace "urn:opendaylight:foo";
+    prefix "f";
+    
+    import bar { prefix "b"; }
+
+    revision "2013-10-08" {
+    }
+
+    extension context-reference {
+    }
+
+    container nodes {
+        leaf id {
+            type instance-identifier;
+            context-reference "b:identity-class";
+        }
+        leaf-list constraints {
+            type string;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/encoding-javadoc/encoding-javadoc.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/encoding-javadoc/encoding-javadoc.yang
new file mode 100644 (file)
index 0000000..c66cef9
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 encoding-javadoc {
+    yang-version 1;
+    namespace "urn:opendaylight:encoding-javadoc";
+    prefix "enc";
+
+    revision "2014-04-09" {
+    }
+
+    container cont1 {
+        description "/e.g. 1/*/*";
+        reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+
+        list list1 {
+            description "/e.g. 1/*/*";
+            reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+
+            key "topology-id";
+            leaf topology-id {
+                description "/e.g. 1/*/*";
+                reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+                type int32;
+            }
+            uses link1;
+        }
+    }
+
+    grouping link1 {
+        list link1 {
+            description "/e.g. 1/*/*";
+            reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+            key "link-id";
+            uses link-attributes;
+        }
+    }
+
+    grouping link-attributes {
+        leaf link-id {
+            description "/e.g. 1/*/*";
+            reference "RFC 6020 - http://tools.ietf.org/html/rfc6020";
+            type int8;
+        }
+    }
+
+    leaf inclusion-rulez {
+        description "/e.g. 1/*/*";
+        reference "RFC 6020 http://technet.com";
+
+        type string;
+    }
+
+    leaf inclusion-rule {
+        description "/e.g. 1/*/*";
+        default include;
+
+        type enumeration {
+            enum include {
+                description
+                    "/e.g. 1/*/*";
+            }
+            enum exclude {
+                description
+                    "/e.g. 1/*/*";
+            }
+        }
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/leaf-return-types/test.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/leaf-return-types/test.yang
new file mode 100644 (file)
index 0000000..0d8dace
--- /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
+ */
+module test {
+    yang-version 1;
+    namespace "urn:opendaylight:test";
+    prefix "t";
+
+    revision "2013-10-08" {
+    }
+
+    container nodes {
+        leaf id-binary {
+            type binary {
+                length 1..10;
+            }
+        }
+        leaf id-bits {
+            type bits {
+                bit ctrl;
+                bit alt {
+                    position 5;
+                }
+                bit delete;
+            }
+        }
+        leaf id-boolean {
+            type boolean;
+        }
+        leaf id-decimal64 {
+            type decimal64 {
+                fraction-digits 4;
+                range "1.5..5.5";
+            }
+        }
+        leaf id-empty {
+            type empty;
+        }
+        leaf id-enumeration {
+            type enumeration {
+                enum zero;
+                enum one;
+                enum seven {
+                    value 7;
+                }
+            }
+        }
+        leaf id-identityref {
+            type identityref {
+                base alg;
+            }
+        }
+        leaf id-instance-identifier {
+            type instance-identifier;
+        }
+        leaf id-8 {
+            type int8;
+        }
+        leaf id-16 {
+            type int16;
+        }
+        leaf id-32 {
+            type int32;
+        }
+        leaf id-64 {
+            type int64;
+        }
+        leaf id-leafref {
+            type leafref {
+                path "/nodes/id-64";
+            }
+        }
+        leaf id-string {
+            type string;
+        }
+        leaf id-u8 {
+            type uint8;
+        }
+        leaf id-u16 {
+            type uint16;
+        }
+        leaf id-u32 {
+            type uint32;
+        }
+        leaf id-u64 {
+            type uint64;
+        }
+        leaf id-union {
+            type union {
+                type string;
+                type binary;
+            }
+        }
+    }
+
+    identity alg {
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/list-gen/test.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/list-gen/test.yang
new file mode 100644 (file)
index 0000000..faa7a7e
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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 test {
+    yang-version 1;
+    namespace "urn:opendaylight:test";
+    prefix "t";
+
+    revision "2013-10-08" {
+    }
+
+    grouping key-args {
+        leaf name {
+            type string;
+        }
+        leaf size {
+            type int32;
+        }
+    }
+
+    list links {
+        uses key-args;
+        key "size name id";
+
+        leaf id {
+            type int8;
+        }
+
+        anyxml text;
+        choice level;
+        container node;
+        grouping link-group {
+            leaf source {
+                type int8;
+            }
+        }
+        leaf links-id {
+            type int32;
+        }
+        list node-list {
+        }
+        typedef nodes-type {
+            type string;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/nested-grouping/test.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/nested-grouping/test.yang
new file mode 100644 (file)
index 0000000..94cf5e1
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * 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 test {
+    yang-version 1;
+    namespace "urn:opendaylight:test";
+    prefix "t";
+
+    revision "2013-10-08" {
+    }
+
+    container foo {
+        grouping bar {
+            leaf id {
+                type int32;
+            }
+        }
+        uses bar;
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/typedef/foo.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/typedef/foo.yang
new file mode 100644 (file)
index 0000000..855279f
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * 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:opendaylight.foo";
+    prefix "foo";
+
+    revision "2013-10-08" {
+    }
+
+
+    typedef bits-ext {
+        type bits {
+            bit pc {
+                position 0;
+            }
+            bit bpc {
+                position 1;
+            }
+            bit dpc {
+                position 2;
+            }
+            bit lbpc {
+                position 3;
+            }
+            bit spc {
+                position 4;
+            }
+            bit sfmof {
+                position 5;
+            }
+            bit sfapc {
+                position 6;
+            }
+        }
+    }
+
+    typedef myenum {
+        type enumeration {
+            enum zero;
+            enum one;
+            enum seven {
+                value 7;
+            }
+        }
+        default one;
+    }
+
+    typedef int32-ext0 {
+        type int32;
+    }
+
+    typedef int32-ext1 {
+        type int32 {
+            range "2..2147483647";
+        }
+    }
+
+    typedef int32-ext2 {
+        type int32-ext1 {
+            range "3..9|11..max";
+        }
+        units "mile";
+        default "11";
+    }
+
+    typedef string-ext1 {
+        type string {
+            pattern "[a-k]*";
+            length "5..11";
+        }
+    }
+
+    typedef string-ext2 {
+        type string-ext1 {
+            length "6..10";
+        }
+    }
+
+    typedef string-ext3 {
+        type string-ext2 {
+            pattern "[b-u]*";
+        }
+    }
+
+    typedef my-decimal-type {
+        type decimal64 {
+            fraction-digits 6;
+            range "1.5..5.5";
+        }
+    }
+
+    typedef my-decimal-type2 {
+        type decimal64 {
+            fraction-digits 18;
+            range "0..1";
+        }
+    }
+
+    typedef union-ext1 {
+        type union {
+            type int16 {
+                range "1..100";
+            }
+            type int32;
+        }
+    }
+
+    typedef union-ext2 {
+        type union-ext1;
+    }
+
+    typedef union-ext3 {
+        type union {
+            type union-ext2;
+            type string;
+        }
+        units "object id";
+    }
+
+    typedef union-ext4 {
+        type union {
+            type union-ext3;
+            type int32-ext2;
+            type empty;
+            type my-decimal-type;
+        }
+    }
+
+    typedef b1 {
+        type binary;
+    }
+
+    typedef b2 {
+        type b1;
+    }
+
+    typedef b3 {
+        type b2 {
+            length 1..10;
+        }
+    }
+
+    container c1 {
+        leaf id {
+            type b3;
+        }
+    }
+
+
+    typedef a {
+        type int8;
+    }
+
+    typedef b {
+        type int16;
+    }
+
+    typedef c {
+        type int32;
+    }
+
+    typedef d {
+        type int64 {
+            range 0..max;
+        }
+    }
+
+    typedef e {
+        type uint8;
+    }
+
+    typedef f {
+        type uint16;
+    }
+
+    typedef g {
+        type uint32;
+    }
+
+    typedef h {
+        type uint64;
+    }
+    container cont1 {
+        leaf leaf1 {
+            type union-ext1;
+        }
+    }
+
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/compilation/union-typedef/union-typedef-test.yang b/code-generator/binding-java-api-generator/src/test/resources/compilation/union-typedef/union-typedef-test.yang
new file mode 100644 (file)
index 0000000..b271f07
--- /dev/null
@@ -0,0 +1,19 @@
+module union-typedef-test {
+    yang-version 1;
+    namespace "org:opendaylight:yangtools:union:typedef";
+    prefix "tp";
+
+    description
+        "Test unused import";
+
+    revision "2014-11-24" {
+        reference "WILL BE DEFINED LATER";
+    }
+
+    typedef typedef-union {
+        type union {
+            type int32;
+            type string;
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-java-api-generator/src/test/resources/demo-topology.yang b/code-generator/binding-java-api-generator/src/test/resources/demo-topology.yang
new file mode 100644 (file)
index 0000000..c217824
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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 demo-topology {
+       yang-version 1;
+    namespace "";
+    prefix "tp";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+               This module contains the definitions of elements that creates network 
+               topology i.e. definition of network nodes and links. This module is
+               not designed to be used solely for network representation. This module
+               SHOULD be used as base module in defining the network topology.
+       ";
+
+    revision "2013-02-08"{
+               reference " WILL BE DEFINED LATER";
+       }
+
+       container topology {
+        description "
+                       This is the model of abstract topology which contains only Network
+                       Nodes and Network Links. Each topology MUST be identified by
+                       unique topology-id for reason that the store could contain many
+                       topologies.
+               ";
+
+        leaf topology-id {
+            type string;
+            description "
+                               It is presumed that datastore will contain many topologies. To
+                               distinguish between topologies it is vital to have UNIQUE
+                               topology identifier.
+                       ";
+        }
+
+        container network-nodes {
+               list network-node {
+                   description "The list of network nodes defined for topology.";
+
+                       key "node-id";
+
+                       leaf node-id {
+                               type string;
+                               description "The Topology identifier of network-node.";
+                       }
+                
+                list network-interface {
+                    key "interface-id";
+                    
+                    leaf interface-id {
+                        type uint8;
+                    }
+                    
+                    leaf interface-address {
+                        type string;
+                    }
+                }
+                
+                   container node-attributes {
+                                       description "
+                                               Additional attributes that can Network Node contains.
+                                       ";
+
+                                       leaf geo-latitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
+
+                                       leaf geo-longitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
+                               }
+               }
+        }
+        
+        container network-links {
+               list network-link {
+                   description "
+                                       The Network Link which is defined by Local (Source) and
+                                       Remote (Destination) Network Nodes. Every link MUST be
+                                       defined either by identifier and his local and remote
+                                       Network Nodes (in real applications it is common that many
+                                       links are originated from one node and end up in same
+                                       remote node). To ensure that we would always know to
+                                       distinguish between links, every link SHOULD have
+                                       identifier.
+                               ";
+                       key "link-id";
+
+                       leaf link-id {
+                               type string;
+                               description "";
+                       }
+
+                   container source {
+                                       leaf node-id {
+                                               type string;
+                                               description "Source node identifier.";
+                                       }
+                               }
+
+                               container destination {
+                                       leaf node-id {
+                                               type string;
+                                               description "Destination node identifier.";
+                                       }
+                               }
+
+                               container link-attributes {
+                                       description "Aditional attributes that can Network Link contains.";
+                               }
+                   }
+        }
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/list-composite-key.yang b/code-generator/binding-java-api-generator/src/test/resources/list-composite-key.yang
new file mode 100644 (file)
index 0000000..fd3f66b
--- /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
+ */
+module list-composite-key {
+    yang-version 1;
+    namespace "urn:composite.key";
+    prefix "scd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+        This module contains the definitions of elements that creates network 
+        topology i.e. definition of network nodes and links. This module is
+        not designed to be used solely for network representation. This module
+        SHOULD be used as base module in defining the network topology.
+    ";
+
+    revision "2013-02-27" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    container list-parent-container {
+
+        list composite-key-list {
+            key "key1 key2";
+
+            leaf key1 {
+                type int8;
+            }
+            
+            leaf key2 {
+                type string;
+            }
+            
+            list inner-list {
+                key "key1";
+                
+                leaf key1 {
+                    type uint16;
+                }
+                
+                leaf foo {
+                    type int32;
+                }
+            }
+            
+            leaf foo {
+                type int32;
+            }
+        }
+        
+        list no-key-list {
+            leaf foo {
+                type int32;
+            }
+            
+            leaf bar {
+                type decimal64 {
+                    fraction-digits 2;
+                }
+            }
+        }
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/simple-container-demo.yang b/code-generator/binding-java-api-generator/src/test/resources/simple-container-demo.yang
new file mode 100644 (file)
index 0000000..1d854bb
--- /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
+ */
+module simple-container-demo {
+       yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "scd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+        This module contains the definitions of elements that creates network 
+        topology i.e. definition of network nodes and links. This module is
+        not designed to be used solely for network representation. This module
+        SHOULD be used as base module in defining the network topology.
+    ";
+
+    revision "2012-02-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    revision "2010-02-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    container simple-container {
+
+       leaf foo {
+               type int32;
+       }
+
+       leaf bar {
+               type string;
+               config true;
+       }
+
+       container nested-container {
+               leaf foo {
+                       type uint8;
+               }
+
+               leaf bar {
+                       type string;
+               }
+       }
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/simple-leaf-list-demo.yang b/code-generator/binding-java-api-generator/src/test/resources/simple-leaf-list-demo.yang
new file mode 100644 (file)
index 0000000..f5d8345
--- /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
+ */
+module simple-leaf-list-demo {
+    yang-version 1;
+    namespace "urn:simple.leaf-list.demo";
+    prefix "scd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+        This module contains the definitions of elements that creates network 
+        topology i.e. definition of network nodes and links. This module is
+        not designed to be used solely for network representation. This module
+        SHOULD be used as base module in defining the network topology.
+    ";
+
+    revision "2012-02-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    revision "2010-02-08" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    container simple-container {
+
+        leaf-list foo {
+            type int32;
+        }
+
+        leaf bar {
+            type string;
+            config true;
+        }
+
+        container nested-container {
+            leaf foo {
+                type uint8;
+            }
+
+            leaf-list bar {
+                type string;
+                config true;
+            }
+        }
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/simple-list-demo.yang b/code-generator/binding-java-api-generator/src/test/resources/simple-list-demo.yang
new file mode 100644 (file)
index 0000000..c8f7f36
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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 simple-list-demo {
+       yang-version 1;
+    namespace "urn:simple.container.demo";
+    prefix "scd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+        This module contains the definitions of elements that creates network 
+        topology i.e. definition of network nodes and links. This module is
+        not designed to be used solely for network representation. This module
+        SHOULD be used as base module in defining the network topology.
+    ";
+
+    revision "2013-02-27" {
+        reference " WILL BE DEFINED LATER";
+    }
+
+    container list-parent-container {
+
+       list simple-list {
+               key "list-key";
+
+               leaf list-key {
+                       type int8;
+               }
+            
+            container list-child-container {
+                leaf foo {
+                    type uint8;
+                }
+            }
+            
+               leaf foo {
+                       type int32;
+               }
+            
+            leaf-list simple-leaf-list {
+                type int32;
+            }
+            
+               leaf bar {
+                       type string;
+                       config true;
+               }       
+       }
+    }
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/yang/abstract-topology@2013-02-08.yang b/code-generator/binding-java-api-generator/src/test/resources/yang/abstract-topology@2013-02-08.yang
new file mode 100644 (file)
index 0000000..af27745
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * 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 abstract-topology {
+    yang-version 1;
+    namespace "urn:model:abstract:topology";
+    prefix "tp";
+
+    import ietf-inet-types {
+        prefix "inet";
+        revision-date 2010-09-24;
+    }
+
+    import ietf-interfaces {
+        prefix "if";
+        revision-date 2012-11-15;
+    }
+
+    organization "Cisco";
+    contact "WILL-BE-DEFINED-LATER";
+
+    description
+        "This module contains the definitions of elements that creates network 
+    topology i.e. definition of network nodes and links. This module is not designed to be used solely for network representation. This module SHOULD be used as base module in defining the network topology.";
+
+    revision "2013-02-08" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+    
+    revision "2013-01-01" {
+        reference "~~~ WILL BE DEFINED LATER";
+    }
+    
+    typedef node-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-nodes/tp:network-node/tp:node-id";
+        }
+        description "This type is used for leafs that reference network node instance.";
+    }
+
+    typedef link-id-ref {
+        type leafref {
+            path "/tp:topology/tp:network-links/tp:network-link/tp:link-id";
+        }
+        description "This type is used for leafs that reference network link instance.";
+    }
+
+    typedef interface-id-ref {
+        type leafref {
+            path "/tp:topology/tp:interfaces/tp:interface/tp:interface-id";
+        }
+    }
+
+    container topology {
+        description "This is the model of abstract topology which contains only Network Nodes and Network Links. Each topology MUST be identified by unique topology-id for reason that the store could contain many topologies.";
+
+        leaf topology-id {
+            type inet:uri;
+            description "It is presumed that datastore will contain many topologies. To distinguish between topologies it is vital to have
+            UNIQUE topology identifier.";
+        }
+
+        container network-nodes {
+            list network-node {
+                key "node-id";
+
+                leaf node-id {
+                    type inet:uri;
+                    description "The Topology identifier of network-node.";
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Node contains.";
+                }
+                description "The list of network nodes defined for topology.";
+            }
+        }
+
+        container interfaces {
+            list interface {
+                key "interface-id";
+
+                leaf interface-id {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:name";
+                    }
+                }
+
+                leaf-list higher-layer-if {
+                    type leafref {
+                        path "/if:interfaces/if:interface/if:higher-layer-if";
+                    }
+                }
+            }
+        }
+        
+        container network-links {
+            list network-link {
+                key "link-id";
+
+                leaf link-id {
+                    type inet:uri;
+                    description "";
+                }
+
+                container source-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Source node identifier.";
+                    }
+                }
+
+                container destination-node {
+                    leaf id {
+                        type node-id-ref;
+                        description "Destination node identifier.";
+                    }
+                }
+
+                container tunnels {
+                    list tunnel {
+                        key "tunnel-id";
+
+                        leaf tunnel-id {
+                            type leafref {
+                                path "../../../link-id";
+                            }
+                        }
+                    }
+                }
+
+                leaf interface {
+                    type interface-id-ref;
+                }
+
+                container attributes {
+                    description "Aditional attributes that can Network Link contains.";
+                }
+                description "The Network Link which is defined by Local (Source) and Remote (Destination) Network Nodes. Every link MUST be defined either by identifier and
+                his local and remote Network Nodes (In real applications it is common that many links are originated from one node and end up in same remote node). To ensure that we would always know to distinguish between links, every link SHOULD have identifier.";
+            }
+        }
+    }
+    
+    identity crypto-base {
+        description "crypto-base description";
+    }
+    
+    identity crypto-alg {
+        base crypto-base;
+        description "crypto-alg description";
+    }
+    
+    grouping target {
+        container nodes {
+            leaf source {
+                type int8;
+            }
+            leaf target {
+                type int16;
+            }
+        }
+        leaf id {
+            type string;
+        }
+    }
+    
+    leaf idreftest {
+        type identityref {
+            base crypto-alg;
+        }
+    }
+    
+}
diff --git a/code-generator/binding-java-api-generator/src/test/resources/yang/iana-if-type@2012-06-05.yang b/code-generator/binding-java-api-generator/src/test/resources/yang/iana-if-type@2012-06-05.yang
new file mode 100644 (file)
index 0000000..a7fa137
--- /dev/null
@@ -0,0 +1,1516 @@
+module iana-if-type {
+  namespace "urn:ietf:params:xml:ns:yang:iana-if-type";
+  prefix ianaift;
+
+  organization "IANA";
+  contact
+    "        Internet Assigned Numbers Authority
+
+     Postal: ICANN
+             4676 Admiralty Way, Suite 330
+             Marina del Rey, CA 90292
+
+     Tel:    +1 310 823 9358
+     E-Mail: iana&iana.org";
+  description
+    "This YANG module defines the iana-if-type typedef, which
+     contains YANG definitions for IANA-registered interface types.
+
+     This YANG module is maintained by IANA, and reflects the
+     'ifType definitions' registry.
+
+     The latest revision of this YANG module can be obtained from
+     the IANA web site.
+
+     Copyright (c) 2011 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see
+     the RFC itself for full legal notices.";
+  // RFC Ed.: replace XXXX with actual RFC number and remove this
+  // note.
+
+  // RFC Ed.: update the date below with the date of RFC publication
+  // and remove this note.
+  revision 2012-06-05 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: TITLE";
+  }
+
+  typedef iana-if-type {
+    type enumeration {
+      enum "other" {
+        value 1;
+        description
+          "None of the following";
+      }
+      enum "regular1822" {
+        value 2;
+      }
+      enum "hdh1822" {
+        value 3;
+      }
+      enum "ddnX25" {
+        value 4;
+      }
+      enum "rfc877x25" {
+        value 5;
+        reference
+          "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer";
+      }
+      enum "ethernetCsmacd" {
+        value 6;
+        description
+          "For all ethernet-like interfaces, regardless of speed,
+           as per RFC3635.";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "iso88023Csmacd" {
+        value 7;
+        status deprecated;
+        description
+          "Deprecated via RFC3635.
+           Use ethernetCsmacd(6) instead.";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "iso88024TokenBus" {
+        value 8;
+      }
+      enum "iso88025TokenRing" {
+        value 9;
+      }
+      enum "iso88026Man" {
+        value 10;
+      }
+      enum "starLan" {
+        value 11;
+        status deprecated;
+        description
+          "Deprecated via RFC3635.
+           Use ethernetCsmacd(6) instead.";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "proteon10Mbit" {
+        value 12;
+      }
+      enum "proteon80Mbit" {
+        value 13;
+      }
+      enum "hyperchannel" {
+        value 14;
+      }
+      enum "fddi" {
+        value 15;
+        reference
+          "RFC 1512 - FDDI Management Information Base";
+      }
+      enum "lapb" {
+        value 16;
+        reference
+          "RFC 1381 - SNMP MIB Extension for X.25 LAPB";
+      }
+      enum "sdlc" {
+        value 17;
+      }
+      enum "ds1" {
+        value 18;
+        description
+          "DS1-MIB";
+        reference
+          "RFC 4805 - Definitions of Managed Objects for the
+                      DS1, J1, E1, DS2, and E2 Interface Types";
+      }
+      enum "e1" {
+        value 19;
+        status obsolete;
+        description
+          "Obsolete see DS1-MIB";
+        reference
+          "RFC 4805 - Definitions of Managed Objects for the
+                      DS1, J1, E1, DS2, and E2 Interface Types";
+      }
+      enum "basicISDN" {
+        value 20;
+        description
+          "see also RFC2127";
+      }
+      enum "primaryISDN" {
+        value 21;
+      }
+      enum "propPointToPointSerial" {
+        value 22;
+        description
+          "proprietary serial";
+      }
+      enum "ppp" {
+        value 23;
+      }
+      enum "softwareLoopback" {
+        value 24;
+      }
+      enum "eon" {
+        value 25;
+        description
+          "CLNP over IP";
+      }
+      enum "ethernet3Mbit" {
+        value 26;
+      }
+      enum "nsip" {
+        value 27;
+        description
+          "XNS over IP";
+      }
+      enum "slip" {
+        value 28;
+        description
+          "generic SLIP";
+      }
+      enum "ultra" {
+        value 29;
+        description
+          "ULTRA technologies";
+      }
+      enum "ds3" {
+        value 30;
+        description
+          "DS3-MIB";
+        reference
+          "RFC 3896 - Definitions of Managed Objects for the
+                      DS3/E3 Interface Type";
+      }
+      enum "sip" {
+        value 31;
+        description
+          "SMDS, coffee";
+        reference
+          "RFC 1694 - Definitions of Managed Objects for SMDS
+                      Interfaces using SMIv2";
+      }
+      enum "frameRelay" {
+        value 32;
+        description
+          "DTE only.";
+        reference
+          "RFC 2115 - Management Information Base for Frame Relay
+                      DTEs Using SMIv2";
+      }
+      enum "rs232" {
+        value 33;
+        reference
+          "RFC 1659 - Definitions of Managed Objects for RS-232-like
+                      Hardware Devices using SMIv2";
+      }
+      enum "para" {
+        value 34;
+        description
+          "parallel-port";
+        reference
+          "RFC 1660 - Definitions of Managed Objects for
+                      Parallel-printer-like Hardware Devices using
+                      SMIv2";
+      }
+      enum "arcnet" {
+        value 35;
+        description
+          "arcnet";
+      }
+      enum "arcnetPlus" {
+        value 36;
+        description
+          "arcnet plus";
+      }
+      enum "atm" {
+        value 37;
+        description
+          "ATM cells";
+      }
+      enum "miox25" {
+        value 38;
+        reference
+          "RFC 1461 - SNMP MIB extension for Multiprotocol
+                      Interconnect over X.25";
+      }
+      enum "sonet" {
+        value 39;
+        description
+          "SONET or SDH";
+      }
+      enum "x25ple" {
+        value 40;
+        reference
+          "RFC 2127 - ISDN Management Information Base using SMIv2";
+      }
+      enum "iso88022llc" {
+        value 41;
+      }
+      enum "localTalk" {
+        value 42;
+      }
+      enum "smdsDxi" {
+        value 43;
+      }
+      enum "frameRelayService" {
+        value 44;
+        description
+          "FRNETSERV-MIB";
+        reference
+          "RFC 2954 - Definitions of Managed Objects for Frame
+                      Relay Service";
+      }
+      enum "v35" {
+        value 45;
+      }
+      enum "hssi" {
+        value 46;
+      }
+      enum "hippi" {
+        value 47;
+      }
+      enum "modem" {
+        value 48;
+        description
+          "Generic modem";
+      }
+      enum "aal5" {
+        value 49;
+        description
+          "AAL5 over ATM";
+      }
+      enum "sonetPath" {
+        value 50;
+      }
+      enum "sonetVT" {
+        value 51;
+      }
+      enum "smdsIcip" {
+        value 52;
+        description
+          "SMDS InterCarrier Interface";
+      }
+      enum "propVirtual" {
+        value 53;
+        description
+          "proprietary virtual/internal";
+        reference
+          "RFC 2863 - The Interfaces Group MIB";
+      }
+      enum "propMultiplexor" {
+        value 54;
+        description
+          "proprietary multiplexing";
+        reference
+          "RFC 2863 - The Interfaces Group MIB";
+      }
+      enum "ieee80212" {
+        value 55;
+        description
+          "100BaseVG";
+      }
+      enum "fibreChannel" {
+        value 56;
+        description
+          "Fibre Channel";
+      }
+      enum "hippiInterface" {
+        value 57;
+        description
+          "HIPPI interfaces";
+      }
+      enum "frameRelayInterconnect" {
+        value 58;
+        status obsolete;
+        description
+          "Obsolete use either
+           frameRelay(32) or frameRelayService(44).";
+      }
+      enum "aflane8023" {
+        value 59;
+        description
+          "ATM Emulated LAN for 802.3";
+      }
+      enum "aflane8025" {
+        value 60;
+        description
+          "ATM Emulated LAN for 802.5";
+      }
+      enum "cctEmul" {
+        value 61;
+        description
+         "ATM Emulated circuit";
+      }
+      enum "fastEther" {
+        value 62;
+        status deprecated;
+        description
+          "Obsoleted via RFC3635.
+          ethernetCsmacd(6) should be used instead";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "isdn" {
+        value 63;
+        description
+          "ISDN and X.25";
+        reference
+          "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN
+                      in the Packet Mode";
+      }
+      enum "v11" {
+        value 64;
+        description
+         "CCITT V.11/X.21";
+      }
+      enum "v36" {
+        value 65;
+        description
+          "CCITT V.36";
+      }
+      enum "g703at64k" {
+        value 66;
+        description
+          "CCITT G703 at 64Kbps";
+      }
+      enum "g703at2mb" {
+        value 67;
+        status obsolete;
+        description
+          "Obsolete see DS1-MIB";
+      }
+      enum "qllc" {
+        value 68;
+        description
+          "SNA QLLC";
+      }
+      enum "fastEtherFX" {
+        value 69;
+        status deprecated;
+        description
+          "Obsoleted via RFC3635
+          ethernetCsmacd(6) should be used instead";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "channel" {
+        value 70;
+        description
+          "channel";
+      }
+      enum "ieee80211" {
+        value 71;
+        description
+          "radio spread spectrum";
+      }
+      enum "ibm370parChan" {
+        value 72;
+        description
+          "IBM System 360/370 OEMI Channel";
+      }
+      enum "escon" {
+        value 73;
+        description
+          "IBM Enterprise Systems Connection";
+      }
+      enum "dlsw" {
+        value 74;
+        description
+          "Data Link Switching";
+      }
+      enum "isdns" {
+        value 75;
+        description
+          "ISDN S/T interface";
+      }
+      enum "isdnu" {
+        value 76;
+        description
+          "ISDN U interface";
+      }
+      enum "lapd" {
+        value 77;
+        description
+          "Link Access Protocol D";
+      }
+      enum "ipSwitch" {
+        value 78;
+        description
+          "IP Switching Objects";
+      }
+      enum "rsrb" {
+        value 79;
+        description
+          "Remote Source Route Bridging";
+      }
+      enum "atmLogical" {
+        value 80;
+        description
+          "ATM Logical Port";
+        reference
+          "RFC 3606 - Definitions of Supplemental Managed Objects
+                      for ATM Interface";
+      }
+      enum "ds0" {
+        value 81;
+        description
+          "Digital Signal Level 0";
+        reference
+          "RFC 2494 - Definitions of Managed Objects for the DS0
+                      and DS0 Bundle Interface Type";
+      }
+      enum "ds0Bundle" {
+        value 82;
+        description
+          "group of ds0s on the same ds1";
+        reference
+          "RFC 2494 - Definitions of Managed Objects for the DS0
+                      and DS0 Bundle Interface Type";
+      }
+      enum "bsc" {
+        value 83;
+        description
+          "Bisynchronous Protocol";
+      }
+      enum "async" {
+        value 84;
+        description
+          "Asynchronous Protocol";
+      }
+      enum "cnr" {
+        value 85;
+        description
+          "Combat Net Radio";
+      }
+      enum "iso88025Dtr" {
+        value 86;
+        description
+          "ISO 802.5r DTR";
+      }
+      enum "eplrs" {
+        value 87;
+        description
+          "Ext Pos Loc Report Sys";
+      }
+      enum "arap" {
+        value 88;
+        description
+          "Appletalk Remote Access Protocol";
+      }
+      enum "propCnls" {
+        value 89;
+        description
+          "Proprietary Connectionless Protocol";
+      }
+      enum "hostPad" {
+        value 90;
+        description
+          "CCITT-ITU X.29 PAD Protocol";
+      }
+      enum "termPad" {
+        value 91;
+        description
+          "CCITT-ITU X.3 PAD Facility";
+      }
+      enum "frameRelayMPI" {
+        value 92;
+        description
+          "Multiproto Interconnect over FR";
+      }
+      enum "x213" {
+        value 93;
+        description
+          "CCITT-ITU X213";
+      }
+      enum "adsl" {
+        value 94;
+        description
+          "Asymmetric Digital Subscriber Loop";
+      }
+      enum "radsl" {
+        value 95;
+        description
+          "Rate-Adapt. Digital Subscriber Loop";
+      }
+      enum "sdsl" {
+        value 96;
+        description
+          "Symmetric Digital Subscriber Loop";
+      }
+      enum "vdsl" {
+        value 97;
+        description
+          "Very H-Speed Digital Subscrib. Loop";
+      }
+      enum "iso88025CRFPInt" {
+        value 98;
+        description
+          "ISO 802.5 CRFP";
+      }
+      enum "myrinet" {
+        value 99;
+        description
+          "Myricom Myrinet";
+      }
+      enum "voiceEM" {
+        value 100;
+        description
+          "voice recEive and transMit";
+      }
+      enum "voiceFXO" {
+        value 101;
+        description
+          "voice Foreign Exchange Office";
+      }
+      enum "voiceFXS" {
+        value 102;
+        description
+          "voice Foreign Exchange Station";
+      }
+      enum "voiceEncap" {
+        value 103;
+        description
+          "voice encapsulation";
+      }
+      enum "voiceOverIp" {
+        value 104;
+        description
+          "voice over IP encapsulation";
+      }
+      enum "atmDxi" {
+        value 105;
+        description
+          "ATM DXI";
+      }
+      enum "atmFuni" {
+        value 106;
+        description
+          "ATM FUNI";
+      }
+      enum "atmIma" {
+        value 107;
+        description
+          "ATM IMA";
+      }
+      enum "pppMultilinkBundle" {
+        value 108;
+        description
+          "PPP Multilink Bundle";
+      }
+      enum "ipOverCdlc" {
+        value 109;
+        description
+          "IBM ipOverCdlc";
+      }
+      enum "ipOverClaw" {
+        value 110;
+        description
+          "IBM Common Link Access to Workstn";
+      }
+      enum "stackToStack" {
+        value 111;
+        description
+          "IBM stackToStack";
+      }
+      enum "virtualIpAddress" {
+        value 112;
+        description
+          "IBM VIPA";
+      }
+      enum "mpc" {
+        value 113;
+        description
+          "IBM multi-protocol channel support";
+      }
+      enum "ipOverAtm" {
+        value 114;
+        description
+          "IBM ipOverAtm";
+        reference
+          "RFC 2320 - Definitions of Managed Objects for Classical IP
+                      and ARP Over ATM Using SMIv2 (IPOA-MIB)";
+      }
+      enum "iso88025Fiber" {
+        value 115;
+        description
+          "ISO 802.5j Fiber Token Ring";
+      }
+      enum "tdlc" {
+        value 116;
+        description
+          "IBM twinaxial data link control";
+      }
+      enum "gigabitEthernet" {
+        value 117;
+        status deprecated;
+        description
+          "Obsoleted via RFC3635
+           ethernetCsmacd(6) should be used instead";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "hdlc" {
+        value 118;
+        description
+          "HDLC";
+      }
+      enum "lapf" {
+        value 119;
+        description
+          "LAP F";
+      }
+      enum "v37" {
+        value 120;
+        description
+          "V.37";
+      }
+      enum "x25mlp" {
+        value 121;
+        description
+          "Multi-Link Protocol";
+      }
+      enum "x25huntGroup" {
+        value 122;
+        description
+          "X25 Hunt Group";
+      }
+      enum "transpHdlc" {
+        value 123;
+        description
+          "Transp HDLC";
+      }
+      enum "interleave" {
+        value 124;
+        description
+          "Interleave channel";
+      }
+      enum "fast" {
+        value 125;
+        description
+          "Fast channel";
+      }
+      enum "ip" {
+        value 126;
+        description
+          "IP (for APPN HPR in IP networks)";
+      }
+      enum "docsCableMaclayer" {
+        value 127;
+        description
+          "CATV Mac Layer";
+      }
+      enum "docsCableDownstream" {
+        value 128;
+        description
+          "CATV Downstream interface";
+      }
+      enum "docsCableUpstream" {
+        value 129;
+        description
+          "CATV Upstream interface";
+      }
+      enum "a12MppSwitch" {
+        value 130;
+        description
+          "Avalon Parallel Processor";
+      }
+      enum "tunnel" {
+        value 131;
+        description
+          "Encapsulation interface";
+      }
+      enum "coffee" {
+        value 132;
+        description
+          "coffee pot";
+        reference
+          "RFC 2325 - Coffee MIB";
+      }
+      enum "ces" {
+        value 133;
+        description
+          "Circuit Emulation Service";
+      }
+      enum "atmSubInterface" {
+        value 134;
+        description
+          "ATM Sub Interface";
+      }
+      enum "l2vlan" {
+        value 135;
+        description
+          "Layer 2 Virtual LAN using 802.1Q";
+      }
+      enum "l3ipvlan" {
+        value 136;
+        description
+          "Layer 3 Virtual LAN using IP";
+      }
+      enum "l3ipxvlan" {
+        value 137;
+        description
+          "Layer 3 Virtual LAN using IPX";
+      }
+      enum "digitalPowerline" {
+        value 138;
+        description
+          "IP over Power Lines";
+      }
+      enum "mediaMailOverIp" {
+        value 139;
+        description
+          "Multimedia Mail over IP";
+      }
+      enum "dtm" {
+        value 140;
+        description
+          "Dynamic syncronous Transfer Mode";
+      }
+      enum "dcn" {
+        value 141;
+        description
+          "Data Communications Network";
+      }
+      enum "ipForward" {
+        value 142;
+        description
+          "IP Forwarding Interface";
+      }
+      enum "msdsl" {
+        value 143;
+        description
+          "Multi-rate Symmetric DSL";
+      }
+      enum "ieee1394" {
+        value 144;
+        description
+          "IEEE1394 High Performance Serial Bus";
+      }
+      enum "if-gsn" {
+        value 145;
+        description
+          "HIPPI-6400";
+      }
+      enum "dvbRccMacLayer" {
+        value 146;
+        description
+          "DVB-RCC MAC Layer";
+      }
+      enum "dvbRccDownstream" {
+        value 147;
+        description
+          "DVB-RCC Downstream Channel";
+      }
+      enum "dvbRccUpstream" {
+        value 148;
+        description
+          "DVB-RCC Upstream Channel";
+      }
+      enum "atmVirtual" {
+        value 149;
+        description
+          "ATM Virtual Interface";
+      }
+      enum "mplsTunnel" {
+        value 150;
+        description
+          "MPLS Tunnel Virtual Interface";
+      }
+      enum "srp" {
+        value 151;
+        description
+          "Spatial Reuse Protocol       ";
+      }
+      enum "voiceOverAtm" {
+        value 152;
+        description
+          "Voice Over ATM";
+      }
+      enum "voiceOverFrameRelay" {
+        value 153;
+        description
+          "Voice Over Frame Relay";
+      }
+      enum "idsl" {
+        value 154;
+        description
+          "Digital Subscriber Loop over ISDN";
+      }
+      enum "compositeLink" {
+        value 155;
+        description
+          "Avici Composite Link Interface";
+      }
+      enum "ss7SigLink" {
+        value 156;
+        description
+          "SS7 Signaling Link";
+      }
+      enum "propWirelessP2P" {
+        value 157;
+        description
+          "Prop. P2P wireless interface";
+      }
+      enum "frForward" {
+        value 158;
+        description
+          "Frame Forward Interface";
+      }
+      enum "rfc1483" {
+        value 159;
+        description
+          "Multiprotocol over ATM AAL5";
+        reference
+          "RFC 1483 - Multiprotocol Encapsulation over ATM
+                      Adaptation Layer 5";
+      }
+      enum "usb" {
+        value 160;
+        description
+          "USB Interface";
+      }
+      enum "ieee8023adLag" {
+        value 161;
+        description
+          "IEEE 802.3ad Link Aggregate";
+      }
+      enum "bgppolicyaccounting" {
+        value 162;
+        description
+          "BGP Policy Accounting";
+      }
+      enum "frf16MfrBundle" {
+        value 163;
+        description
+          "FRF .16 Multilink Frame Relay";
+      }
+      enum "h323Gatekeeper" {
+        value 164;
+        description
+          "H323 Gatekeeper";
+      }
+      enum "h323Proxy" {
+        value 165;
+        description
+          "H323 Voice and Video Proxy";
+      }
+      enum "mpls" {
+        value 166;
+        description
+          "MPLS";
+      }
+      enum "mfSigLink" {
+        value 167;
+        description
+          "Multi-frequency signaling link";
+      }
+      enum "hdsl2" {
+        value 168;
+        description
+          "High Bit-Rate DSL - 2nd generation";
+      }
+      enum "shdsl" {
+        value 169;
+        description
+          "Multirate HDSL2";
+      }
+      enum "ds1FDL" {
+        value 170;
+        description
+          "Facility Data Link 4Kbps on a DS1";
+      }
+      enum "pos" {
+        value 171;
+        description
+          "Packet over SONET/SDH Interface";
+      }
+      enum "dvbAsiIn" {
+        value 172;
+        description
+          "DVB-ASI Input";
+      }
+      enum "dvbAsiOut" {
+        value 173;
+        description
+          "DVB-ASI Output";
+      }
+      enum "plc" {
+        value 174;
+        description
+          "Power Line Communtications";
+      }
+      enum "nfas" {
+        value 175;
+        description
+          "Non Facility Associated Signaling";
+      }
+      enum "tr008" {
+        value 176;
+        description
+          "TR008";
+      }
+      enum "gr303RDT" {
+        value 177;
+        description
+          "Remote Digital Terminal";
+      }
+      enum "gr303IDT" {
+        value 178;
+        description
+          "Integrated Digital Terminal";
+      }
+      enum "isup" {
+        value 179;
+        description
+          "ISUP";
+      }
+      enum "propDocsWirelessMaclayer" {
+        value 180;
+        description
+          "Cisco proprietary Maclayer";
+      }
+      enum "propDocsWirelessDownstream" {
+        value 181;
+        description
+          "Cisco proprietary Downstream";
+      }
+      enum "propDocsWirelessUpstream" {
+        value 182;
+        description
+          "Cisco proprietary Upstream";
+      }
+      enum "hiperlan2" {
+        value 183;
+        description
+          "HIPERLAN Type 2 Radio Interface";
+      }
+      enum "propBWAp2Mp" {
+        value 184;
+        description
+          "PropBroadbandWirelessAccesspt2multipt use of this value
+           for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f
+           is deprecated and ieee80216WMAN(237) should be used
+           instead.";
+      }
+      enum "sonetOverheadChannel" {
+        value 185;
+        description
+          "SONET Overhead Channel";
+      }
+      enum "digitalWrapperOverheadChannel" {
+        value 186;
+        description
+          "Digital Wrapper";
+      }
+      enum "aal2" {
+        value 187;
+        description
+          "ATM adaptation layer 2";
+      }
+      enum "radioMAC" {
+        value 188;
+        description
+          "MAC layer over radio links";
+      }
+      enum "atmRadio" {
+        value 189;
+        description
+          "ATM over radio links";
+      }
+      enum "imt" {
+        value 190;
+        description
+          "Inter Machine Trunks";
+      }
+      enum "mvl" {
+        value 191;
+        description
+          "Multiple Virtual Lines DSL";
+      }
+      enum "reachDSL" {
+        value 192;
+        description
+          "Long Reach DSL";
+      }
+      enum "frDlciEndPt" {
+        value 193;
+        description
+          "Frame Relay DLCI End Point";
+      }
+      enum "atmVciEndPt" {
+        value 194;
+        description
+          "ATM VCI End Point";
+      }
+      enum "opticalChannel" {
+        value 195;
+        description
+          "Optical Channel";
+      }
+      enum "opticalTransport" {
+        value 196;
+        description
+          "Optical Transport";
+      }
+      enum "propAtm" {
+        value 197;
+        description
+          "Proprietary ATM";
+      }
+      enum "voiceOverCable" {
+        value 198;
+        description
+          "Voice Over Cable Interface";
+      }
+      enum "infiniband" {
+        value 199;
+        description
+          "Infiniband";
+      }
+      enum "teLink" {
+        value 200;
+        description
+          "TE Link";
+      }
+      enum "q2931" {
+        value 201;
+        description
+          "Q.2931";
+      }
+      enum "virtualTg" {
+        value 202;
+        description
+          "Virtual Trunk Group";
+      }
+      enum "sipTg" {
+        value 203;
+        description
+          "SIP Trunk Group";
+      }
+      enum "sipSig" {
+        value 204;
+        description
+          "SIP Signaling";
+      }
+      enum "docsCableUpstreamChannel" {
+        value 205;
+        description
+          "CATV Upstream Channel";
+      }
+      enum "econet" {
+        value 206;
+        description
+          "Acorn Econet";
+      }
+      enum "pon155" {
+        value 207;
+        description
+          "FSAN 155Mb Symetrical PON interface";
+      }
+      enum "pon622" {
+        value 208;
+        description
+          "FSAN622Mb Symetrical PON interface";
+      }
+      enum "bridge" {
+        value 209;
+        description
+          "Transparent bridge interface";
+      }
+      enum "linegroup" {
+        value 210;
+        description
+          "Interface common to multiple lines";
+      }
+      enum "voiceEMFGD" {
+        value 211;
+        description
+          "voice E&M Feature Group D";
+      }
+      enum "voiceFGDEANA" {
+        value 212;
+        description
+          "voice FGD Exchange Access North American";
+      }
+      enum "voiceDID" {
+        value 213;
+        description
+          "voice Direct Inward Dialing";
+      }
+      enum "mpegTransport" {
+        value 214;
+        description
+          "MPEG transport interface";
+      }
+      enum "sixToFour" {
+        value 215;
+        status deprecated;
+        description
+          "6to4 interface (DEPRECATED)";
+        reference
+          "RFC 4087 - IP Tunnel MIB";
+      }
+      enum "gtp" {
+        value 216;
+        description
+          "GTP (GPRS Tunneling Protocol)";
+      }
+      enum "pdnEtherLoop1" {
+        value 217;
+        description
+          "Paradyne EtherLoop 1";
+      }
+      enum "pdnEtherLoop2" {
+        value 218;
+        description
+          "Paradyne EtherLoop 2";
+      }
+      enum "opticalChannelGroup" {
+        value 219;
+        description
+          "Optical Channel Group";
+      }
+      enum "homepna" {
+        value 220;
+        description
+          "HomePNA ITU-T G.989";
+      }
+      enum "gfp" {
+        value 221;
+        description
+          "Generic Framing Procedure (GFP)";
+      }
+      enum "ciscoISLvlan" {
+        value 222;
+        description
+          "Layer 2 Virtual LAN using Cisco ISL";
+      }
+      enum "actelisMetaLOOP" {
+        value 223;
+        description
+          "Acteleis proprietary MetaLOOP High Speed Link";
+      }
+      enum "fcipLink" {
+        value 224;
+        description
+          "FCIP Link";
+      }
+      enum "rpr" {
+        value 225;
+        description
+          "Resilient Packet Ring Interface Type";
+      }
+      enum "qam" {
+        value 226;
+        description
+          "RF Qam Interface";
+      }
+      enum "lmp" {
+        value 227;
+        description
+          "Link Management Protocol";
+        reference
+          "RFC 4327 - Link Management Protocol (LMP) Management
+                      Information Base (MIB)";
+      }
+      enum "cblVectaStar" {
+        value 228;
+        description
+          "Cambridge Broadband Networks Limited VectaStar";
+      }
+      enum "docsCableMCmtsDownstream" {
+        value 229;
+        description
+          "CATV Modular CMTS Downstream Interface";
+      }
+      enum "adsl2" {
+        value 230;
+        status deprecated;
+        description
+          "Asymmetric Digital Subscriber Loop Version 2
+           (DEPRECATED/OBSOLETED - please use adsl2plus(238)
+           instead)";
+        reference
+          "RFC 4706 - Definitions of Managed Objects for Asymmetric
+                      Digital Subscriber Line 2 (ADSL2)";
+      }
+      enum "macSecControlledIF" {
+        value 231;
+        description
+          "MACSecControlled";
+      }
+      enum "macSecUncontrolledIF" {
+        value 232;
+        description
+          "MACSecUncontrolled";
+      }
+      enum "aviciOpticalEther" {
+        value 233;
+        description
+         "Avici Optical Ethernet Aggregate";
+      }
+      enum "atmbond" {
+        value 234;
+        description
+          "atmbond";
+      }
+      enum "voiceFGDOS" {
+        value 235;
+        description
+          "voice FGD Operator Services";
+      }
+      enum "mocaVersion1" {
+        value 236;
+        description
+          "MultiMedia over Coax Alliance (MoCA) Interface
+           as documented in information provided privately to IANA";
+      }
+      enum "ieee80216WMAN" {
+        value 237;
+        description
+          "IEEE 802.16 WMAN interface";
+      }
+      enum "adsl2plus" {
+        value 238;
+        description
+          "Asymmetric Digital Subscriber Loop Version 2,
+           Version 2 Plus and all variants";
+      }
+      enum "dvbRcsMacLayer" {
+        value 239;
+        description
+          "DVB-RCS MAC Layer";
+        reference
+          "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+      }
+      enum "dvbTdm" {
+        value 240;
+        description
+          "DVB Satellite TDM";
+        reference
+          "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+      }
+      enum "dvbRcsTdma" {
+        value 241;
+        description
+          "DVB-RCS TDMA";
+        reference
+          "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+      }
+      enum "x86Laps" {
+        value 242;
+        description
+          "LAPS based on ITU-T X.86/Y.1323";
+      }
+      enum "wwanPP" {
+        value 243;
+        description
+          "3GPP WWAN";
+      }
+      enum "wwanPP2" {
+        value 244;
+        description
+          "3GPP2 WWAN";
+      }
+      enum "voiceEBS" {
+        value 245;
+        description
+          "voice P-phone EBS physical interface";
+      }
+      enum "ifPwType" {
+        value 246;
+        description
+          "Pseudowire interface type";
+        reference
+          "RFC 5601 - Pseudowire (PW) Management Information Base";
+      }
+      enum "ilan" {
+        value 247;
+        description
+          "Internal LAN on a bridge per IEEE 802.1ap";
+      }
+      enum "pip" {
+        value 248;
+        description
+          "Provider Instance Port on a bridge per IEEE 802.1ah PBB";
+      }
+      enum "aluELP" {
+        value 249;
+        description
+          "Alcatel-Lucent Ethernet Link Protection";
+      }
+      enum "gpon" {
+        value 250;
+        description
+          "Gigabit-capable passive optical networks (G-PON) as per
+           ITU-T G.948";
+      }
+      enum "vdsl2" {
+        value 251;
+        description
+          "Very high speed digital subscriber line Version 2
+           (as per ITU-T Recommendation G.993.2)";
+        reference
+          "RFC 5650 - Definitions of Managed Objects for Very High
+                      Speed Digital Subscriber Line 2 (VDSL2)";
+      }
+      enum "capwapDot11Profile" {
+        value 252;
+        description
+          "WLAN Profile Interface";
+        reference
+          "RFC 5834 - Control and Provisioning of Wireless Access
+                      Points (CAPWAP) Protocol Binding MIB for
+                      IEEE 802.11";
+      }
+      enum "capwapDot11Bss" {
+        value 253;
+        description
+          "WLAN BSS Interface";
+        reference
+          "RFC 5834 - Control and Provisioning of Wireless Access
+                      Points (CAPWAP) Protocol Binding MIB for
+                      IEEE 802.11";
+      }
+      enum "capwapWtpVirtualRadio" {
+        value 254;
+        description
+          "WTP Virtual Radio Interface";
+        reference
+          "RFC 5833 - Control and Provisioning of Wireless Access
+                      Points (CAPWAP) Protocol Base MIB";
+      }
+      enum "bits" {
+        value 255;
+        description
+          "bitsport";
+      }
+      enum "docsCableUpstreamRfPort" {
+        value 256;
+        description
+          "DOCSIS CATV Upstream RF Port";
+      }
+      enum "cableDownstreamRfPort" {
+        value 257;
+        description
+          "CATV downstream RF port";
+      }
+      enum "vmwareVirtualNic" {
+        value 258;
+        description
+          "VMware Virtual Network Interface";
+      }
+      enum "ieee802154" {
+        value 259;
+        description
+          "IEEE 802.15.4 WPAN interface";
+        reference
+          "IEEE 802.15.4-2006";
+      }
+      enum "otnOdu" {
+        value 260;
+        description
+          "OTN Optical Data Unit";
+      }
+      enum "otnOtu" {
+        value 261;
+        description
+          "OTN Optical channel Transport Unit";
+      }
+      enum "ifVfiType" {
+        value 262;
+        description
+          "VPLS Forwarding Instance Interface Type";
+      }
+      enum "g9981" {
+        value 263;
+        description
+          "G.998.1 bonded interface";
+      }
+      enum "g9982" {
+        value 264;
+        description
+          "G.998.2 bonded interface";
+      }
+      enum "g9983" {
+        value 265;
+        description
+          "G.998.3 bonded interface";
+      }
+      enum "aluEpon" {
+        value 266;
+        description
+          "Ethernet Passive Optical Networks (E-PON)";
+      }
+      enum "aluEponOnu" {
+        value 267;
+        description
+          "EPON Optical Network Unit";
+      }
+      enum "aluEponPhysicalUni" {
+        value 268;
+        description
+          "EPON physical User to Network interface";
+      }
+      enum "aluEponLogicalLink" {
+        value 269;
+        description
+          "The emulation of a point-to-point link over the EPON
+           layer";
+      }
+      enum "aluGponOnu" {
+        value 270;
+        description
+          "GPON Optical Network Unit";
+        reference
+          "ITU-T G.984.2";
+      }
+      enum "aluGponPhysicalUni" {
+        value 271;
+        description
+          "GPON physical User to Network interface";
+        reference
+          "ITU-T G.984.2";
+      }
+      enum "vmwareNicTeam" {
+        value 272;
+        description
+          "VMware NIC Team";
+      }
+    }
+    description
+      "This data type is used as the syntax of the 'type'
+       leaf in the 'interface' list in the YANG module
+       ietf-interface.
+
+       The definition of this typedef with the
+       addition of newly assigned values is published
+       periodically by the IANA, in either the Assigned
+       Numbers RFC, or some derivative of it specific to
+       Internet Network Management number assignments.  (The
+       latest arrangements can be obtained by contacting the
+       IANA.)
+
+       Requests for new values should be made to IANA via
+       email (iana&iana.org).";
+    reference
+      "ifType definitions registry.
+       <http://www.iana.org/assignments/smi-numbers>";
+  }
+}
\ No newline at end of file
diff --git a/code-generator/binding-java-api-generator/src/test/resources/yang/ietf-inet-types@2010-09-24.yang b/code-generator/binding-java-api-generator/src/test/resources/yang/ietf-inet-types@2010-09-24.yang
new file mode 100644 (file)
index 0000000..6a6c748
--- /dev/null
@@ -0,0 +1,418 @@
+ module ietf-inet-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+   prefix "inet";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types for Internet addresses and related things.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of protocol field related types ***/
+
+   typedef ip-version {
+     type enumeration {
+       enum unknown {
+         value "0";
+         description
+          "An unknown or unspecified version of the Internet protocol.";
+       }
+       enum ipv4 {
+         value "1";
+         description
+          "The IPv4 protocol as defined in RFC 791.";
+       }
+       enum ipv6 {
+         value "2";
+         description
+          "The IPv6 protocol as defined in RFC 2460.";
+       }
+     }
+     description
+      "This value represents the version of the IP protocol.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetVersion textual convention of the SMIv2.";
+     reference
+      "RFC  791: Internet Protocol
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   typedef dscp {
+     type uint8 {
+       range "0..63";
+     }
+     description
+      "The dscp type represents a Differentiated Services Code-Point
+       that may be used for marking packets in a traffic stream.
+
+       In the value set and its semantics, this type is equivalent
+       to the Dscp textual convention of the SMIv2.";
+     reference
+      "RFC 3289: Management Information Base for the Differentiated
+                 Services Architecture
+       RFC 2474: Definition of the Differentiated Services Field
+                 (DS Field) in the IPv4 and IPv6 Headers
+       RFC 2780: IANA Allocation Guidelines For Values In
+                 the Internet Protocol and Related Headers";
+   }
+
+   typedef ipv6-flow-label {
+     type uint32 {
+       range "0..1048575";
+     }
+     description
+      "The flow-label type represents flow identifier or Flow Label
+       in an IPv6 packet header that may be used to discriminate
+       traffic flows.
+
+       In the value set and its semantics, this type is equivalent
+       to the IPv6FlowLabel textual convention of the SMIv2.";
+     reference
+      "RFC 3595: Textual Conventions for IPv6 Flow Label
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+   }
+
+   typedef port-number {
+     type uint16 {
+       range "0..65535";
+     }
+     description
+      "The port-number type represents a 16-bit port number of an
+       Internet transport layer protocol such as UDP, TCP, DCCP, or
+       SCTP.  Port numbers are assigned by IANA.  A current list of
+       all assignments is available from <http://www.iana.org/>.
+
+       Note that the port number value zero is reserved by IANA.  In
+       situations where the value zero does not make sense, it can
+       be excluded by subtyping the port-number type.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetPortNumber textual convention of the SMIv2.";
+     reference
+      "RFC  768: User Datagram Protocol
+       RFC  793: Transmission Control Protocol
+       RFC 4960: Stream Control Transmission Protocol
+       RFC 4340: Datagram Congestion Control Protocol (DCCP)
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of autonomous system related types ***/
+
+   typedef as-number {
+     type uint32;
+     description
+      "The as-number type represents autonomous system numbers
+       which identify an Autonomous System (AS).  An AS is a set
+       of routers under a single technical administration, using
+       an interior gateway protocol and common metrics to route
+       packets within the AS, and using an exterior gateway
+       protocol to route packets to other ASs'.  IANA maintains
+       the AS number space and has delegated large parts to the
+       regional registries.
+
+       Autonomous system numbers were originally limited to 16
+       bits.  BGP extensions have enlarged the autonomous system
+       number space to 32 bits.  This type therefore uses an uint32
+       base type without a range restriction in order to support
+       a larger autonomous system number space.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetAutonomousSystemNumber textual convention of
+       the SMIv2.";
+     reference
+      "RFC 1930: Guidelines for creation, selection, and registration
+                 of an Autonomous System (AS)
+       RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+       RFC 4893: BGP Support for Four-octet AS Number Space
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of IP address and hostname related types ***/
+
+   typedef ip-address {
+     type union {
+       type inet:ipv4-address;
+       type inet:ipv6-address;
+     }
+     description
+      "The ip-address type represents an IP address and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-address {
+     type string {
+       pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '(%[\p{N}\p{L}]+)?';
+     }
+     description
+       "The ipv4-address type represents an IPv4 address in
+        dotted-quad notation.  The IPv4 address may include a zone
+        index, separated by a % sign.
+
+        The zone index is used to disambiguate identical address
+        values.  For link-local addresses, the zone index will
+        typically be the interface index number or the name of an
+        interface.  If the zone index is not present, the default
+        zone of the device will be used.
+
+        The canonical format for the zone index is the numerical
+        format";
+   }
+
+   typedef ipv6-address {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(%[\p{N}\p{L}]+)?';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(%.+)?';
+     }
+     description
+      "The ipv6-address type represents an IPv6 address in full,
+       mixed, shortened, and shortened-mixed notation.  The IPv6
+       address may include a zone index, separated by a % sign.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format of IPv6 addresses uses the compressed
+       format described in RFC 4291, Section 2.2, item 2 with the
+       following additional rules: the :: substitution must be
+       applied to the longest sequence of all-zero 16-bit chunks
+       in an IPv6 address.  If there is a tie, the first sequence
+       of all-zero 16-bit chunks is replaced by ::.  Single
+       all-zero 16-bit chunks are not compressed.  The canonical
+       format uses lowercase characters and leading zeros are
+       not allowed.  The canonical format for the zone index is
+       the numerical format as described in RFC 4007, Section
+       11.2.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture
+       RFC 4007: IPv6 Scoped Address Architecture
+       RFC 5952: A Recommendation for IPv6 Address Text Representation";
+   }
+
+   typedef ip-prefix {
+     type union {
+       type inet:ipv4-prefix;
+       type inet:ipv6-prefix;
+     }
+     description
+      "The ip-prefix type represents an IP prefix and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-prefix {
+     type string {
+       pattern
+          '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+        +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+        + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+     }
+     description
+      "The ipv4-prefix type represents an IPv4 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal to 32.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The canonical format of an IPv4 prefix has all bits of
+       the IPv4 address set to zero that are not part of the
+       IPv4 prefix.";
+   }
+
+   typedef ipv6-prefix {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(/.+)';
+     }
+     description
+      "The ipv6-prefix type represents an IPv6 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal 128.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The IPv6 address should have all bits that do not belong
+       to the prefix set to zero.
+
+       The canonical format of an IPv6 prefix has all bits of
+       the IPv6 address set to zero that are not part of the
+       IPv6 prefix.  Furthermore, IPv6 address is represented
+       in the compressed format described in RFC 4291, Section
+       2.2, item 2 with the following additional rules: the ::
+       substitution must be applied to the longest sequence of
+       all-zero 16-bit chunks in an IPv6 address.  If there is
+       a tie, the first sequence of all-zero 16-bit chunks is
+       replaced by ::.  Single all-zero 16-bit chunks are not
+       compressed.  The canonical format uses lowercase
+       characters and leading zeros are not allowed.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture";
+   }
+
+   /*** collection of domain name and URI types ***/
+
+   typedef domain-name {
+     type string {
+       pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+            +  '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+            +  '|\.';
+       length "1..253";
+     }
+     description
+      "The domain-name type represents a DNS domain name.  The
+       name SHOULD be fully qualified whenever possible.
+
+       Internet domain names are only loosely specified.  Section
+       3.5 of RFC 1034 recommends a syntax (modified in Section
+       2.1 of RFC 1123).  The pattern above is intended to allow
+       for current practice in domain name use, and some possible
+       future expansion.  It is designed to hold various types of
+       domain names, including names used for A or AAAA records
+       (host names) and other records, such as SRV records.  Note
+       that Internet host names have a stricter syntax (described
+       in RFC 952) than the DNS recommendations in RFCs 1034 and
+       1123, and that systems that want to store host names in
+       schema nodes using the domain-name type are recommended to
+       adhere to this stricter standard to ensure interoperability.
+
+       The encoding of DNS names in the DNS protocol is limited
+       to 255 characters.  Since the encoding consists of labels
+       prefixed by a length bytes and there is a trailing NULL
+       byte, only 253 characters can appear in the textual dotted
+       notation.
+
+       The description clause of schema nodes using the domain-name
+       type MUST describe when and how these names are resolved to
+       IP addresses.  Note that the resolution of a domain-name value
+       may require to query multiple DNS records (e.g., A for IPv4
+       and AAAA for IPv6).  The order of the resolution process and
+       which DNS record takes precedence can either be defined
+       explicitely or it may depend on the configuration of the
+       resolver.
+
+       Domain-name values use the US-ASCII encoding.  Their canonical
+       format uses lowercase US-ASCII characters.  Internationalized
+       domain names MUST be encoded in punycode as described in RFC
+       3492";
+     reference
+      "RFC  952: DoD Internet Host Table Specification
+       RFC 1034: Domain Names - Concepts and Facilities
+       RFC 1123: Requirements for Internet Hosts -- Application
+                 and Support
+       RFC 2782: A DNS RR for specifying the location of services
+                 (DNS SRV)
+       RFC 3492: Punycode: A Bootstring encoding of Unicode for
+                 Internationalized Domain Names in Applications
+                 (IDNA)
+       RFC 5891: Internationalizing Domain Names in Applications
+                 (IDNA): Protocol";
+   }
+
+   typedef host {
+     type union {
+       type inet:ip-address;
+       type inet:domain-name;
+     }
+     description
+      "The host type represents either an IP address or a DNS
+       domain name.";
+   }
+
+   typedef uri {
+     type string;
+     description
+      "The uri type represents a Uniform Resource Identifier
+       (URI) as defined by STD 66.
+
+       Objects using the uri type MUST be in US-ASCII encoding,
+       and MUST be normalized as described by RFC 3986 Sections
+       6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+       percent-encoding is removed, and all case-insensitive
+       characters are set to lowercase except for hexadecimal
+       digits, which are normalized to uppercase as described in
+       Section 6.2.2.1.
+
+       The purpose of this normalization is to help provide
+       unique URIs.  Note that this normalization is not
+       sufficient to provide uniqueness.  Two URIs that are
+       textually distinct after this normalization may still be
+       equivalent.
+
+       Objects using the uri type may restrict the schemes that
+       they permit.  For example, 'data:' and 'urn:' schemes
+       might not be appropriate.
+
+       A zero-length URI is not a valid URI.  This can be used to
+       express 'URI absent' where required.
+
+       In the value set and its semantics, this type is equivalent
+       to the Uri SMIv2 textual convention defined in RFC 5017.";
+     reference
+      "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+       RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                 Group: Uniform Resource Identifiers (URIs), URLs,
+                 and Uniform Resource Names (URNs): Clarifications
+                 and Recommendations
+       RFC 5017: MIB Textual Conventions for Uniform Resource
+                 Identifiers (URIs)";
+   }
+
+ }
\ No newline at end of file
diff --git a/code-generator/binding-java-api-generator/src/test/resources/yang/ietf-interfaces@2012-11-15.yang b/code-generator/binding-java-api-generator/src/test/resources/yang/ietf-interfaces@2012-11-15.yang
new file mode 100644 (file)
index 0000000..481a5d2
--- /dev/null
@@ -0,0 +1,469 @@
+module ietf-interfaces {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+  prefix if;
+
+  import ietf-yang-types {
+    prefix yang;
+    revision-date 2010-09-24;
+  }
+
+  organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+  contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     WG Chair: Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>
+
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+
+  description
+    "This module contains a collection of YANG definitions for
+     managing network interfaces.
+
+     Copyright (c) 2012 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see
+     the RFC itself for full legal notices.";
+
+  // RFC Ed.: replace XXXX with actual RFC number and remove this
+  // note.
+
+  // RFC Ed.: update the date below with the date of RFC publication
+  // and remove this note.
+  revision 2012-11-15 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: A YANG Data Model for Interface Management";
+  }
+
+  /* Typedefs */
+
+  typedef interface-ref {
+    type leafref {
+      path "/if:interfaces/if:interface/if:name";
+    }
+    description
+      "This type is used by data models that need to reference
+       interfaces.";
+  }
+
+  /* Features */
+
+  feature arbitrary-names {
+    description
+      "This feature indicates that the server allows interfaces to
+       be named arbitrarily.";
+  }
+
+  feature if-mib {
+    description
+      "This feature indicates that the server implements IF-MIB.";
+    reference
+      "RFC 2863: The Interfaces Group MIB";
+  }
+
+  /* Data nodes */
+
+  container interfaces {
+    description
+      "Interface parameters.";
+
+    list interface {
+      key "name";
+      unique "type location";
+
+      description
+        "The list of interfaces on the device.";
+
+      leaf name {
+        type string;
+        description
+          "The name of the interface.
+
+           A device MAY restrict the allowed values for this leaf,
+           possibly depending on the type and location.
+
+           If the device allows arbitrarily named interfaces, the
+           feature 'arbitrary-names' is advertised.
+
+           This leaf MAY be mapped to ifName by an implementation.
+           Such an implementation MAY restrict the allowed values for
+           this leaf so that it matches the restrictions of ifName.
+           If a NETCONF server that implements this restriction is
+           sent a value that doesn't match the restriction, it MUST
+           reply with an rpc-error with the error-tag
+           'invalid-value'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifName";
+      }
+
+      leaf description {
+        type string;
+        description
+          "A textual description of the interface.
+
+           This leaf MAY be mapped to ifAlias by an implementation.
+           Such an implementation MAY restrict the allowed values for
+           this leaf so that it matches the restrictions of ifAlias.
+           If a NETCONF server that implements this restriction is
+           sent a value that doesn't match the restriction, it MUST
+           reply with an rpc-error with the error-tag
+           'invalid-value'.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifAlias";
+      }
+
+      leaf location {
+        type string;
+        description
+          "The device-specific location of the interface of a
+           particular type.  The format of the location string
+           depends on the interface type and the device.
+
+           If the interface's type represents a physical interface,
+           this leaf MUST be set.
+
+           When an interface entry is created, a server MAY
+           initialize the location leaf with a valid value, e.g., if
+           it is possible to derive the location from the name of
+           the interface.";
+      }
+
+      leaf enabled {
+        type boolean;
+        default "true";
+        description
+          "The desired state of the interface.
+
+           This leaf contains the configured, desired state of the
+           interface.  Systems that implement the IF-MIB use the
+           value of this leaf to set IF-MIB.ifAdminStatus to 'up' or
+           'down' after an ifEntry has been initialized, as described
+           in RFC 2863.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+      }
+
+      leaf last-change {
+        type yang:date-and-time;
+        config false;
+        description
+          "The time the interface entered its current operational
+           state.  If the current state was entered prior to the
+           last re-initialization of the local network management
+           subsystem, then this node is not present.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifLastChange";
+      }
+
+      leaf if-index {
+        if-feature if-mib;
+        type int32 {
+          range "1..2147483647";
+        }
+        config false;
+        description
+          "The ifIndex value for the ifEntry represented by this
+           interface.
+
+           Media-specific modules must specify how the type is
+           mapped to entries in the ifTable.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifIndex";
+      }
+
+      leaf phys-address {
+        type yang:phys-address;
+        config false;
+        description
+          "The interface's address at its protocol sub-layer.  For
+          example, for an 802.x interface, this object normally
+          contains a MAC address.  The interface's media-specific
+          modules must define the bit and byte ordering and the
+          format of the value of this object.  For interfaces that do
+          not have such an address (e.g., a serial line), this node
+          is not present.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifPhysAddress";
+      }
+
+      leaf-list higher-layer-if {
+        type interface-ref;
+        config false;
+        description
+          "A list of references to interfaces layered on top of this
+           interface.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifStackTable";
+      }
+
+      leaf-list lower-layer-if {
+        type interface-ref;
+        config false;
+        description
+          "A list of references to interfaces layered underneath this
+           interface.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifStackTable";
+      }
+
+      leaf speed {
+        type yang:gauge64;
+        units "bits / second";
+        config false;
+        description
+            "An estimate of the interface's current bandwidth in bits
+             per second.  For interfaces which do not vary in
+             bandwidth or for those where no accurate estimation can
+             be made, this node should contain the nominal bandwidth.
+             For interfaces that has no concept of bandwidth, this
+             node is not present.";
+        reference
+          "RFC 2863: The Interfaces Group MIB -
+                     ifSpeed, ifHighSpeed";
+      }
+
+      container statistics {
+        config false;
+        description
+          "A collection of interface-related statistics objects.";
+
+        leaf discontinuity-time {
+          type yang:date-and-time;
+          description
+            "The time on the most recent occasion at which any one or
+             more of this interface's counters suffered a
+             discontinuity.  If no such discontinuities have occurred
+             since the last re-initialization of the local management
+             subsystem, then this node contains the time the local
+             management subsystem re-initialized itself.";
+        }
+
+        leaf in-octets {
+          type yang:counter64;
+          description
+            "The total number of octets received on the interface,
+             including framing characters.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
+        }
+        leaf in-unicast-pkts {
+          type yang:counter64;
+          description
+            "The number of packets, delivered by this sub-layer to a
+             higher (sub-)layer, which were not addressed to a
+             multicast or broadcast address at this sub-layer.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
+        }
+        leaf in-broadcast-pkts {
+          type yang:counter64;
+          description
+            "The number of packets, delivered by this sub-layer to a
+             higher (sub-)layer, which were addressed to a broadcast
+             address at this sub-layer.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCInBroadcastPkts";
+        }
+        leaf in-multicast-pkts {
+          type yang:counter64;
+          description
+            "The number of packets, delivered by this sub-layer to a
+             higher (sub-)layer, which were addressed to a multicast
+             address at this sub-layer.  For a MAC layer protocol,
+             this includes both Group and Functional addresses.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCInMulticastPkts";
+        }
+        leaf in-discards {
+          type yang:counter32;
+          description
+            "The number of inbound packets which were chosen to be
+             discarded even though no errors had been detected to
+             prevent their being deliverable to a higher-layer
+             protocol.  One possible reason for discarding such a
+             packet could be to free up buffer space.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifInDiscards";
+        }
+        leaf in-errors {
+          type yang:counter32;
+          description
+            "For packet-oriented interfaces, the number of inbound
+             packets that contained errors preventing them from being
+             deliverable to a higher-layer protocol.  For character-
+             oriented or fixed-length interfaces, the number of
+             inbound transmission units that contained errors
+             preventing them from being deliverable to a higher-layer
+             protocol.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifInErrors";
+        }
+        leaf in-unknown-protos {
+          type yang:counter32;
+          description
+            "For packet-oriented interfaces, the number of packets
+             received via the interface which were discarded because
+             of an unknown or unsupported protocol.  For
+             character-oriented or fixed-length interfaces that
+             support protocol multiplexing the number of transmission
+             units received via the interface which were discarded
+             because of an unknown or unsupported protocol.  For any
+             interface that does not support protocol multiplexing,
+             this counter is not present.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
+        }
+
+        leaf out-octets {
+          type yang:counter64;
+          description
+            "The total number of octets transmitted out of the
+             interface, including framing characters.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
+        }
+        leaf out-unicast-pkts {
+          type yang:counter64;
+          description
+            "The total number of packets that higher-level protocols
+             requested be transmitted, and which were not addressed
+             to a multicast or broadcast address at this sub-layer,
+             including those that were discarded or not sent.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
+        }
+        leaf out-broadcast-pkts {
+          type yang:counter64;
+          description
+            "The total number of packets that higher-level protocols
+             requested be transmitted, and which were addressed to a
+             broadcast address at this sub-layer, including those
+             that were discarded or not sent.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCOutBroadcastPkts";
+        }
+        leaf out-multicast-pkts {
+          type yang:counter64;
+          description
+            "The total number of packets that higher-level protocols
+             requested be transmitted, and which were addressed to a
+             multicast address at this sub-layer, including those
+             that were discarded or not sent.  For a MAC layer
+             protocol, this includes both Group and Functional
+             addresses.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCOutMulticastPkts";
+        }
+        leaf out-discards {
+          type yang:counter32;
+          description
+            "The number of outbound packets which were chosen to be
+             discarded even though no errors had been detected to
+             prevent their being transmitted.  One possible reason
+             for discarding such a packet could be to free up buffer
+             space.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
+        }
+        leaf out-errors {
+          type yang:counter32;
+          description
+            "For packet-oriented interfaces, the number of outbound
+             packets that could not be transmitted because of errors.
+             For character-oriented or fixed-length interfaces, the
+             number of outbound transmission units that could not be
+             transmitted because of errors.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifOutErrors";
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/code-generator/binding-java-api-generator/src/test/resources/yang/ietf-yang-types@2010-09-24.yang b/code-generator/binding-java-api-generator/src/test/resources/yang/ietf-yang-types@2010-09-24.yang
new file mode 100644 (file)
index 0000000..e9d88ab
--- /dev/null
@@ -0,0 +1,396 @@
+ module ietf-yang-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types";
+   prefix "yang";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of counter and gauge types ***/
+
+   typedef counter32 {
+     type uint32;
+     description
+      "The counter32 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter32 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter32 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter32.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter32 {
+     type yang:counter32;
+     default "0";
+     description
+      "The zero-based-counter32 type represents a counter32
+       that has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter32 textual convention of the SMIv2.";
+     reference
+       "RFC 4502: Remote Network Monitoring Management Information
+                  Base Version 2";
+   }
+
+   typedef counter64 {
+     type uint64;
+     description
+      "The counter64 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter64 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter64 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter64.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter64 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter64 {
+     type yang:counter64;
+     default "0";
+     description
+      "The zero-based-counter64 type represents a counter64 that
+       has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter64 textual convention of the SMIv2.";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   typedef gauge32 {
+     type uint32;
+     description
+      "The gauge32 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^32-1 (4294967295 decimal), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge32 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge32 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the Gauge32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef gauge64 {
+     type uint64;
+     description
+      "The gauge64 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^64-1 (18446744073709551615), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge64 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge64 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the CounterBasedGauge64 SMIv2 textual convention defined
+       in RFC 2856";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   /*** collection of identifier related types ***/
+
+   typedef object-identifier {
+     type string {
+       pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))'
+             + '(\.(0|([1-9]\d*)))*';
+     }
+     description
+      "The object-identifier type represents administratively
+       assigned names in a registration-hierarchical-name tree.
+
+       Values of this type are denoted as a sequence of numerical
+       non-negative sub-identifier values.  Each sub-identifier
+       value MUST NOT exceed 2^32-1 (4294967295).  Sub-identifiers
+       are separated by single dots and without any intermediate
+       whitespace.
+
+       The ASN.1 standard restricts the value space of the first
+       sub-identifier to 0, 1, or 2.  Furthermore, the value space
+       of the second sub-identifier is restricted to the range
+       0 to 39 if the first sub-identifier is 0 or 1.  Finally,
+       the ASN.1 standard requires that an object identifier
+       has always at least two sub-identifier.  The pattern
+       captures these restrictions.
+
+       Although the number of sub-identifiers is not limited,
+       module designers should realize that there may be
+       implementations that stick with the SMIv2 limit of 128
+       sub-identifiers.
+
+       This type is a superset of the SMIv2 OBJECT IDENTIFIER type
+       since it is not restricted to 128 sub-identifiers.  Hence,
+       this type SHOULD NOT be used to represent the SMIv2 OBJECT
+       IDENTIFIER type, the object-identifier-128 type SHOULD be
+       used instead.";
+     reference
+      "ISO9834-1: Information technology -- Open Systems
+       Interconnection -- Procedures for the operation of OSI
+       Registration Authorities: General procedures and top
+       arcs of the ASN.1 Object Identifier tree";
+   }
+
+
+
+
+   typedef object-identifier-128 {
+     type object-identifier {
+       pattern '\d*(\.\d*){1,127}';
+     }
+     description
+      "This type represents object-identifiers restricted to 128
+       sub-identifiers.
+
+       In the value set and its semantics, this type is equivalent
+       to the OBJECT IDENTIFIER type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   /*** collection of date and time related types ***/
+
+   typedef date-and-time {
+     type string {
+       pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
+             + '(Z|[\+\-]\d{2}:\d{2})';
+     }
+     description
+      "The date-and-time type is a profile of the ISO 8601
+       standard for representation of dates and times using the
+       Gregorian calendar.  The profile is defined by the
+       date-time production in Section 5.6 of RFC 3339.
+
+       The date-and-time type is compatible with the dateTime XML
+       schema type with the following notable exceptions:
+
+       (a) The date-and-time type does not allow negative years.
+
+       (b) The date-and-time time-offset -00:00 indicates an unknown
+           time zone (see RFC 3339) while -00:00 and +00:00 and Z all
+           represent the same time zone in dateTime.
+
+       (c) The canonical format (see below) of data-and-time values
+           differs from the canonical format used by the dateTime XML
+           schema type, which requires all times to be in UTC using the
+           time-offset 'Z'.
+
+       This type is not equivalent to the DateAndTime textual
+       convention of the SMIv2 since RFC 3339 uses a different
+       separator between full-date and full-time and provides
+       higher resolution of time-secfrac.
+
+       The canonical format for date-and-time values with a known time
+       zone uses a numeric time zone offset that is calculated using
+       the device's configured known offset to UTC time.  A change of
+       the device's offset to UTC time will cause date-and-time values
+       to change accordingly.  Such changes might happen periodically
+       in case a server follows automatically daylight saving time
+       (DST) time zone offset changes.  The canonical format for
+       date-and-time values with an unknown time zone (usually referring
+       to the notion of local time) uses the time-offset -00:00.";
+     reference
+      "RFC 3339: Date and Time on the Internet: Timestamps
+       RFC 2579: Textual Conventions for SMIv2
+       XSD-TYPES: XML Schema Part 2: Datatypes Second Edition";
+   }
+
+   typedef timeticks {
+     type uint32;
+     description
+      "The timeticks type represents a non-negative integer that
+       represents the time, modulo 2^32 (4294967296 decimal), in
+       hundredths of a second between two epochs.  When a schema
+       node is defined that uses this type, the description of
+       the schema node identifies both of the reference epochs.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeTicks type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef timestamp {
+     type yang:timeticks;
+     description
+      "The timestamp type represents the value of an associated
+       timeticks schema node at which a specific occurrence happened.
+       The specific occurrence must be defined in the description
+       of any schema node defined using this type.  When the specific
+       occurrence occurred prior to the last time the associated
+       timeticks attribute was zero, then the timestamp value is
+       zero.  Note that this requires all timestamp values to be
+       reset to zero when the value of the associated timeticks
+       attribute reaches 497+ days and wraps around to zero.
+
+       The associated timeticks schema node must be specified
+       in the description of any schema node using this type.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeStamp textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of generic address types ***/
+
+   typedef phys-address {
+     type string {
+       pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
+     }
+     description
+      "Represents media- or physical-level addresses represented
+       as a sequence octets, each octet represented by two hexadecimal
+       numbers.  Octets are separated by colons.  The canonical
+       representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the PhysAddress textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   typedef mac-address {
+     type string {
+       pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
+     }
+     description
+      "The mac-address type represents an IEEE 802 MAC address.
+       The canonical representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the MacAddress textual convention of the SMIv2.";
+     reference
+      "IEEE 802: IEEE Standard for Local and Metropolitan Area
+                 Networks: Overview and Architecture
+       RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of XML specific types ***/
+
+   typedef xpath1.0 {
+     type string;
+     description
+      "This type represents an XPATH 1.0 expression.
+
+       When a schema node is defined that uses this type, the
+       description of the schema node MUST specify the XPath
+       context in which the XPath expression is evaluated.";
+     reference
+      "XPATH: XML Path Language (XPath) Version 1.0";
+   }
+
+ }
\ No newline at end of file
diff --git a/code-generator/binding-model-api/pom.xml b/code-generator/binding-model-api/pom.xml
new file mode 100644 (file)
index 0000000..235167e
--- /dev/null
@@ -0,0 +1,48 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>binding-model-api</artifactId>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/AccessModifier.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/AccessModifier.java
new file mode 100644 (file)
index 0000000..13f13ee
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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.sal.binding.model.api;
+
+/**
+ * Enum definition which provides four access modifiers that are described
+ * in Java programming language (Default, Private, Protected, Public).
+ */
+public enum AccessModifier {
+    DEFAULT, PRIVATE, PUBLIC, PROTECTED
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/AnnotationType.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/AnnotationType.java
new file mode 100644 (file)
index 0000000..4e248f0
--- /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.sal.binding.model.api;
+
+import java.util.List;
+
+/**
+ * The Annotation Type interface is designed to hold information about
+ * annotation for any type that could be annotated in Java. <br>
+ * For sake of simplicity the Annotation Type is not designed to model exact
+ * behaviour of annotation mechanism, but just to hold information needed to
+ * model annotation over java Type definition.
+ */
+public interface AnnotationType extends Type {
+
+    /**
+     * Returns the List of Annotations. <br>
+     * Each Annotation Type MAY have defined multiple Annotations.
+     * 
+     * @return the List of Annotations.
+     */
+    List<AnnotationType> getAnnotations();
+
+    /**
+     * Returns Parameter Definition assigned for given parameter name. <br>
+     * If Annotation does not contain parameter with specified param name, the
+     * method MAY return <code>null</code> value.
+     * 
+     * @param paramName
+     *            Parameter Name
+     * @return Parameter Definition assigned for given parameter name.
+     */
+    Parameter getParameter(final String paramName);
+
+    /**
+     * Returns List of all parameters assigned to Annotation Type.
+     * 
+     * @return List of all parameters assigned to Annotation Type.
+     */
+    List<Parameter> getParameters();
+
+    /**
+     * Returns List of parameter names.
+     * 
+     * @return List of parameter names.
+     */
+    List<String> getParameterNames();
+
+    /**
+     * Returns <code>true</code> if annotation contains parameters.
+     * 
+     * @return <code>true</code> if annotation contains parameters.
+     */
+    boolean containsParameters();
+
+    /**
+     * Annotation Type parameter interface. For simplicity the Parameter
+     * contains values and value types as Strings. Every annotation which
+     * contains parameters could contain either single parameter or array of
+     * parameters. To model this purposes the by contract if the parameter
+     * contains single parameter the {@link #getValues()} method will return
+     * empty List and {@link #getValue()} MUST always return non-
+     * <code>null</code> parameter. If the Parameter holds List of values the
+     * singular {@link #getValue()} parameter MAY return <code>null</code>
+     * value.
+     */
+    interface Parameter {
+
+        /**
+         * Returns the Name of the parameter.
+         * 
+         * @return the Name of the parameter.
+         */
+        String getName();
+
+        /**
+         * Returns value in String format if Parameter contains singular value,
+         * otherwise MAY return <code>null</code>.
+         * 
+         * @return value in String format if Parameter contains singular value.
+         */
+        String getValue();
+
+        /**
+         * Returns List of Parameter assigned values in order in which they were
+         * assigned for given parameter name. <br>
+         * If there are multiple values assigned for given parameter name the
+         * method MUST NOT return empty List.
+         * 
+         * @return List of Parameter assigned values in order in which they were
+         *         assigned for given parameter name.
+         */
+        List<String> getValues();
+    }
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/CodeGenerator.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/CodeGenerator.java
new file mode 100644 (file)
index 0000000..bde957b
--- /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.sal.binding.model.api;
+
+/**
+ * Transformates virtual data to the concrete code in programming language.
+ * 
+ */
+public interface CodeGenerator {
+
+    /**
+     * Generates code for <code>type</code>.
+     * 
+     * @param type
+     *            Input type to be processed
+     * @return generated JAVA code
+     */
+    String generate(Type type);
+
+    /**
+     * Checks if the concrete instance of <code>type</code> fit to concrete
+     * implementation of this interface.
+     * 
+     * (e. g. method return true if in <code>EnumGenerator</code> (which
+     * implements this interface) has input parameter of type Enumeration (which
+     * is subtype of Type)
+     * 
+     * @param type
+     *            Input type to be processed
+     * @return true if type is acceptable for processing.
+     */
+    boolean isAcceptable(Type type);
+
+    /**
+     * Returns name of <code>type</code> parameter.
+     * 
+     * @param type
+     *            Input type to be processed
+     * @return name of generated unit
+     */
+    String getUnitName(Type type);
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/ConcreteType.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/ConcreteType.java
new file mode 100644 (file)
index 0000000..52adeb9
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.sal.binding.model.api;
+
+/**
+ * The Concrete Type is marker interface that encapsulates definition of java
+ * concrete type.
+ */
+public interface ConcreteType extends Type {
+
+    Restrictions getRestrictions();
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Constant.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Constant.java
new file mode 100644 (file)
index 0000000..31d673c
--- /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.sal.binding.model.api;
+
+/**
+ * Interface Contact is designed to hold and model java constant. In Java there
+ * are no constant keywords instead of the constant is defined as static final
+ * field with assigned value. For this purpose the Constant interface contains
+ * methods {@link #getType()} to provide wrapped return Type of Constant,
+ * {@link #getName()} the Name of constant and the {@link #getValue()} for
+ * providing of value assigned to Constant. To determine of which type the
+ * constant value is it is recommended firstly to retrieve Type from constant.
+ * The Type interface holds base information like java package name and java
+ * type name (e.g. fully qualified name). From this string user should be able
+ * to determine to which type can be {@link #getValue()} type typecasted to
+ * unbox and provide value assigned to constant.
+ */
+public interface Constant {
+
+    /**
+     * Returns the Type that declares constant.
+     * 
+     * @return the Type that declares constant.
+     */
+    Type getDefiningType();
+
+    /**
+     * Returns the return Type (or just Type) of the Constant.
+     * 
+     * @return the return Type (or just Type) of the Constant.
+     */
+    Type getType();
+
+    /**
+     * Returns the name of constant. <br>
+     * By conventions the name SHOULD be in CAPITALS separated with underscores.
+     * 
+     * @return the name of constant.
+     */
+    String getName();
+
+    /**
+     * Returns boxed value that is assigned for context.
+     * 
+     * @return boxed value that is assigned for context.
+     */
+    Object getValue();
+
+    /**
+     * Returns Constant definition in formatted string. <br>
+     * <br>
+     * The expected string SHOULD be in format: <code>public final
+     * static [Type] CONSTANT_NAME = [value];</code>
+     * 
+     * @return Constant definition in formatted string.
+     */
+    String toFormattedString();
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/DocumentedType.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/DocumentedType.java
new file mode 100644 (file)
index 0000000..484d7d4
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.sal.binding.model.api;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * Implementing this interface allows an object to hold information which are
+ * essential for generating java doc from type definition.
+ */
+public interface DocumentedType {
+
+    /**
+     * Returns a string that contains a human-readable textual description of
+     * type definition.
+     *
+     * @return a human-readable textual description of type definition.
+     */
+    String getDescription();
+
+    /**
+     * Returns a string that is used to specify a textual cross-reference to an
+     * external document, either another module that defines related management
+     * information, or a document that provides additional information relevant
+     * to this definition.
+     *
+     * @return a textual cross-reference to an external document.
+     */
+    String getReference();
+
+    /**
+     * Returns a list of QNames which represent schema path in schema tree from
+     * actual concrete type to the root.
+     *
+     * @return a schema path in schema tree from actual concrete schema node
+     *         identifier to the root.
+     */
+    Iterable<QName> getSchemaPath();
+
+    /**
+     * Returns the name of the module, in which generated type was specified.
+     *
+     * @return the name of the module, in which generated type was specified.
+     */
+    String getModuleName();
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Enumeration.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Enumeration.java
new file mode 100644 (file)
index 0000000..9709be3
--- /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.sal.binding.model.api;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
+
+/**
+ * Interface provide methods for reading data of enumeration class.
+ */
+public interface Enumeration extends GeneratedType {
+
+    /**
+     *
+     * Returns list of annotation definitions associated with enumeration type.
+     *
+     * @return list of annotation definitions associated with enumeration type.
+     *
+     */
+    @Override
+    List<AnnotationType> getAnnotations();
+
+    @Override
+    Type getParentType();
+
+    /**
+     * Returns list of the couples - name and value.
+     *
+     * @return list of the enumeration pairs.
+     */
+    List<Pair> getValues();
+
+    /**
+     * Formats enumeration according to rules of the programming language.
+     *
+     * @return string with source code in some programming language
+     */
+    String toFormattedString();
+
+    /**
+     * Interface is used for reading enumeration item. It means item's name and
+     * its value.
+     */
+    interface Pair extends DocumentedNode {
+
+        /**
+         * Returns the name of the enumeration item.
+         *
+         * @return the name of the enumeration item.
+         */
+        String getName();
+
+        /**
+         * Returns value of the enumeration item.
+         *
+         * @return the value of the enumeration item.
+         */
+        Integer getValue();
+    }
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedProperty.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedProperty.java
new file mode 100644 (file)
index 0000000..0464db4
--- /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.sal.binding.model.api;
+
+/**
+ * Generated Property extends interface {@link MethodSignature} interface. <br>
+ * The Generated Property interface is designed to store information of fields
+ * (or members) declared in Java Transfer Objects (or any java classes) and
+ * their access counterparts (getters and setters).
+ *
+ * @see MethodSignature
+ */
+public interface GeneratedProperty extends TypeMember {
+
+    String getValue();
+
+    /**
+     * Returns <code>true</code> if the property si declared as read-only. <br>
+     * If the property has flag <code>isReadOnly == true</code> the property
+     * SHOULD be generated as getter only.
+     *
+     * @return <code>true</code> if the property si declared as read-only.
+     */
+    boolean isReadOnly();
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedTransferIdentityObject.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedTransferIdentityObject.java
new file mode 100644 (file)
index 0000000..d9d7f32
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * 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.sal.binding.model.api;
+
+public interface GeneratedTransferIdentityObject extends
+        GeneratedTransferObject {
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedTransferObject.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedTransferObject.java
new file mode 100644 (file)
index 0000000..f96ade0
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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.sal.binding.model.api;
+
+import java.util.List;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+/**
+ * Generated Transfer Object extends {@link GeneratedType} and is designed to
+ * represent Java Class. The Generated Transfer Object contains declarations of
+ * member fields stored in List of Properties. The Generated Transfer Object can
+ * be extended by exactly ONE Generated Transfer Object as Java don't allow
+ * multiple inheritance. For retrieval of implementing Generated Types use
+ * {@link #getImplements()} method. <br>
+ * Every transfer object SHOULD contain equals, hashCode and toString
+ * definitions. For this purpose retrieve definitions through
+ * {@link #getEqualsIdentifiers ()}, {@link #getHashCodeIdentifiers()} and
+ * {@link #getToStringIdentifiers ()}.
+ *
+ */
+public interface GeneratedTransferObject extends GeneratedType {
+
+    GeneratedProperty getSUID();
+
+    /**
+     * Returns the Generated Transfer Object from which this GTO is derived, or
+     * null if this GTO is not derived from a GTO -- e.g. it is either an union
+     * or it is derived from a concrete type.
+     *
+     * @return Generated Transfer Object or <code>null</code> if this GTO is
+     *         not derived from another GTO.
+     */
+    GeneratedTransferObject getSuperType();
+
+    /**
+     * Returns List of Properties that are designated to define equality for
+     * Generated Transfer Object.
+     *
+     * @return List of Properties that are designated to define equality for
+     *         Generated Transfer Object.
+     */
+    List<GeneratedProperty> getEqualsIdentifiers();
+
+    /**
+     * Returns List of Properties that are designated to define identity for
+     * Generated Transfer Object.
+     *
+     * @return List of Properties that are designated to define identity for
+     *         Generated Transfer Object.
+     */
+    List<GeneratedProperty> getHashCodeIdentifiers();
+
+    /**
+     * Returns List of Properties that will be members of toString definition
+     * for Generated Transfer Object.
+     *
+     * @return List of Properties that will be members of toString definition
+     *         for Generated Transfer Object.
+     */
+    List<GeneratedProperty> getToStringIdentifiers();
+
+    boolean isTypedef();
+
+    /**
+     * Returns Base type of Java representation of YANG typedef if set, otherwise it returns null
+     *
+     * @return Base type of Java representation of YANG typedef if set, otherwise it returns null
+     */
+    TypeDefinition<?> getBaseType();
+
+    /**
+     * Return boolean value which describe whether Generated Transfer Object
+     * was/wasn't created from union YANG type.
+     *
+     * @return true value if Generated Transfer Object was created from union
+     *         YANG type.
+     */
+    boolean isUnionType();
+
+    boolean isUnionTypeBuilder();
+
+    Restrictions getRestrictions();
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedType.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedType.java
new file mode 100644 (file)
index 0000000..0e9b51e
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * 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.sal.binding.model.api;
+
+import java.util.List;
+
+/**
+ * Every Java interface has to be specified with:
+ * <ul>
+ * <li><code>package</code> that belongs into</li>
+ * <li><code>interface</code> name (with commentary that <b>SHOULD</b> be
+ * present to proper define interface and base <i>contracts</i> specified for
+ * interface)</li>
+ * <li>Each Generated Type can define list of types that Generated Type can
+ * implement to extend it's definition (i.e. interface extends list of
+ * interfaces or java class implements list of interfaces)</li>
+ * <li>Each Generated Type can contain multiple enclosed definitions of
+ * Generated Types (i.e. interface can contain N enclosed interface definitions
+ * or enclosed classes)</li>
+ * <li><code>enum</code> and <code>constant</code> definitions (i.e. each
+ * constant definition is by default defined as <code>public static final</code>
+ * + type (either primitive or object) and constant name</li>
+ * <li><code>method definitions</code> with specified input parameters (with
+ * types) and return values</li>
+ * </ul>
+ *
+ * By the definition of the interface constant, enum, enclosed types and method
+ * definitions MUST be public, so there is no need to specify the scope of
+ * visibility.
+ */
+public interface GeneratedType extends Type, DocumentedType {
+
+    /**
+     * Returns the parent type if Generated Type is defined as enclosing type,
+     * otherwise returns <code>null</code>
+     *
+     * @return the parent type if Generated Type is defined as enclosing type,
+     *         otherwise returns <code>null</code>
+     */
+    Type getParentType();
+
+    /**
+     * Returns comment string associated with Generated Type.
+     *
+     * @return comment string associated with Generated Type.
+     */
+    String getComment();
+
+    /**
+     * Returns List of annotation definitions associated with generated type.
+     *
+     * @return List of annotation definitions associated with generated type.
+     */
+    List<AnnotationType> getAnnotations();
+
+    /**
+     * Returns <code>true</code> if The Generated Type is defined as abstract.
+     *
+     * @return <code>true</code> if The Generated Type is defined as abstract.
+     */
+    boolean isAbstract();
+
+    /**
+     * Returns List of Types that Generated Type will implement.
+     *
+     * @return List of Types that Generated Type will implement.
+     */
+    List<Type> getImplements();
+
+    /**
+     * Returns List of enclosing Generated Types.
+     *
+     * @return List of enclosing Generated Types.
+     */
+    List<GeneratedType> getEnclosedTypes();
+
+    /**
+     * Returns List of all Enumerator definitions associated with Generated
+     * Type.
+     *
+     * @return List of all Enumerator definitions associated with Generated
+     *         Type.
+     */
+    List<Enumeration> getEnumerations();
+
+    /**
+     * Returns List of Constant definitions associated with Generated Type.
+     *
+     * @return List of Constant definitions associated with Generated Type.
+     */
+    List<Constant> getConstantDefinitions();
+
+    /**
+     * Returns List of Method Definitions associated with Generated Type.
+     *
+     * List does not contains getters and setters for properties.
+     *
+     * @return List of Method Definitions associated with Generated Type.
+     */
+    List<MethodSignature> getMethodDefinitions();
+
+    /**
+     * Returns List of Properties that are declared for Generated Transfer
+     * Object.
+     *
+     * @return List of Properties that are declared for Generated Transfer
+     *         Object.
+     */
+    List<GeneratedProperty> getProperties();
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/MethodSignature.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/MethodSignature.java
new file mode 100644 (file)
index 0000000..00699b9
--- /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.sal.binding.model.api;
+
+import java.util.List;
+
+/**
+ * The Method Signature interface contains simplified meta model for java method
+ * definition. Each method MUST be defined by name, return type, parameters and
+ * access modifier. <br>
+ * Additionally method MAY contain associated annotations and comment. By
+ * contract if method does not contain any comments or annotation definitions
+ * the {@link #getComment()} SHOULD rather return empty string and
+ * {@link #getAnnotations()} SHOULD rather return empty list than
+ * <code>null</code> values. <br>
+ * The defining Type contains the reference to Generated Type that declares
+ * Method Signature.
+ */
+public interface MethodSignature extends TypeMember {
+
+    /**
+     * Returns <code>true</code> if the method signature is defined as abstract. <br>
+     * By default in java all method declarations in interface are defined as
+     * abstract, but the user don't need necessary to declare abstract keyword
+     * in front of each method. <br>
+     * The abstract methods are allowed in Class definitions but only when the
+     * class is declared as abstract.
+     * 
+     * @return <code>true</code> if the method signature is defined as abstract.
+     */
+    boolean isAbstract();
+
+    /**
+     * Returns the List of parameters that method declare. If the method does
+     * not contain any parameters, the method will return empty List.
+     * 
+     * @return the List of parameters that method declare.
+     */
+    List<Parameter> getParameters();
+
+    /**
+     * The Parameter interface is designed to hold the information of method
+     * Parameter(s). The parameter is defined by his Name which MUST be unique
+     * as java does not allow multiple parameters with same names for one method
+     * and Type that is associated with parameter.
+     */
+    interface Parameter {
+
+        /**
+         * Returns the parameter name.
+         * 
+         * @return the parameter name.
+         */
+        String getName();
+
+        /**
+         * Returns Type that is bounded to parameter name.
+         * 
+         * @return Type that is bounded to parameter name.
+         */
+        Type getType();
+    }
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/ParameterizedType.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/ParameterizedType.java
new file mode 100644 (file)
index 0000000..06b8498
--- /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.sal.binding.model.api;
+
+/**
+ * Represents an instance of simple parametrized type such as List&lt;String&gt;.
+ *
+ * The parametrized Type is designed to be used to store information of Java
+ * Generic Type. The array of {@link #getActualTypeArguments()} holds
+ * information of all generic parameters defined for Parameterized Type.
+ */
+public interface ParameterizedType extends Type {
+
+    /**
+     * Returns array of Types that are defined for Parameterized Type.
+     * <br>
+     * (for example if ParameterizedType encapsulates java generic Map that
+     * specifies two parameters Map&lt;K,V&gt; and the K is java.lang.Integer and V
+     * is defined as GeneratedType the array will contain two Types to store
+     * the information of generic parameters.)
+     *
+     * @return array of Types that are defined for Parameterized Type.
+     */
+    Type[] getActualTypeArguments();
+
+    /**
+     * Returns the Raw Type definition of Parameterized Type.
+     *
+     * @return the Raw Type definition of Parameterized Type.
+     */
+    Type getRawType();
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Restrictions.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Restrictions.java
new file mode 100644 (file)
index 0000000..292b632
--- /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.sal.binding.model.api;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+
+public interface Restrictions {
+
+    List<LengthConstraint> getLengthConstraints();
+    List<PatternConstraint> getPatternConstraints();
+    List<RangeConstraint> getRangeConstraints();
+    boolean isEmpty();
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Type.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/Type.java
new file mode 100644 (file)
index 0000000..c259d59
--- /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.sal.binding.model.api;
+
+/**
+ * The Type interface defines the base type for all types defined in java. Each
+ * Type defined in java MUST contain name and package name, except of primitive
+ * types like int, byte etc. In case of mapping of primitive type the package
+ * name MUST be left as empty string.
+ * 
+ */
+public interface Type {
+    /**
+     * Returns name of the package that interface belongs to.
+     * 
+     * @return name of the package that interface belongs to
+     */
+    String getPackageName();
+
+    /**
+     * Returns name of the interface.
+     * 
+     * @return name of the interface.
+     */
+    String getName();
+
+    /**
+     * Returns fully qualified name of Type. <br>
+     * The fully qualified name of Type MUST be returned in following format:
+     * <ul>
+     * <li>If does not contains package name: [type name] (e.g. int, byte,
+     * byte[],...)</li>
+     * <li>If Type contains package name: [package name].[type name] (e.g
+     * java.lang.Byte, org.opendaylight.controller.gen.GenType)</li>
+     * </ul>
+     * 
+     * @return fully qualified name of Type.
+     */
+    String getFullyQualifiedName();
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/TypeMember.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/TypeMember.java
new file mode 100644 (file)
index 0000000..2447e21
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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.sal.binding.model.api;
+
+import java.util.List;
+
+/**
+ * Common interface for variables and methods in class.
+ */
+public interface TypeMember {
+
+    /**
+     * Returns comment string associated with member.
+     *
+     * @return comment string associated with member.
+     */
+    String getComment();
+
+    /**
+     * Returns List of annotation definitions associated with generated type.
+     *
+     * @return List of annotation definitions associated with generated type.
+     */
+    List<AnnotationType> getAnnotations();
+
+    /**
+     * Returns the access modifier of member.
+     *
+     * @return the access modifier of member.
+     */
+    AccessModifier getAccessModifier();
+
+    /**
+     * Returns <code>true</code> if member is declared as static.
+     *
+     * @return <code>true</code> if member is declared as static.
+     */
+    boolean isStatic();
+
+    /**
+     * Returns <code>true</code> if member is declared as final.
+     *
+     * @return <code>true</code> if member is declared as final.
+     */
+    boolean isFinal();
+
+    /**
+     * Get the returning Type of member.
+     *
+     * @return the returning Type of member.
+     */
+    Type getReturnType();
+
+    /**
+     * Returns the name of member.
+     *
+     * @return the name of member.
+     */
+    String getName();
+
+    /**
+     * Returns the Type that declares member.
+     *
+     * @return the Type that declares member.
+     */
+    Type getDefiningType();
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/WildcardType.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/WildcardType.java
new file mode 100644 (file)
index 0000000..7246de6
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.sal.binding.model.api;
+
+/**
+ * 
+ * Marker interface which assign to object property that it is bounded wildcard
+ * type.
+ * 
+ */
+public interface WildcardType extends Type {
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/package-info.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/package-info.java
new file mode 100644 (file)
index 0000000..64d4119
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.sal.binding.model.api;
\ No newline at end of file
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/AnnotationTypeBuilder.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/AnnotationTypeBuilder.java
new file mode 100644 (file)
index 0000000..c9ded32
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * 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.sal.binding.model.api.type.builder;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.sal.binding.model.api.AnnotationType;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+/**
+ * Annotation Type Builder Interface serves for creation and instantiation of
+ * immutable copy of Annotation Type. The Annotation Type Builder extends from
+ * {@link Type} interface. The Annotation Type contains set of methods which are
+ * capable to provide information about other Annotation Types and Annotation
+ * Parameters.
+ * 
+ * @see AnnotationType
+ */
+public interface AnnotationTypeBuilder extends Type {
+
+    /**
+     * The method creates new AnnotationTypeBuilder containing specified package
+     * name an annotation name. <br>
+     * Neither the package name or annotation name can contain <code>null</code>
+     * references. In case that any of parameters contains <code>null</code> the
+     * method SHOULD thrown {@link IllegalArgumentException}
+     * 
+     * @param packageName
+     *            Package Name of Annotation Type
+     * @param name
+     *            Name of Annotation Type
+     * @return <code>new</code> instance of Annotation Type Builder.
+     */
+    AnnotationTypeBuilder addAnnotation(final String packageName, final String name);
+
+    /**
+     * Adds the parameter into List of parameters for Annotation Type. <br>
+     * If there is already stored parameter with the same name as the new
+     * parameter, the value of the old one will be simply overwritten by the
+     * newer parameter. <br>
+     * Neither the param name or value can contain <code>null</code> references.
+     * In case that any of parameters contains <code>null</code> the method
+     * SHOULD thrown {@link IllegalArgumentException}
+     * 
+     * @param paramName
+     *            Parameter Name
+     * @param value
+     *            Parameter Value
+     * @return <code>true</code> if the parameter has been successfully assigned
+     *         for Annotation Type
+     */
+    boolean addParameter(final String paramName, String value);
+
+    /**
+     * Adds the parameter with specified List of parameter values into List of
+     * parameters for Annotation Type. <br>
+     * If there is already stored parameter with the same name as the new
+     * parameter, the value of the old one will be simply overwritten by the
+     * newer parameter. <br>
+     * Neither the param name or value can contain <code>null</code> references.
+     * In case that any of parameters contains <code>null</code> the method
+     * SHOULD thrown {@link IllegalArgumentException}
+     * 
+     * @param paramName
+     *            Parameter Name
+     * @param values
+     *            List of Values bounded to Parameter Name
+     * @return <code>true</code> if the parameter has been successfully assigned
+     *         for Annotation Type
+     */
+    boolean addParameters(final String paramName, List<String> values);
+
+    /**
+     * Returns <code>new</code> <i>immutable</i> instance of Annotation Type
+     * with values assigned in current instance of Annotation Type Builder. <br>
+     * The return Annotation Type instance is immutable thus no additional
+     * modification to Annotation Type Builder will have an impact to
+     * instantiated Annotation Type. <br>
+     * For this purpose call this method after all additions are complete.
+     * 
+     * @return <code>new</code> <i>immutable</i> instance of Annotation Type.
+     */
+    AnnotationType toInstance();
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/ConstantBuilder.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/ConstantBuilder.java
new file mode 100644 (file)
index 0000000..de3f090
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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.sal.binding.model.api.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+/**
+ *
+ */
+public interface ConstantBuilder {
+
+    void assignValue(final Object value);
+
+    Constant toInstance(Type definingType);
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/EnumBuilder.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/EnumBuilder.java
new file mode 100644 (file)
index 0000000..a3339b9
--- /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.sal.binding.model.api.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+
+/**
+ * Enum Builder is interface that contains methods to build and instantiate
+ * Enumeration definition.
+ *
+ * @see Enumeration
+ */
+public interface EnumBuilder extends Type {
+
+    /**
+     * The method creates new AnnotationTypeBuilder containing specified package
+     * name an annotation name. <br>
+     * Neither the package name or annotation name can contain <code>null</code>
+     * references. In case that any of parameters contains <code>null</code> the
+     * method SHOULD thrown {@link IllegalArgumentException}
+     *
+     * @param packageName
+     *            Package Name of Annotation Type
+     * @param name
+     *            Name of Annotation Type
+     * @return <code>new</code> instance of Annotation Type Builder.
+     */
+    AnnotationTypeBuilder addAnnotation(final String packageName, final String name);
+
+    /**
+     *
+     * @param name
+     * @param value
+     */
+    void addValue(final String name, final Integer value, final String description);
+
+    /**
+     *
+     * @param definingType
+     * @return
+     */
+    Enumeration toInstance(final Type definingType);
+
+    /**
+     * Updates this builder with data from <code>enumTypeDef</code>.
+     * Specifically this data represents list of value-name pairs.
+     *
+     * @param enumTypeDef
+     *            enum type definition as source of enum data for
+     *            <code>enumBuilder</code>
+     */
+    void updateEnumPairsFromEnumTypeDef(final EnumTypeDefinition enumTypeDef);
+
+    /**
+     * @param description
+     */
+    void setDescription(final String description);
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedPropertyBuilder.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedPropertyBuilder.java
new file mode 100644 (file)
index 0000000..cd4b9b4
--- /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.sal.binding.model.api.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+/**
+ * Generated Property Builder is interface that contains methods to build and
+ * instantiate Generated Property definition.
+ *
+ * @see GeneratedProperty
+ */
+public interface GeneratedPropertyBuilder extends TypeMemberBuilder<GeneratedPropertyBuilder> {
+
+    GeneratedPropertyBuilder setValue(String value);
+
+    /**
+     * Sets isReadOnly flag for property. If property is marked as read only it
+     * is the same as set property in java as final.
+     *
+     * @param isReadOnly
+     *            Read Only property flag.
+     */
+    GeneratedPropertyBuilder setReadOnly(final boolean isReadOnly);
+
+    /**
+     * Returns <code>new</code> <i>immutable</i> instance of Generated Property. <br>
+     * The <code>definingType</code> param cannot be <code>null</code>. The
+     * every member in Java MUST be declared and defined inside the scope of
+     * <code>class</code> definition. In case that defining Type will be passed
+     * as <code>null</code> reference the method SHOULD thrown
+     * {@link IllegalArgumentException}.
+     *
+     * @param definingType
+     *            Defining Type of Generated Property
+     * @return <code>new</code> <i>immutable</i> instance of Generated Property.
+     */
+    GeneratedProperty toInstance(final Type definingType);
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTOBuilder.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTOBuilder.java
new file mode 100644 (file)
index 0000000..ca25dad
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.sal.binding.model.api.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+
+/**
+ * Generated Transfer Object Builder is interface that contains methods to build
+ * and instantiate Generated Transfer Object definition.
+ *
+ * @see GeneratedTransferObject
+ */
+public interface GeneratedTOBuilder extends GeneratedTypeBuilderBase<GeneratedTOBuilder> {
+
+    /**
+     * Add Generated Transfer Object from which will be extended current
+     * Generated Transfer Object. <br>
+     * By definition Java does not allow multiple inheritance, hence if there is
+     * already definition of Generated Transfer Object the extending object will
+     * be overwritten by lastly added Generated Transfer Object. <br>
+     * If Generated Transfer Object is <code>null</code> the method SHOULD throw
+     * {@link IllegalArgumentException}
+     *
+     * @param genTransObj
+     *            Generated Transfer Object
+     * @return This instance of builder
+     */
+    GeneratedTOBuilder setExtendsType(final GeneratedTransferObject genTransObj);
+
+    /**
+     * Add Property that will be part of <code>equals</code> definition. <br>
+     * If Generated Property Builder is <code>null</code> the method SHOULD
+     * throw {@link IllegalArgumentException}
+     *
+     * @param property
+     *            Generated Property Builder
+     * @return This instance of builder
+     */
+    GeneratedTOBuilder addEqualsIdentity(final GeneratedPropertyBuilder property);
+
+    /**
+     * Add Property that will be part of <code>hashCode</code> definition. <br>
+     * If Generated Property Builder is <code>null</code> the method SHOULD
+     * throw {@link IllegalArgumentException}
+     *
+     * @param property
+     *            Generated Property Builder
+     * @return This instance of builder
+     */
+    GeneratedTOBuilder addHashIdentity(final GeneratedPropertyBuilder property);
+
+    /**
+     * Add Property that will be part of <code>toString</code> definition. <br>
+     * If Generated Property Builder is <code>null</code> the method SHOULD
+     * throw {@link IllegalArgumentException}
+     *
+     * @param property
+     *            Generated Property Builder
+     * @return This instance of builder
+     */
+    GeneratedTOBuilder addToStringProperty(final GeneratedPropertyBuilder property);
+
+    void setRestrictions(Restrictions restrictions);
+
+    /**
+     * Returns instance of <code>GeneratedTransferObject</code> which data are
+     * build from the data of this builder
+     *
+     * @return generated transfer object instance
+     */
+    GeneratedTransferObject toInstance();
+
+    void setTypedef(boolean isTypedef);
+
+    /**
+     * Sets the base type for Java representation of YANG typedef
+     *
+     * @param typeDef
+     *           Type Definition
+     */
+    void setBaseType(TypeDefinition<?> typeDef);
+
+    /**
+     *
+     * @param isUnion
+     */
+    void setIsUnion(boolean isUnion);
+
+    void setIsUnionBuilder(boolean isUnionTypeBuilder);
+
+    void setSUID(GeneratedPropertyBuilder suid);
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTypeBuilder.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTypeBuilder.java
new file mode 100644 (file)
index 0000000..9756bd2
--- /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.sal.binding.model.api.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
+
+/**
+ * Generated Type Builder interface is helper interface for building and
+ * defining the GeneratedType.
+ * 
+ * @see GeneratedType
+ */
+public interface GeneratedTypeBuilder extends GeneratedTypeBuilderBase<GeneratedTypeBuilder> {
+
+    /**
+     * Returns the <code>new</code> <i>immutable</i> instance of Generated Type.
+     * 
+     * @return the <code>new</code> <i>immutable</i> instance of Generated Type.
+     */
+    GeneratedType toInstance();
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTypeBuilderBase.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTypeBuilderBase.java
new file mode 100644 (file)
index 0000000..cc95e19
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * 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.sal.binding.model.api.type.builder;
+
+import java.util.List;
+
+import org.opendaylight.yangtools.sal.binding.model.api.Constant;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.common.QName;
+
+public interface GeneratedTypeBuilderBase<T extends GeneratedTypeBuilderBase<T>> extends Type {
+
+    /**
+     * Adds new Enclosing Transfer Object into definition of Generated Type and
+     * returns <code>new</code> Instance of Generated TO Builder. <br>
+     * There is no need of specifying of Package Name because enclosing Type is
+     * already defined inside Generated Type with specific package name. <br>
+     * The name of enclosing Type cannot be same as Name of parent type and if
+     * there is already defined enclosing type with the same name, the new
+     * enclosing type will simply overwrite the older definition. <br>
+     * If the name of enclosing type is <code>null</code> the method SHOULD
+     * throw {@link IllegalArgumentException}
+     *
+     * @param name
+     *            Name of Enclosing Type
+     * @return <code>new</code> Instance of Generated Type Builder.
+     */
+    GeneratedTOBuilder addEnclosingTransferObject(String name);
+
+    /**
+     * Adds new Enclosing Transfer Object <code>genTOBuilder</code> into
+     * definition of Generated Type
+     *
+     * <br>
+     * There is no need of specifying of Package Name because enclosing Type is
+     * already defined inside Generated Type with specific package name. <br>
+     * The name of enclosing Type cannot be same as Name of parent type and if
+     * there is already defined enclosing type with the same name, the new
+     * enclosing type will simply overwrite the older definition. <br>
+     * If the parameter <code>genTOBuilder</code> of enclosing type is
+     * <code>null</code> the method SHOULD throw
+     * {@link IllegalArgumentException}
+     *
+     * @param genTOBuilder
+     *            Name of Enclosing Type
+     */
+    T addEnclosingTransferObject(GeneratedTOBuilder genTOBuilder);
+
+    /**
+     * Adds String definition of comment into Method Signature definition. <br>
+     * The comment String MUST NOT contain anny comment specific chars (i.e.
+     * "/**" or "//") just plain String text description.
+     *
+     * @param comment
+     *            Comment String.
+     */
+    T addComment(String comment);
+
+    /**
+     * The method creates new AnnotationTypeBuilder containing specified package
+     * name an annotation name. <br>
+     * Neither the package name or annotation name can contain <code>null</code>
+     * references. In case that any of parameters contains <code>null</code> the
+     * method SHOULD thrown {@link IllegalArgumentException}
+     *
+     * @param packageName
+     *            Package Name of Annotation Type
+     * @param name
+     *            Name of Annotation Type
+     * @return <code>new</code> instance of Annotation Type Builder.
+     */
+    AnnotationTypeBuilder addAnnotation(String packageName, String name);
+
+    boolean isAbstract();
+
+    /**
+     * Sets the <code>abstract</code> flag to define Generated Type as
+     * <i>abstract</i> type.
+     *
+     * @param isAbstract
+     *            abstract flag
+     */
+    T setAbstract(boolean isAbstract);
+
+    List<Type> getImplementsTypes();
+
+    /**
+     * Add Type to implements.
+     *
+     * @param genType
+     *            Type to implement
+     * @return <code>true</code> if the addition of type is successful.
+     */
+    T addImplementsType(Type genType);
+
+    /**
+     * Adds Constant definition and returns <code>new</code> Constant instance. <br>
+     * By definition Constant MUST be defined by return Type, Name and assigned
+     * value. The name SHOULD be defined with capital letters. Neither of method
+     * parameters can be <code>null</code> and the method SHOULD throw
+     * {@link IllegalArgumentException} if the contract is broken.
+     *
+     * @param type
+     *            Constant Type
+     * @param name
+     *            Name of Constant
+     * @param value
+     *            Assigned Value
+     * @return <code>new</code> Constant instance.
+     */
+    Constant addConstant(Type type, String name, Object value);
+
+    /**
+     * Adds new Enumeration definition for Generated Type Builder and returns
+     * Enum Builder for specifying all Enum parameters. <br>
+     * If there is already Enumeration stored with the same name, the old enum
+     * will be simply overwritten byt new enum definition. <br>
+     * Name of Enumeration cannot be <code>null</code>, if it is
+     * <code>null</code> the method SHOULD throw
+     * {@link IllegalArgumentException}
+     *
+     * @param name
+     *            Enumeration Name
+     * @return <code>new</code> instance of Enumeration Builder.
+     */
+    EnumBuilder addEnumeration(String name);
+
+    List<MethodSignatureBuilder> getMethodDefinitions();
+
+    /**
+     * Add new Method Signature definition for Generated Type Builder and
+     * returns Method Signature Builder for specifying all Method parameters. <br>
+     * Name of Method cannot be <code>null</code>, if it is <code>null</code>
+     * the method SHOULD throw {@link IllegalArgumentException} <br>
+     * By <i>Default</i> the MethodSignatureBuilder SHOULD be pre-set as
+     * {@link MethodSignatureBuilder#setAbstract(boolean)},
+     * {TypeMemberBuilder#setFinal(boolean)} and
+     * {TypeMemberBuilder#setAccessModifier(boolean)}
+     *
+     * @param name
+     *            Name of Method
+     * @return <code>new</code> instance of Method Signature Builder.
+     */
+    MethodSignatureBuilder addMethod(String name);
+
+    /**
+     * Checks if GeneratedTypeBuilder contains method with name
+     * <code>methodName</code>
+     *
+     * @param methodName
+     *            is method name
+     */
+    boolean containsMethod(String methodName);
+
+    List<GeneratedPropertyBuilder> getProperties();
+
+    /**
+     * Add new Generated Property definition for Generated Transfer Object
+     * Builder and returns Generated Property Builder for specifying Property. <br>
+     * Name of Property cannot be <code>null</code>, if it is <code>null</code>
+     * the method SHOULD throw {@link IllegalArgumentException}
+     *
+     * @param name
+     *            Name of Property
+     * @return <code>new</code> instance of Generated Property Builder.
+     */
+    GeneratedPropertyBuilder addProperty(String name);
+
+    /**
+     * Check whether GeneratedTOBuilder contains property with name
+     * <code>name</code>
+     *
+     * @param name
+     *            of property which existance is checked
+     * @return true if property <code>name</code> exists in list of properties.
+     */
+    boolean containsProperty(String name);
+
+    /**
+     * Set a string that contains a human-readable textual description of type
+     * definition.
+     *
+     * @param description
+     *            a string that contains a human-readable textual description of
+     *            type definition.
+     */
+    void setDescription(String description);
+
+    /**
+     * Set the name of the module, in which generated type was specified.
+     *
+     * @param moduleName
+     *            the name of the module
+     */
+    void setModuleName(String moduleName);
+
+    /**
+     * Set a list of QNames which represent schema path in schema tree from
+     * actual concrete type to the root.
+     *
+     * @param schemaPath
+     *            a list of QNames which represent schema path in schema tree
+     */
+    void setSchemaPath(Iterable<QName> schemaPath);
+
+    /**
+     * Set a string that is used to specify a textual cross-reference to an
+     * external document, either another module that defines related management
+     * information, or a document that provides additional information relevant
+     * to this definition.
+     *
+     * @param reference
+     *            a textual cross-reference to an external document.
+     */
+    void setReference(String reference);
+
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/MethodSignatureBuilder.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/MethodSignatureBuilder.java
new file mode 100644 (file)
index 0000000..7137452
--- /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.sal.binding.model.api.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+/**
+ * Method Signature Builder serves solely for building Method Signature and
+ * returning the <code>new</code> instance of Method Signature. <br>
+ * By definition of {@link MethodSignature} the Method in java MUST contain
+ * Name, Return Type and Access Modifier. By default the Access Modifier can be
+ * set to public. The Method Signature builder does not contain method for
+ * addName due to enforce reason that MethodSignatureBuilder SHOULD be
+ * instantiated only once with defined method name. <br>
+ * The methods as {@link #addAnnotation(String, String)} and
+ * {@link #setComment(String)} can be used as optional because not all methods
+ * MUST contain annotation or comment definitions.
+ *
+ *
+ * @see MethodSignature
+ */
+public interface MethodSignatureBuilder extends TypeMemberBuilder<MethodSignatureBuilder> {
+
+    /**
+     * Sets the flag for declaration of method as abstract or non abstract. If
+     * the flag <code>isAbstract == true</code> The instantiated Method
+     * Signature MUST have return value for {@link MethodSignature#isAbstract()}
+     * also equals to <code>true</code>.
+     *
+     * @param isAbstract
+     *            is abstract flag
+     */
+    MethodSignatureBuilder setAbstract(boolean isAbstract);
+
+    /**
+     * Adds Parameter into the List of method parameters. Neither the Name or
+     * Type of parameter can be <code>null</code>.
+     *
+     * <br>
+     * In case that any of parameters are defined as <code>null</code> the
+     * method SHOULD throw an {@link IllegalArgumentException}
+     *
+     * @param type
+     *            Parameter Type
+     * @param name
+     *            Parameter Name
+     */
+    MethodSignatureBuilder addParameter(final Type type, final String name);
+
+    /**
+     * Returns <code>new</code> <i>immutable</i> instance of Method Signature. <br>
+     * The <code>definingType</code> param cannot be <code>null</code>. The
+     * every method in Java MUST be declared and defined inside the scope of
+     * <code>class</code> or <code>interface</code> definition. In case that
+     * defining Type will be passed as <code>null</code> reference the method
+     * SHOULD thrown {@link IllegalArgumentException}.
+     *
+     * @param definingType
+     *            Defining Type of Method Signature
+     * @return <code>new</code> <i>immutable</i> instance of Method Signature.
+     */
+    MethodSignature toInstance(final Type definingType);
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/TypeMemberBuilder.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/TypeMemberBuilder.java
new file mode 100644 (file)
index 0000000..aa44be4
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.sal.binding.model.api.type.builder;
+
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+
+/**
+ *
+ */
+public interface TypeMemberBuilder<T extends TypeMemberBuilder<T>> {
+
+    /**
+     * The method creates new AnnotationTypeBuilder containing specified package
+     * name an annotation name. <br>
+     * Neither the package name or annotation name can contain <code>null</code>
+     * references. In case that any of parameters contains <code>null</code> the
+     * method SHOULD thrown {@link IllegalArgumentException}
+     *
+     * @param packageName
+     *            Package Name of Annotation Type
+     * @param name
+     *            Name of Annotation Type
+     * @return <code>new</code> instance of Annotation Type Builder.
+     */
+    AnnotationTypeBuilder addAnnotation(final String packageName, final String name);
+
+    /**
+     * Returns the name of property.
+     *
+     * @return the name of property.
+     */
+    String getName();
+
+    /**
+     * Adds return Type into Builder definition for Generated Property. <br>
+     * The return Type MUST NOT be <code>null</code>, otherwise the method
+     * SHOULD throw {@link IllegalArgumentException}
+     *
+     * @param returnType
+     *            Return Type of property.
+     */
+    T setReturnType(final Type returnType);
+
+    AccessModifier getAccessModifier();
+
+    /**
+     * Sets the access modifier of property.
+     *
+     * @param modifier
+     *            Access Modifier value.
+     */
+    T setAccessModifier(final AccessModifier modifier);
+
+    /**
+     * Adds String definition of comment into Method Signature definition. <br>
+     * The comment String MUST NOT contain anny comment specific chars (i.e.
+     * "/**" or "//") just plain String text description.
+     *
+     * @param comment
+     *            Comment String.
+     */
+    T setComment(final String comment);
+
+    /**
+     * Sets the flag final for method signature. If this is set the method will
+     * be prohibited from overriding. <br>
+     * This setting is irrelevant for methods designated to be defined in
+     * interface definitions because interface can't have final method.
+     *
+     * @param isFinal
+     *            Is Final
+     */
+    T setFinal(final boolean isFinal);
+
+    T setStatic(final boolean isStatic);
+}
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/package-info.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/package-info.java
new file mode 100644 (file)
index 0000000..f46cc4c
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.sal.binding.model.api.type.builder;
\ No newline at end of file
diff --git a/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/provider/package-info.java b/code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/provider/package-info.java
new file mode 100644 (file)
index 0000000..b88b1ab
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.sal.binding.model.api.type.provider;
\ No newline at end of file
diff --git a/code-generator/binding-parent/pom.xml b/code-generator/binding-parent/pom.xml
new file mode 100644 (file)
index 0000000..cc1013a
--- /dev/null
@@ -0,0 +1,134 @@
+<?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.odlparent</groupId>
+        <artifactId>bundle-parent</artifactId>
+        <version>1.6.0-SNAPSHOT</version>
+        <relativePath/>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.opendaylight.yangtools</groupId>
+    <artifactId>binding-parent</artifactId>
+    <version>0.8.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <properties>
+        <yangtools.version>0.8.0-SNAPSHOT</yangtools.version>
+        <salGeneratorPath>src/main/yang-gen-sal</salGeneratorPath>
+    </properties>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yangtools-artifacts</artifactId>
+                <version>${yangtools.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <profiles>
+        <profile>
+            <activation>
+                <file>
+                    <exists>src/main/yang</exists>
+                </file>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.opendaylight.yangtools</groupId>
+                    <artifactId>yang-binding</artifactId>
+                </dependency>
+            </dependencies>
+            <build>
+                <pluginManagement>
+                    <plugins>
+                        <plugin>
+                            <groupId>org.opendaylight.yangtools</groupId>
+                            <artifactId>yang-maven-plugin</artifactId>
+                            <version>${yangtools.version}</version>
+                            <dependencies>
+                                <dependency>
+                                    <groupId>org.opendaylight.yangtools</groupId>
+                                    <artifactId>maven-sal-api-gen-plugin</artifactId>
+                                    <version>${yangtools.version}</version>
+                                    <type>jar</type>
+                                </dependency>
+                            </dependencies>
+                            <executions>
+                                <execution>
+                                    <id>binding</id>
+                                    <goals>
+                                        <goal>generate-sources</goal>
+                                    </goals>
+                                    <configuration>
+                                        <codeGenerators>
+                                            <generator>
+                                                <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                                                <outputBaseDir>${salGeneratorPath}</outputBaseDir>
+                                            </generator>
+                                        </codeGenerators>
+                                        <inspectDependencies>true</inspectDependencies>
+                                    </configuration>
+                                </execution>
+                            </executions>
+                        </plugin>
+                        <plugin>
+                            <artifactId>maven-clean-plugin</artifactId>
+                            <configuration>
+                                <filesets>
+                                    <fileset>
+                                        <directory>${salGeneratorPath}</directory>
+                                        <includes>
+                                            <include>**</include>
+                                        </includes>
+                                    </fileset>
+                                </filesets>
+                            </configuration>
+                        </plugin>
+                        <plugin>
+                            <groupId>org.codehaus.mojo</groupId>
+                            <artifactId>build-helper-maven-plugin</artifactId>
+                            <executions>
+                                <execution>
+                                    <id>add-yang-sources</id>
+                                    <phase>generate-sources</phase>
+                                    <goals>
+                                        <goal>add-source</goal>
+                                    </goals>
+                                    <configuration>
+                                        <sources>
+                                            <source>${salGeneratorPath}</source>
+                                        </sources>
+                                    </configuration>
+                                </execution>
+                            </executions>
+                        </plugin>
+                    </plugins>
+                </pluginManagement>
+                <plugins>
+                    <plugin>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>yang-maven-plugin</artifactId>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/code-generator/binding-test-model/pom.xml b/code-generator/binding-test-model/pom.xml
new file mode 100644 (file)
index 0000000..b759f86
--- /dev/null
@@ -0,0 +1,67 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>yang-ext</artifactId>
+        </dependency>
+    </dependencies>
+
+    <artifactId>binding-test-model</artifactId>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+                                    </codeGeneratorClass>
+                                    <outputBaseDir>
+                                        target/generated-sources/sal
+                                    </outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>true</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <scm>
+        <connection>scm:git:ssh://git.opendaylight.org:29418/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <tag>HEAD</tag>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL</url>
+    </scm>
+
+</project>
diff --git a/code-generator/binding-test-model/src/main/java/org/opendaylight/controller/md/sal/test/model/util/ListsBindingUtils.java b/code-generator/binding-test-model/src/main/java/org/opendaylight/controller/md/sal/test/model/util/ListsBindingUtils.java
new file mode 100644 (file)
index 0000000..0d3e7e8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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.controller.md.sal.test.model.util;
+
+import com.google.common.collect.ImmutableList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeComplexUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.TreeLeafOnlyUsesAugmentBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUses;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUsesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.augment.rev140709.complex.from.grouping.ListViaUsesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.TopBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701.two.level.list.top.level.list.NestedListKey;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+import java.util.Arrays;
+
+public class ListsBindingUtils {
+
+    private static final InstanceIdentifier<Top> TOP_PATH = InstanceIdentifier.create(Top.class);
+
+    private ListsBindingUtils() {
+        throw new UnsupportedOperationException();
+    }
+
+    public static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    public static final TopLevelListKey TOP_BAR_KEY = new TopLevelListKey("bar");
+    public static final ListViaUsesKey USES_ONE_KEY = new ListViaUsesKey("one");
+    public static final ListViaUsesKey USES_TWO_KEY = new ListViaUsesKey("two");
+
+
+    public static InstanceIdentifier<TopLevelList> path(final TopLevelListKey key) {
+        return TOP_PATH.child(TopLevelList.class, key);
+    }
+
+    public static InstanceIdentifier<NestedList> path(final TopLevelListKey top,final NestedListKey nested) {
+        return path(top).child(NestedList.class, nested);
+    }
+
+    public static InstanceIdentifier<ListViaUses> path(final TopLevelListKey top,final ListViaUsesKey uses) {
+        return path(top).augmentation(TreeComplexUsesAugment.class).child(ListViaUses.class, uses);
+    }
+
+    public static <T extends DataObject & Augmentation<TopLevelList>> InstanceIdentifier<T> path(final TopLevelListKey key, final Class<T> augmentation) {
+        return path(key).augmentation(augmentation);
+    }
+
+    public static Top top(final TopLevelList... listItems) {
+        return new TopBuilder().setTopLevelList(Arrays.asList(listItems)).build();
+    }
+
+    public static TopLevelList topLevelList(final TopLevelListKey key) {
+        return new TopLevelListBuilder().setKey(key).build();
+    }
+
+    public static TopLevelList topLevelList(final TopLevelListKey key, final TreeComplexUsesAugment augment) {
+        TopLevelListBuilder builder = new TopLevelListBuilder().setKey(key);
+        builder.addAugmentation(TreeComplexUsesAugment.class, augment);
+        return builder.build();
+    }
+
+    public static TreeComplexUsesAugment complexUsesAugment(final ListViaUsesKey... keys) {
+        ImmutableList.Builder<ListViaUses> listViaUses = ImmutableList.<ListViaUses> builder();
+        for (ListViaUsesKey key : keys) {
+            listViaUses.add(new ListViaUsesBuilder().setKey(key).build());
+        }
+        return new TreeComplexUsesAugmentBuilder().setListViaUses(listViaUses.build()).build();
+    }
+
+    public static TreeLeafOnlyUsesAugment leafOnlyUsesAugment(String leafFromGroupingValue) {
+
+        return new TreeLeafOnlyUsesAugmentBuilder().setLeafFromGrouping(leafFromGroupingValue).build();
+    }
+
+}
diff --git a/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/binding/rev140701/Int32StringUnionBuilder.java b/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/binding/rev140701/Int32StringUnionBuilder.java
new file mode 100644 (file)
index 0000000..7c78c4b
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.binding.rev140701;
+
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ */
+public class Int32StringUnionBuilder {
+
+    public static Int32StringUnion getDefaultInstance(final String defaultValue) {
+        try {
+            return new Int32StringUnion(Integer.parseInt(defaultValue));
+        } catch (NumberFormatException e) {
+            return new Int32StringUnion(defaultValue);
+        }
+    }
+
+}
diff --git a/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/TopLevelBuilder.java b/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/TopLevelBuilder.java
new file mode 100644 (file)
index 0000000..09d8e0d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ */
+public class TopLevelBuilder {
+
+    public static TopLevel getDefaultInstance(java.lang.String defaultValue) {
+        if (defaultValue.length() <= 4) {
+            return new TopLevel(new NonUnionTestType(defaultValue));
+        }
+        else {
+            return new TopLevel(UnionTestTypeBuilder.getDefaultInstance(defaultValue));
+        }
+    }
+
+}
diff --git a/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/UnionTestTypeBuilder.java b/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/UnionTestTypeBuilder.java
new file mode 100644 (file)
index 0000000..613f2dc
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ * 
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ * 
+ */
+public class UnionTestTypeBuilder {
+
+    public static UnionTestType getDefaultInstance(java.lang.String defaultValue) {
+        if (defaultValue.length() > 8) {
+            return new UnionTestType(new LowestLevel1(defaultValue));
+        } else {
+            return new UnionTestType(new LowestLevel2(defaultValue));
+        }
+    }
+
+}
diff --git a/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang b/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-augment-test.yang
new file mode 100644 (file)
index 0000000..04646fc
--- /dev/null
@@ -0,0 +1,183 @@
+module opendaylight-yangtools-augment-test {
+
+    namespace "urn:opendaylight:params:xml:ns:yang:yangtools:test:augment";
+    prefix aug-test;
+
+    import opendaylight-yangtools-binding-test {
+        prefix test;
+    }
+    import yang-ext {
+        prefix ext;
+    }
+
+    description
+        "This module contains a collection of YANG augmentations used for
+        some test cases.";
+
+    revision 2014-07-09 {
+        description
+        "Test model for testing data broker with nested lists.";
+    }
+
+    identity third-party {
+        base test:test-root;
+    }
+
+    grouping leaf-from-grouping {
+        leaf leaf-from-grouping {
+            type string;
+        }
+    }
+
+    grouping complex-from-grouping {
+        container container-with-uses {
+            uses leaf-from-grouping;
+        }
+        list list-via-uses {
+            key "name";
+            leaf name {
+                type string;
+            }
+        }
+    }
+
+    augment "/test:top/test:top-level-list" {
+        ext:augment-identifier tree-leaf-only-uses-augment;
+        uses leaf-from-grouping;
+    }
+
+    augment "/test:top/test:top-level-list" {
+        ext:augment-identifier tree-complex-leaves;
+        leaf simple-type {
+            type int32;
+        }
+        leaf identity {
+            type test:test-identityref;
+        }
+        leaf schema-unaware-union {
+            type test:int32-string-union;
+        }
+
+        leaf simple-type-ref {
+            type leafref {
+                path "../simple-type";
+            }
+        }
+        leaf identity-ref {
+            type leafref {
+                path "../identity";
+            }
+        }
+        leaf schema-unaware-union-ref {
+            type leafref {
+                path "../schema-unaware-union";
+            }
+        }
+    }
+
+
+    augment "/test:put-top/test:input/test:top-level-list" {
+        ext:augment-identifier rpc-leaf-only-uses-augment;
+        uses leaf-from-grouping;
+    }
+
+    augment "/test:top/test:top-level-list" {
+        ext:augment-identifier tree-complex-uses-augment;
+        uses complex-from-grouping;
+    }
+
+    augment "/test:put-top/test:input/test:top-level-list" {
+        ext:augment-identifier rpc-complex-uses-augment;
+        uses complex-from-grouping;
+    }
+
+    augment "/test:top/test:top-level-list" {
+        ext:augment-identifier tree-leaf-only-augment;
+
+        leaf simple-value {
+            type string;
+        }
+    }
+
+    augment "/test:top/test:top-level-list" {
+        ext:augment-identifier tree-second-leaf-only-augment;
+
+        leaf second-simple-value {
+            type string;
+        }
+    }
+
+    augment "/test:put-top/test:input/test:top-level-list" {
+        ext:augment-identifier rpc-leaf-only-augment;
+
+        leaf simple-value {
+            type string;
+        }
+    }
+
+    augment "/test:put-top/test:input/test:top-level-list" {
+        ext:augment-identifier rpc-second-leaf-only-augment;
+
+        leaf second-simple-value {
+            type string;
+        }
+    }
+
+    augment "/test:top/test:top-level-list/test:choice-in-list" {
+        case simple-via-uses {
+            uses leaf-from-grouping;
+        }
+        case complex-via-uses {
+            uses complex-from-grouping;
+        }
+        case empty-leaf {
+            leaf empty-type {
+                type empty;
+            }
+        }
+    }
+
+    augment "/test:put-top/test:input/test:top-level-list/test:choice-in-list" {
+        case simple-via-uses {
+            uses leaf-from-grouping;
+        }
+        case complex-via-uses-with-different-name {
+            uses complex-from-grouping;
+        }
+    }
+
+    augment "/test:top" {
+        ext:augment-identifier top-choice-augment1;
+        choice augment-choice1 {
+            case case1 {
+                container case1-container {
+                    leaf case1-leaf {
+                        type string;
+                    }
+                }
+            }
+
+            case case2 {
+                container case2-container {
+                    leaf case2-leaf {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+    augment "/test:top/augment-choice1/case1" {
+        ext:augment-identifier top-choice-augment2;
+        choice augment-choice2 {
+            case case11 {
+                container case11-choice-case-container {
+                    leaf case11-choice-case-leaf {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+}
diff --git a/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-binding-test.yang b/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-binding-test.yang
new file mode 100644 (file)
index 0000000..5ba1cbc
--- /dev/null
@@ -0,0 +1,119 @@
+module opendaylight-yangtools-binding-test {
+
+    namespace "urn:opendaylight:params:xml:ns:yang:yangtools:test:binding";
+    prefix list-test;
+
+
+    description
+        "This module contains a collection of YANG definitions used for
+        some test cases.";
+
+    revision 2014-07-01 {
+        description
+        "Test model for testing data broker with nested lists.";
+    }
+
+    typedef int32-string-union {
+        type union {
+            type int32;
+            type string;
+        }
+    }
+
+    identity test-root;
+
+    identity test-one {
+        base test-root;
+    }
+
+    identity test-two {
+        base test-root;
+    }
+
+    typedef test-identityref {
+        type identityref {
+            base test-root;
+        }
+    }
+
+    grouping two-level-list {
+        list top-level-list {
+            description
+                "Top Level List";
+            key "name";
+            leaf name {
+                type string;
+            }
+
+            choice choice-in-list {
+                case simple-case {
+                    leaf simple {
+                        type string;
+                    }
+                }
+            }
+
+            list nested-list {
+                key "name";
+                leaf name {
+                    type string;
+                }
+                leaf type {
+                    type string;
+                    mandatory true;
+                    description
+                        "Mandatory type of list.";
+                }
+                ordered-by user;
+                description
+                    "A list of service functions that compose the service chain";
+            }
+        }
+        leaf-list top-level-leaf-list {
+            type string;
+        }
+    }
+
+    grouping choice {
+        choice identifier {
+            case simple {
+                container simple-id {
+                    leaf id {
+                        type int32;
+                    }
+                }
+            }
+            case extended {
+                container extended-id {
+                    leaf id {
+                        type string;
+                    }
+                }
+            }
+        }
+    }
+
+    container top {
+        uses two-level-list;
+    }
+
+    container choice-container {
+        uses choice;
+    }
+
+    rpc put-top {
+        input {
+            uses two-level-list;
+        }
+    }
+
+    notification two-level-list-changed {
+        uses two-level-list;
+    }
+
+    rpc get-top {
+        output {
+            uses two-level-list;
+        }
+    }
+}
diff --git a/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-union-test.yang b/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-union-test.yang
new file mode 100644 (file)
index 0000000..eea063b
--- /dev/null
@@ -0,0 +1,47 @@
+module opendaylight-yangtools-union-test {
+
+    namespace "urn:opendaylight:params:xml:ns:yang:yangtools:test:union";
+    prefix union-test;
+
+
+    description
+        "This module contains a collection of YANG definitions used for
+        some test cases.";
+
+    revision "2015-01-21" {
+        description
+        "Test model for testing union data types.";
+    }
+
+    typedef lowest-level1 {
+        type string;
+    }
+
+    typedef lowest-level2 {
+        type string;
+    }
+
+    typedef non-union-test-type {
+        type string;
+    }
+
+    typedef union-test-type {
+        type union {
+            type lowest-level1;
+            type lowest-level2;
+        }
+    }
+
+    typedef top-level {
+        type union {
+            type non-union-test-type;
+            type union-test-type;
+        }
+    }
+
+    container wrapper {
+        leaf wrap {
+            type top-level;
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-type-provider/pom.xml b/code-generator/binding-type-provider/pom.xml
new file mode 100644 (file)
index 0000000..f192464
--- /dev/null
@@ -0,0 +1,67 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>binding-type-provider</artifactId>
+
+    <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>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.mockito</groupId>
+          <artifactId>mockito-core</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/BaseYangTypes.java b/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/BaseYangTypes.java
new file mode 100644 (file)
index 0000000..ef65b6c
--- /dev/null
@@ -0,0 +1,268 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import org.opendaylight.yangtools.yang.model.util.BaseConstraints;
+
+public final class BaseYangTypes {
+    /**
+     * mapping of basic built-in YANG types (keys) to JAVA
+     * {@link org.opendaylight.yangtools.sal.binding.model.api.Type Type}. This
+     * map is filled with mapping data in static initialization block
+     */
+    private static final Map<String, Type> TYPE_MAP;
+
+    /**
+     * <code>Type</code> representation of <code>boolean</code> YANG type
+     */
+    public static final Type BOOLEAN_TYPE = Types.typeForClass(Boolean.class);
+
+    /**
+     * <code>Type</code> representation of <code>empty</code> YANG type
+     */
+    public static final Type EMPTY_TYPE = Types.typeForClass(Boolean.class);
+
+    public static final Type ENUM_TYPE = Types.typeForClass(Enum.class);
+
+    /**
+     * <code>Type</code> representation of <code>int8</code> YANG type
+     */
+    public static final Type INT8_TYPE = Types.typeForClass(Byte.class);
+
+    /**
+     * <code>Type</code> representation of <code>int16</code> YANG type
+     */
+    public static final Type INT16_TYPE = Types.typeForClass(Short.class);
+
+    /**
+     * <code>Type</code> representation of <code>int32</code> YANG type
+     */
+    public static final Type INT32_TYPE = Types.typeForClass(Integer.class);
+
+    /**
+     * <code>Type</code> representation of <code>int64</code> YANG type
+     */
+    public static final Type INT64_TYPE = Types.typeForClass(Long.class);
+
+    /**
+     * <code>Type</code> representation of <code>string</code> YANG type
+     */
+    public static final Type STRING_TYPE = Types.typeForClass(String.class);
+
+    /**
+     * <code>Type</code> representation of <code>decimal64</code> YANG type
+     */
+    public static final Type DECIMAL64_TYPE = Types.typeForClass(BigDecimal.class);
+
+    /**
+     * <code>Type</code> representation of <code>uint8</code> YANG type
+     */
+    public static final Type UINT8_TYPE = Types.typeForClass(Short.class, singleRangeRestrictions((short)0, (short)255));
+
+    /**
+     * <code>Type</code> representation of <code>uint16</code> YANG type
+     */
+    public static final Type UINT16_TYPE = Types.typeForClass(Integer.class, singleRangeRestrictions(0, 65535));
+
+    /**
+     * <code>Type</code> representation of <code>uint32</code> YANG type
+     */
+    public static final Type UINT32_TYPE = Types.typeForClass(Long.class, singleRangeRestrictions(0L, 4294967295L));
+
+    /**
+     * <code>Type</code> representation of <code>uint64</code> YANG type
+     */
+    public static final Type UINT64_TYPE = Types.typeForClass(BigInteger.class,
+            singleRangeRestrictions(BigInteger.ZERO, new BigInteger("18446744073709551615")));
+
+    public static final Type UNION_TYPE = new UnionType();
+
+    /**
+     * <code>Type</code> representation of <code>binary</code> YANG type
+     */
+    public static final Type BINARY_TYPE = Types.primitiveType("byte[]", null);
+
+    public static final Type INSTANCE_IDENTIFIER = Types.parameterizedTypeFor(Types
+            .typeForClass(InstanceIdentifier.class));
+
+    /**
+     * It is undesirable to create instance of this class.
+     */
+    private BaseYangTypes() {
+        throw new UnsupportedOperationException();
+    }
+
+    static {
+        final Builder<String, Type> b = ImmutableMap.<String, Type>builder();
+
+        b.put("boolean", BOOLEAN_TYPE);
+        b.put("empty", EMPTY_TYPE);
+        b.put("enumeration", ENUM_TYPE);
+        b.put("int8", INT8_TYPE);
+        b.put("int16", INT16_TYPE);
+        b.put("int32", INT32_TYPE);
+        b.put("int64", INT64_TYPE);
+        b.put("string", STRING_TYPE);
+        b.put("decimal64", DECIMAL64_TYPE);
+        b.put("uint8", UINT8_TYPE);
+        b.put("uint16", UINT16_TYPE);
+        b.put("uint32", UINT32_TYPE);
+        b.put("uint64", UINT64_TYPE);
+        b.put("union", UNION_TYPE);
+        b.put("binary", BINARY_TYPE);
+        b.put("instance-identifier", INSTANCE_IDENTIFIER);
+
+        TYPE_MAP = b.build();
+    }
+
+    public static final TypeProvider BASE_YANG_TYPES_PROVIDER = new TypeProvider() {
+        /**
+         * Searches <code>Type</code> value to which is YANG <code>type</code>
+         * mapped.
+         *
+         * @param type
+         *            string with YANG type name
+         * @return java <code>Type</code> representation of <code>type</code>
+         */
+        @Override
+        public Type javaTypeForYangType(final String type) {
+            return TYPE_MAP.get(type);
+        }
+
+        /**
+         * Searches <code>Type</code> value to which is YANG <code>type</code>
+         * mapped.
+         *
+         * @param type
+         *            type definition representation of YANG type
+         * @return java <code>Type</code> representation of <code>type</code>.
+         *         If <code>type</code> isn't found then <code>null</code> is
+         *         returned.
+         */
+        @Override
+        public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode) {
+            if (type != null) {
+                return TYPE_MAP.get(type.getQName().getLocalName());
+            }
+
+            return null;
+        }
+
+        @Override
+        public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode,
+                final Restrictions restrictions) {
+            String typeName = type.getQName().getLocalName();
+            switch (typeName) {
+            case "binary":
+                return restrictions == null ? Types.BYTE_ARRAY : Types.primitiveType("byte[]", restrictions);
+            case "decimal64":
+                return Types.typeForClass(BigDecimal.class, restrictions);
+            case "enumeration":
+                return Types.typeForClass(Enum.class, restrictions);
+            case "int8":
+                return Types.typeForClass(Byte.class, restrictions);
+            case "int16":
+                return Types.typeForClass(Short.class, restrictions);
+            case "int32":
+                return Types.typeForClass(Integer.class, restrictions);
+            case "int64":
+                return Types.typeForClass(Long.class, restrictions);
+            case "string":
+                return Types.typeForClass(String.class, restrictions);
+            case "uint8":
+                return Types.typeForClass(Short.class, restrictions);
+            case "uint16":
+                return Types.typeForClass(Integer.class, restrictions);
+            case "uint32":
+                return Types.typeForClass(Long.class, restrictions);
+            case "uint64":
+                return Types.typeForClass(BigInteger.class, restrictions);
+            case "union" :
+                return UNION_TYPE;
+            default:
+                return javaTypeForSchemaDefinitionType(type, parentNode);
+            }
+        }
+
+        @Override
+        public String getTypeDefaultConstruction(final LeafSchemaNode node) {
+            return null;
+        }
+
+        @Override
+        public String getConstructorPropertyName(final SchemaNode node) {
+            return null;
+        }
+
+        @Override
+        public String getParamNameFromType(final TypeDefinition<?> type) {
+            return "_" + BindingMapping.getPropertyName(type.getQName().getLocalName());
+        }
+    };
+
+    private static <T extends Number> Restrictions singleRangeRestrictions(final T min, final T max) {
+        return new Restrictions() {
+            @Override
+            public boolean isEmpty() {
+                return false;
+            }
+
+            @Override
+            public List<RangeConstraint> getRangeConstraints() {
+                return Collections.singletonList(BaseConstraints.newRangeConstraint(min, max,
+                        Optional.<String> absent(), Optional.<String> absent()));
+            }
+
+            @Override
+            public List<PatternConstraint> getPatternConstraints() {
+                return Collections.emptyList();
+            }
+
+            @Override
+            public List<LengthConstraint> getLengthConstraints() {
+                return Collections.emptyList();
+            }
+        };
+    }
+
+    public static final class UnionType implements Type {
+        @Override
+        public String getPackageName() {
+            return null;
+        }
+        @Override
+        public String getName() {
+            return "Union";
+        }
+        @Override
+        public String getFullyQualifiedName() {
+            return "Union";
+        }
+    }
+
+}
diff --git a/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/GroupingDefinitionDependencySort.java b/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/GroupingDefinitionDependencySort.java
new file mode 100644 (file)
index 0000000..ece776f
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.UsesNode;
+import org.opendaylight.yangtools.yang.parser.util.TopologicalSort;
+import org.opendaylight.yangtools.yang.parser.util.TopologicalSort.Node;
+
+public class GroupingDefinitionDependencySort {
+
+    /**
+     * Sorts set <code>groupingDefinitions</code> according to the mutual
+     * dependencies.<br>
+     *
+     * Elements of <code>groupingDefinitions</code> are firstly transformed to
+     * {@link org.opendaylight.yangtools.yang.parser.util.TopologicalSort.Node
+     * Node} interfaces and then are sorted by
+     * {@link org.opendaylight.yangtools.yang.parser.util.TopologicalSort#sort(Set)
+     * sort()} method of <code>TopologicalSort</code>.<br>
+     * <br>
+     *
+     *
+     * <i>Definition of dependency relation:<br>
+     * The first <code>GroupingDefinition</code> object (in this context)
+     * depends on second <code>GroupingDefinition</code> object if the first one
+     * contains in its set of <code>UsesNode</code> (obtained through
+     * {@link org.opendaylight.yangtools.yang.model.api.DataNodeContainer#getUses()
+     * getUses} method) reference to the second one.</i>
+     *
+     * @param groupingDefinitions
+     *            set of grouping definition which should be sorted according to
+     *            mutual dependencies
+     * @return list of grouping definitiond which are sorted by mutual
+     *         dependencies
+     * @throws IllegalArgumentException
+     *             if <code>groupingDefinitions</code>
+     *
+     */
+    public List<GroupingDefinition> sort(final Collection<GroupingDefinition> groupingDefinitions) {
+        if (groupingDefinitions == null) {
+            throw new IllegalArgumentException("Set of Type Definitions " + "cannot be NULL!");
+        }
+
+        final List<GroupingDefinition> resultGroupingDefinitions = new ArrayList<GroupingDefinition>();
+        final Set<Node> unsorted = groupingDefinitionsToNodes(groupingDefinitions);
+        final List<Node> sortedNodes = TopologicalSort.sort(unsorted);
+        for (Node node : sortedNodes) {
+            NodeWrappedType nodeWrappedType = (NodeWrappedType) node;
+            resultGroupingDefinitions.add((GroupingDefinition) (nodeWrappedType.getWrappedType()));
+        }
+        return resultGroupingDefinitions;
+
+    }
+
+    /**
+     * Wraps every grouping definition to node type and adds to every node
+     * information about dependencies.
+     *
+     * The map with mapping from schema path (represents grouping definition) to
+     * node is created. For every created node (next <i>nodeFrom</i>) is for its
+     * wrapped grouping definition passed the set of its <i>uses nodes</i>
+     * through. For every uses node is found its wrapping node (next as
+     * <i>nodeTo</i>). This dependency relationship between nodeFrom and all
+     * found nodesTo is modeled with creating of one edge from nodeFrom to
+     * nodeTo.
+     *
+     *
+     * @param groupingDefinitions
+     *            set of goruping definition which will be wrapped to nodes
+     *
+     * @return set of nodes where every one contains wrapped grouping definition
+     */
+    private Set<Node> groupingDefinitionsToNodes(final Collection<GroupingDefinition> groupingDefinitions) {
+        final Map<SchemaPath, Node> nodeMap = Maps.newHashMap();
+        final Set<Node> resultNodes = Sets.newHashSet();
+
+        for (final GroupingDefinition groupingDefinition : groupingDefinitions) {
+            final Node node = new NodeWrappedType(groupingDefinition);
+            nodeMap.put(groupingDefinition.getPath(), node);
+            resultNodes.add(node);
+        }
+
+        for (final Node node : resultNodes) {
+            final NodeWrappedType nodeWrappedType = (NodeWrappedType) node;
+            final GroupingDefinition groupingDefinition = (GroupingDefinition) nodeWrappedType.getWrappedType();
+
+            Set<UsesNode> usesNodes = getAllUsesNodes(groupingDefinition);
+
+            for (UsesNode usesNode : usesNodes) {
+                SchemaPath schemaPath = usesNode.getGroupingPath();
+                if (schemaPath != null) {
+                    Node nodeTo = nodeMap.get(schemaPath);
+                    if (nodeTo != null) {
+                        nodeWrappedType.addEdge(nodeTo);
+                    }
+                }
+            }
+        }
+
+        return resultNodes;
+    }
+
+    /**
+     * Returns the set of the uses nodes which are get from uses in
+     * <code>container</code>, from uses in groupings inside
+     * <code>container</code> and from uses inside child nodes of the
+     * <code>container</code>.
+     *
+     * @param container
+     *            data node container which can contain some uses of grouping
+     * @return set of uses nodes which were find in <code>container</code>.
+     */
+    private Set<UsesNode> getAllUsesNodes(final DataNodeContainer container) {
+        Set<UsesNode> ret = new HashSet<>();
+        Set<UsesNode> usesNodes = container.getUses();
+        ret.addAll(usesNodes);
+
+        for (UsesNode usesNode : usesNodes) {
+            for (AugmentationSchema augment : usesNode.getAugmentations()) {
+                ret.addAll(getAllUsesNodes(augment));
+            }
+        }
+        Set<GroupingDefinition> groupings = container.getGroupings();
+        for (GroupingDefinition groupingDefinition : groupings) {
+            ret.addAll(getAllUsesNodes(groupingDefinition));
+        }
+        for (DataSchemaNode childNode : container.getChildNodes()) {
+            if (childNode instanceof DataNodeContainer) {
+                ret.addAll(getAllUsesNodes((DataNodeContainer) childNode));
+            } else if (childNode instanceof ChoiceSchemaNode) {
+                Set<ChoiceCaseNode> cases = ((ChoiceSchemaNode) childNode).getCases();
+                for (ChoiceCaseNode choiceCaseNode : cases) {
+                    ret.addAll(getAllUsesNodes(choiceCaseNode));
+                }
+            }
+        }
+        return ret;
+    }
+
+}
diff --git a/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/NodeWrappedType.java b/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/NodeWrappedType.java
new file mode 100644 (file)
index 0000000..0029a51
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import org.opendaylight.yangtools.yang.parser.util.TopologicalSort.NodeImpl;
+
+public final class NodeWrappedType extends NodeImpl {
+    /**
+     * The payload which is saved inside Node
+     */
+    private final Object wrappedType;
+
+    /**
+     * Create new instance of class <code>NodeWrappedType</code>.
+     * 
+     * @param wrappedType
+     *            object with payload data
+     */
+    NodeWrappedType(Object wrappedType) {
+        this.wrappedType = wrappedType;
+    }
+
+    /**
+     * Gets payload from class
+     * 
+     * @return object with <code>wrappedType</code>
+     */
+    Object getWrappedType() {
+        return wrappedType;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof NodeWrappedType)) {
+            return false;
+        }
+        NodeWrappedType nodeWrappedType = (NodeWrappedType) o;
+        if (!wrappedType.equals(nodeWrappedType.wrappedType)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        return wrappedType.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return "NodeWrappedType{" + "wrappedType=" + wrappedType + '}';
+    }
+
+}
diff --git a/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java b/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java
new file mode 100644 (file)
index 0000000..501b6c3
--- /dev/null
@@ -0,0 +1,1682 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.packageNameForGeneratedType;
+import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
+import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
+import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Sets;
+import com.google.common.io.BaseEncoding;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.commons.lang3.StringEscapeUtils;
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
+import org.opendaylight.yangtools.binding.generator.util.TypeConstants;
+import org.opendaylight.yangtools.binding.generator.util.Types;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.EnumerationBuilderImpl;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
+import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
+import org.opendaylight.yangtools.sal.binding.model.api.AccessModifier;
+import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
+import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty;
+import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
+import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+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.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
+import org.opendaylight.yangtools.yang.model.util.EnumerationType;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+import org.opendaylight.yangtools.yang.model.util.Int16;
+import org.opendaylight.yangtools.yang.model.util.Int32;
+import org.opendaylight.yangtools.yang.model.util.Int64;
+import org.opendaylight.yangtools.yang.model.util.Int8;
+import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.opendaylight.yangtools.yang.model.util.StringType;
+import org.opendaylight.yangtools.yang.model.util.Uint16;
+import org.opendaylight.yangtools.yang.model.util.Uint32;
+import org.opendaylight.yangtools.yang.model.util.Uint64;
+import org.opendaylight.yangtools.yang.model.util.Uint8;
+import org.opendaylight.yangtools.yang.model.util.UnionType;
+import org.opendaylight.yangtools.yang.parser.util.YangValidationException;
+
+public final class TypeProviderImpl implements TypeProvider {
+    private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
+
+    /**
+     * Contains the schema data red from YANG files.
+     */
+    private final SchemaContext schemaContext;
+
+    /**
+     * Map<moduleName, Map<moduleDate, Map<typeName, type>>>
+     */
+    private final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap;
+
+    /**
+     * The map which maps schema paths to JAVA <code>Type</code>.
+     */
+    private final Map<SchemaPath, Type> referencedTypes;
+    private final Map<Module, Set<Type>> additionalTypes;
+
+    /**
+     * Creates new instance of class <code>TypeProviderImpl</code>.
+     *
+     * @param schemaContext
+     *            contains the schema data red from YANG files
+     * @throws IllegalArgumentException
+     *             if <code>schemaContext</code> equal null.
+     */
+    public TypeProviderImpl(final SchemaContext schemaContext) {
+        Preconditions.checkArgument(schemaContext != null, "Schema Context cannot be null!");
+
+        this.schemaContext = schemaContext;
+        this.genTypeDefsContextMap = new HashMap<>();
+        this.referencedTypes = new HashMap<>();
+        this.additionalTypes = new HashMap<>();
+        resolveTypeDefsFromContext();
+    }
+
+    /**
+     * Puts <code>refType</code> to map with key <code>refTypePath</code>
+     *
+     * @param refTypePath
+     *            schema path used as the map key
+     * @param refType
+     *            type which represents the map value
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>refTypePath</code> equal null</li>
+     *             <li>if <code>refType</code> equal null</li>
+     *             </ul>
+     *
+     */
+    public void putReferencedType(final SchemaPath refTypePath, final Type refType) {
+        Preconditions.checkArgument(refTypePath != null,
+                "Path reference of Enumeration Type Definition cannot be NULL!");
+        Preconditions.checkArgument(refType != null, "Reference to Enumeration Type cannot be NULL!");
+        referencedTypes.put(refTypePath, refType);
+    }
+
+    public Map<Module, Set<Type>> getAdditionalTypes() {
+        return additionalTypes;
+    }
+
+    /**
+     *
+     * Converts basic YANG type <code>type</code> to JAVA <code>Type</code>.
+     *
+     * @param type
+     *            string with YANG name of type
+     * @return JAVA <code>Type</code> for YANG type <code>type</code>
+     * @see TypeProvider#javaTypeForYangType(String)
+     */
+    @Override
+    @Deprecated
+    public Type javaTypeForYangType(final String type) {
+        return BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(type);
+    }
+
+    @Override
+    public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
+        return javaTypeForSchemaDefinitionType(typeDefinition, parentNode, null);
+    }
+
+    /**
+     * Converts schema definition type <code>typeDefinition</code> to JAVA
+     * <code>Type</code>
+     *
+     * @param typeDefinition
+     *            type definition which is converted to JAVA type
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>typeDefinition</code> equal null</li>
+     *             <li>if Qname of <code>typeDefinition</code> equal null</li>
+     *             <li>if name of <code>typeDefinition</code> equal null</li>
+     *             </ul>
+     */
+    @Override
+    public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
+            final Restrictions r) {
+        Type returnType;
+        Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
+        Preconditions.checkArgument(typeDefinition.getQName() != null,
+                "Type Definition cannot have non specified QName (QName cannot be NULL!)");
+        String typedefName = typeDefinition.getQName().getLocalName();
+        Preconditions.checkArgument(typedefName != null, "Type Definitions Local Name cannot be NULL!");
+
+        if (typeDefinition instanceof ExtendedType) {
+            returnType = javaTypeForExtendedType(typeDefinition);
+            if (r != null && returnType instanceof GeneratedTransferObject) {
+                GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
+                Module module = findParentModule(schemaContext, parentNode);
+                String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+                String packageName = packageNameForGeneratedType(basePackageName, typeDefinition.getPath());
+                String genTOName = BindingMapping.getClassName(typedefName);
+                String name = packageName + "." + genTOName;
+                if (!(returnType.getFullyQualifiedName().equals(name))) {
+                    returnType = shadedTOWithRestrictions(gto, r);
+                }
+            }
+        } else {
+            returnType = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode);
+            if (returnType == null) {
+                returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(typeDefinition.getQName()
+                        .getLocalName());
+            }
+        }
+        return returnType;
+    }
+
+    private static GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto, final Restrictions r) {
+        GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName());
+        GeneratedTransferObject parent = gto.getSuperType();
+        if (parent != null) {
+            gtob.setExtendsType(parent);
+        }
+        gtob.setRestrictions(r);
+        for (GeneratedProperty gp : gto.getProperties()) {
+            GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
+            gpb.setValue(gp.getValue());
+            gpb.setReadOnly(gp.isReadOnly());
+            gpb.setAccessModifier(gp.getAccessModifier());
+            gpb.setReturnType(gp.getReturnType());
+            gpb.setFinal(gp.isFinal());
+            gpb.setStatic(gp.isStatic());
+        }
+        return gtob.toInstance();
+    }
+
+    private boolean isLeafRefSelfReference(final LeafrefTypeDefinition leafref, final SchemaNode parentNode) {
+        final SchemaNode leafRefValueNode;
+        final RevisionAwareXPath leafRefXPath = leafref.getPathStatement();
+        final RevisionAwareXPath leafRefStrippedXPath = new RevisionAwareXPathImpl(leafRefXPath.toString()
+                .replaceAll("\\[(.*?)\\]", ""), leafRefXPath.isAbsolute());
+
+        ///// skip leafrefs in augments - they're checked once augments are resolved
+        final Iterator<QName> iterator = parentNode.getPath().getPathFromRoot().iterator();
+        boolean isAugmenting = false;
+        DataNodeContainer current = null;
+        DataSchemaNode dataChildByName;
+
+        while (iterator.hasNext() && !isAugmenting) {
+            final QName next = iterator.next();
+            if (current == null) {
+                dataChildByName = schemaContext.getDataChildByName(next);
+            } else {
+                dataChildByName = current.getDataChildByName(next);
+            }
+            if (dataChildByName != null) {
+                isAugmenting = dataChildByName.isAugmenting();
+            } else {
+                return false;
+            }
+            if (dataChildByName instanceof DataNodeContainer) {
+                current = (DataNodeContainer) dataChildByName;
+            }
+        }
+        if (isAugmenting) {
+            return false;
+        }
+        /////
+
+        Module parentModule = getParentModule(parentNode);
+        if (!leafRefStrippedXPath.isAbsolute()) {
+            leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
+                    parentNode, leafRefStrippedXPath);
+        } else {
+            leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath);
+        }
+        return (leafRefValueNode != null) ? leafRefValueNode.equals(parentNode) : false;
+    }
+
+    /**
+     * Returns JAVA <code>Type</code> for instances of the type
+     * <code>LeafrefTypeDefinition</code> or
+     * <code>IdentityrefTypeDefinition</code>.
+     *
+     * @param typeDefinition
+     *            type definition which is converted to JAVA <code>Type</code>
+     * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
+     */
+    private Type javaTypeForLeafrefOrIdentityRef(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
+        if (typeDefinition instanceof LeafrefTypeDefinition) {
+            final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition;
+            if (isLeafRefSelfReference(leafref, parentNode)) {
+                throw new YangValidationException("Leafref " + leafref.toString() + " is referencing itself, incoming" +
+                        " StackOverFlowError detected.");
+            }
+            return provideTypeForLeafref(leafref, parentNode);
+        } else if (typeDefinition instanceof IdentityrefTypeDefinition) {
+            final IdentityrefTypeDefinition idref = (IdentityrefTypeDefinition) typeDefinition;
+            return provideTypeForIdentityref(idref);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Returns JAVA <code>Type</code> for instances of the type
+     * <code>ExtendedType</code>.
+     *
+     * @param typeDefinition
+     *            type definition which is converted to JAVA <code>Type</code>
+     * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
+     */
+    private Type javaTypeForExtendedType(final TypeDefinition<?> typeDefinition) {
+        final String typedefName = typeDefinition.getQName().getLocalName();
+        final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
+        Type returnType = javaTypeForLeafrefOrIdentityRef(baseTypeDef, typeDefinition);
+        if (returnType == null) {
+            if (baseTypeDef instanceof EnumTypeDefinition) {
+                final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDef;
+                returnType = provideTypeForEnum(enumTypeDef, typedefName, typeDefinition);
+            } else {
+                final Module module = findParentModule(schemaContext, typeDefinition);
+                Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
+                if (module != null) {
+                    final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
+                    final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
+                    if (genTOs != null) {
+                        returnType = genTOs.get(typedefName);
+                    }
+                    if (returnType == null) {
+                        returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
+                                baseTypeDef, typeDefinition, r);
+                    }
+                }
+            }
+        }
+        return returnType;
+    }
+
+    /**
+     * Seeks for identity reference <code>idref</code> the JAVA
+     * <code>type</code>.<br />
+     * <br />
+     *
+     * <i>Example:<br />
+     * If identy which is referenced via <code>idref</code> has name <b>Idn</b>
+     * then returning type is <b>{@code Class<? extends Idn>}</b></i>
+     *
+     * @param idref
+     *            identityref type definition for which JAVA <code>Type</code>
+     *            is sought
+     * @return JAVA <code>Type</code> of the identity which is refrenced through
+     *         <code>idref</code>
+     */
+    private Type provideTypeForIdentityref(final IdentityrefTypeDefinition idref) {
+        QName baseIdQName = idref.getIdentity().getQName();
+        Module module = schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
+                baseIdQName.getRevision());
+        IdentitySchemaNode identity = null;
+        for (IdentitySchemaNode id : module.getIdentities()) {
+            if (id.getQName().equals(baseIdQName)) {
+                identity = id;
+            }
+        }
+        Preconditions.checkArgument(identity != null, "Target identity '" + baseIdQName + "' do not exists");
+
+        final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+        final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
+        final String genTypeName = BindingMapping.getClassName(identity.getQName());
+
+        Type baseType = Types.typeForClass(Class.class);
+        Type paramType = Types.wildcardTypeFor(packageName, genTypeName);
+        return Types.parameterizedTypeFor(baseType, paramType);
+    }
+
+    /**
+     * Converts <code>typeDefinition</code> to concrete JAVA <code>Type</code>.
+     *
+     * @param typeDefinition
+     *            type definition which should be converted to JAVA
+     *            <code>Type</code>
+     * @return JAVA <code>Type</code> which represents
+     *         <code>typeDefinition</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>typeDefinition</code> equal null</li>
+     *             <li>if Q name of <code>typeDefinition</code></li>
+     *             <li>if name of <code>typeDefinition</code></li>
+     *             </ul>
+     */
+    public Type generatedTypeForExtendedDefinitionType(final TypeDefinition<?> typeDefinition,
+            final SchemaNode parentNode) {
+        Type returnType = null;
+        Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
+        if (typeDefinition.getQName() == null) {
+            throw new IllegalArgumentException(
+                    "Type Definition cannot have non specified QName (QName cannot be NULL!)");
+        }
+        Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
+                "Type Definitions Local Name cannot be NULL!");
+
+        final String typedefName = typeDefinition.getQName().getLocalName();
+        if (typeDefinition instanceof ExtendedType) {
+            final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
+
+            if (!(baseTypeDef instanceof LeafrefTypeDefinition) && !(baseTypeDef instanceof IdentityrefTypeDefinition)) {
+                final Module module = findParentModule(schemaContext, parentNode);
+
+                if (module != null) {
+                    final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
+                    final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
+                    if (genTOs != null) {
+                        returnType = genTOs.get(typedefName);
+                    }
+                }
+            }
+        }
+        return returnType;
+    }
+
+    /**
+     * Gets base type definition for <code>extendTypeDef</code>. The method is
+     * recursivelly called until non <code>ExtendedType</code> type is found.
+     *
+     * @param extendTypeDef
+     *            type definition for which is the base type definition sought
+     * @return type definition which is base type for <code>extendTypeDef</code>
+     * @throws IllegalArgumentException
+     *             if <code>extendTypeDef</code> equal null
+     */
+    private TypeDefinition<?> baseTypeDefForExtendedType(final TypeDefinition<?> extendTypeDef) {
+        Preconditions.checkArgument(extendTypeDef != null, "Type Definition reference cannot be NULL!");
+        final TypeDefinition<?> baseTypeDef = extendTypeDef.getBaseType();
+        if (baseTypeDef == null) {
+            return extendTypeDef;
+        } else if (baseTypeDef instanceof ExtendedType) {
+            return baseTypeDefForExtendedType(baseTypeDef);
+        } else {
+            return baseTypeDef;
+        }
+
+    }
+
+    /**
+     * Converts <code>leafrefType</code> to JAVA <code>Type</code>.
+     *
+     * The path of <code>leafrefType</code> is followed to find referenced node
+     * and its <code>Type</code> is returned.
+     *
+     * @param leafrefType
+     *            leafref type definition for which is the type sought
+     * @return JAVA <code>Type</code> of data schema node which is referenced in
+     *         <code>leafrefType</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>leafrefType</code> equal null</li>
+     *             <li>if path statement of <code>leafrefType</code> equal null</li>
+     *             </ul>
+     *
+     */
+    public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode) {
+        Type returnType = null;
+        Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!");
+
+        Preconditions.checkArgument(leafrefType.getPathStatement() != null,
+                "The Path Statement for Leafref Type Definition cannot be NULL!");
+
+        final RevisionAwareXPath xpath = leafrefType.getPathStatement();
+        final String strXPath = xpath.toString();
+
+        if (strXPath != null) {
+            if (strXPath.indexOf('[') == -1) {
+                final Module module = findParentModule(schemaContext, parentNode);
+                if (module != null) {
+                    final SchemaNode dataNode;
+                    if (xpath.isAbsolute()) {
+                        dataNode = findDataSchemaNode(schemaContext, module, xpath);
+                    } else {
+                        dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
+                    }
+
+                    if (leafContainsEnumDefinition(dataNode)) {
+                        returnType = referencedTypes.get(dataNode.getPath());
+                    } else if (leafListContainsEnumDefinition(dataNode)) {
+                        returnType = Types.listTypeFor(referencedTypes.get(dataNode.getPath()));
+                    } else {
+                        returnType = resolveTypeFromDataSchemaNode(dataNode);
+                    }
+                }
+            } else {
+                returnType = Types.typeForClass(Object.class);
+            }
+        }
+        if (returnType == null) {
+            throw new IllegalArgumentException("Failed to find leafref target: " + strXPath);
+        }
+        return returnType;
+    }
+
+    /**
+     * Checks if <code>dataNode</code> is <code>LeafSchemaNode</code> and if it
+     * so then checks if it is of type <code>EnumTypeDefinition</code>.
+     *
+     * @param dataNode
+     *            data schema node for which is checked if it is leaf and if it
+     *            is of enum type
+     * @return boolean value
+     *         <ul>
+     *         <li>true - if <code>dataNode</code> is leaf of type enumeration</li>
+     *         <li>false - other cases</li>
+     *         </ul>
+     */
+    private static boolean leafContainsEnumDefinition(final SchemaNode dataNode) {
+        if (dataNode instanceof LeafSchemaNode) {
+            final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
+            if (leaf.getType() instanceof EnumTypeDefinition) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Checks if <code>dataNode</code> is <code>LeafListSchemaNode</code> and if
+     * it so then checks if it is of type <code>EnumTypeDefinition</code>.
+     *
+     * @param dataNode
+     *            data schema node for which is checked if it is leaflist and if
+     *            it is of enum type
+     * @return boolean value
+     *         <ul>
+     *         <li>true - if <code>dataNode</code> is leaflist of type
+     *         enumeration</li>
+     *         <li>false - other cases</li>
+     *         </ul>
+     */
+    private static boolean leafListContainsEnumDefinition(final SchemaNode dataNode) {
+        if (dataNode instanceof LeafListSchemaNode) {
+            final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
+            if (leafList.getType() instanceof EnumTypeDefinition) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Converts <code>enumTypeDef</code> to
+     * {@link org.opendaylight.yangtools.sal.binding.model.api.Enumeration
+     * enumeration}.
+     *
+     * @param enumTypeDef
+     *            enumeration type definition which is converted to enumeration
+     * @param enumName
+     *            string with name which is used as the enumeration name
+     * @return enumeration type which is built with data (name, enum values)
+     *         from <code>enumTypeDef</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>enumTypeDef</code> equals null</li>
+     *             <li>if enum values of <code>enumTypeDef</code> equal null</li>
+     *             <li>if Q name of <code>enumTypeDef</code> equal null</li>
+     *             <li>if name of <code>enumTypeDef</code> equal null</li>
+     *             </ul>
+     */
+    private Enumeration provideTypeForEnum(final EnumTypeDefinition enumTypeDef, final String enumName,
+            final SchemaNode parentNode) {
+        Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
+        Preconditions.checkArgument(enumTypeDef.getValues() != null,
+                "EnumTypeDefinition MUST contain at least ONE value definition!");
+        Preconditions.checkArgument(enumTypeDef.getQName() != null, "EnumTypeDefinition MUST contain NON-NULL QName!");
+        Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
+                "Local Name in EnumTypeDefinition QName cannot be NULL!");
+
+        final String enumerationName = BindingMapping.getClassName(enumName);
+
+        Module module = findParentModule(schemaContext, parentNode);
+        final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+
+        final EnumerationBuilderImpl enumBuilder = new EnumerationBuilderImpl(basePackageName, enumerationName);
+        enumBuilder.setDescription(enumTypeDef.getDescription());
+        enumBuilder.setReference(enumTypeDef.getReference());
+        enumBuilder.setModuleName(module.getName());
+        enumBuilder.setSchemaPath(enumTypeDef.getPath().getPathFromRoot());
+        enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
+        return enumBuilder.toInstance(null);
+    }
+
+    /**
+     * Adds enumeration to <code>typeBuilder</code>. The enumeration data are
+     * taken from <code>enumTypeDef</code>.
+     *
+     * @param enumTypeDef
+     *            enumeration type definition is source of enumeration data for
+     *            <code>typeBuilder</code>
+     * @param enumName
+     *            string with the name of enumeration
+     * @param typeBuilder
+     *            generated type builder to which is enumeration added
+     * @return enumeration type which contains enumeration data form
+     *         <code>enumTypeDef</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>enumTypeDef</code> equals null</li>
+     *             <li>if enum values of <code>enumTypeDef</code> equal null</li>
+     *             <li>if Q name of <code>enumTypeDef</code> equal null</li>
+     *             <li>if name of <code>enumTypeDef</code> equal null</li>
+     *             <li>if name of <code>typeBuilder</code> equal null</li>
+     *             </ul>
+     *
+     */
+    private static Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef, final String enumName,
+            final GeneratedTypeBuilderBase<?> typeBuilder) {
+        Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
+        Preconditions.checkArgument(enumTypeDef.getValues() != null,
+                "EnumTypeDefinition MUST contain at least ONE value definition!");
+        Preconditions.checkArgument(enumTypeDef.getQName() != null, "EnumTypeDefinition MUST contain NON-NULL QName!");
+        Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
+                "Local Name in EnumTypeDefinition QName cannot be NULL!");
+        Preconditions.checkArgument(typeBuilder != null, "Generated Type Builder reference cannot be NULL!");
+
+        final String enumerationName = BindingMapping.getClassName(enumName);
+
+        final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
+        enumBuilder.setDescription(enumTypeDef.getDescription());
+        enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
+        return enumBuilder.toInstance(enumBuilder);
+    }
+
+    /**
+     * Converts <code>dataNode</code> to JAVA <code>Type</code>.
+     *
+     * @param dataNode
+     *            contains information about YANG type
+     * @return JAVA <code>Type</code> representation of <code>dataNode</code>
+     */
+    private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode) {
+        Type returnType = null;
+        if (dataNode != null) {
+            if (dataNode instanceof LeafSchemaNode) {
+                final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
+                returnType = javaTypeForSchemaDefinitionType(leaf.getType(), leaf);
+            } else if (dataNode instanceof LeafListSchemaNode) {
+                final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
+                returnType = javaTypeForSchemaDefinitionType(leafList.getType(), leafList);
+            }
+        }
+        return returnType;
+    }
+
+    /**
+     * Passes through all modules and through all its type definitions and
+     * convert it to generated types.
+     *
+     * The modules are firstly sorted by mutual dependencies. The modules are
+     * sequentially passed. All type definitions of a module are at the
+     * beginning sorted so that type definition with less amount of references
+     * to other type definition are processed first.<br />
+     * For each module is created mapping record in the map
+     * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap}
+     * which map current module name to the map which maps type names to
+     * returned types (generated types).
+     *
+     */
+    private void resolveTypeDefsFromContext() {
+        final Set<Module> modules = schemaContext.getModules();
+        Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL!");
+        final Module[] modulesArray = new Module[modules.size()];
+        int i = 0;
+        for (Module modul : modules) {
+            modulesArray[i++] = modul;
+        }
+        final List<Module> modulesSortedByDependency = org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort
+                .sort(modulesArray);
+
+        for (final Module module : modulesSortedByDependency) {
+            Map<Date, Map<String, Type>> dateTypeMap = genTypeDefsContextMap.get(module.getName());
+            if (dateTypeMap == null) {
+                dateTypeMap = new HashMap<>();
+            }
+            dateTypeMap.put(module.getRevision(), Collections.<String, Type>emptyMap());
+            genTypeDefsContextMap.put(module.getName(), dateTypeMap);
+        }
+
+        for (final Module module : modulesSortedByDependency) {
+            if (module == null) {
+                continue;
+            }
+            final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+
+            final DataNodeIterator it = new DataNodeIterator(module);
+            final List<TypeDefinition<?>> typeDefinitions = it.allTypedefs();
+            final List<TypeDefinition<?>> listTypeDefinitions = sortTypeDefinitionAccordingDepth(typeDefinitions);
+
+            if ((listTypeDefinitions != null) && (basePackageName != null)) {
+                for (final TypeDefinition<?> typedef : listTypeDefinitions) {
+                    typedefToGeneratedType(basePackageName, module, typedef);
+                }
+            }
+        }
+    }
+
+    /**
+     *
+     * @param basePackageName
+     *            string with name of package to which the module belongs
+     * @param module
+     *            string with the name of the module for to which the
+     *            <code>typedef</code> belongs
+     * @param typedef
+     *            type definition of the node for which should be creted JAVA
+     *            <code>Type</code> (usually generated TO)
+     * @return JAVA <code>Type</code> representation of <code>typedef</code> or
+     *         <code>null</code> value if <code>basePackageName</code> or
+     *         <code>modulName</code> or <code>typedef</code> or Q name of
+     *         <code>typedef</code> equals <code>null</code>
+     */
+    private Type typedefToGeneratedType(final String basePackageName, final Module module,
+            final TypeDefinition<?> typedef) {
+        final String moduleName = module.getName();
+        final Date moduleRevision = module.getRevision();
+        if ((basePackageName != null) && (moduleName != null) && (typedef != null) && (typedef.getQName() != null)) {
+            final String typedefName = typedef.getQName().getLocalName();
+            final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
+            if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
+                    && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) {
+                Type returnType = null;
+                if (innerTypeDefinition instanceof ExtendedType) {
+                    ExtendedType innerExtendedType = (ExtendedType) innerTypeDefinition;
+                    returnType = provideGeneratedTOFromExtendedType(typedef, innerExtendedType, basePackageName,
+                            module.getName());
+                } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
+                    final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
+                            (UnionTypeDefinition) innerTypeDefinition, typedefName, typedef);
+                    genTOBuilder.setTypedef(true);
+                    genTOBuilder.setIsUnion(true);
+                    addUnitsToGenTO(genTOBuilder, typedef.getUnits());
+                    makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
+                    returnType = genTOBuilder.toInstance();
+                    // union builder
+                    GeneratedTOBuilder unionBuilder = new GeneratedTOBuilderImpl(genTOBuilder.getPackageName(),
+                            genTOBuilder.getName() + "Builder");
+                    unionBuilder.setIsUnionBuilder(true);
+                    MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
+                    method.setReturnType(returnType);
+                    method.addParameter(Types.STRING, "defaultValue");
+                    method.setAccessModifier(AccessModifier.PUBLIC);
+                    method.setStatic(true);
+                    Set<Type> types = additionalTypes.get(module);
+                    if (types == null) {
+                        types = Sets.<Type> newHashSet(unionBuilder.toInstance());
+                        additionalTypes.put(module, types);
+                    } else {
+                        types.add(unionBuilder.toInstance());
+                    }
+                } else if (innerTypeDefinition instanceof EnumTypeDefinition) {
+                    // enums are automatically Serializable
+                    final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypeDefinition;
+                    // TODO units for typedef enum
+                    returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef);
+                } else if (innerTypeDefinition instanceof BitsTypeDefinition) {
+                    final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition;
+                    final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForBitsTypeDefinition(
+                            basePackageName, bitsTypeDefinition, typedefName, module.getName());
+                    genTOBuilder.setTypedef(true);
+                    addUnitsToGenTO(genTOBuilder, typedef.getUnits());
+                    makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
+                    returnType = genTOBuilder.toInstance();
+                } else {
+                    final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
+                            innerTypeDefinition, typedef);
+                    returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName());
+                }
+                if (returnType != null) {
+                    final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(moduleName);
+                    Map<String, Type> typeMap = modulesByDate.get(moduleRevision);
+                    if (typeMap != null) {
+                        if (typeMap.isEmpty()) {
+                            typeMap = new HashMap<>(4);
+                            modulesByDate.put(moduleRevision, typeMap);
+                        }
+                        typeMap.put(typedefName, returnType);
+                    }
+                    return returnType;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Wraps base YANG type to generated TO.
+     *
+     * @param basePackageName
+     *            string with name of package to which the module belongs
+     * @param typedef
+     *            type definition which is converted to the TO
+     * @param javaType
+     *            JAVA <code>Type</code> to which is <code>typedef</code> mapped
+     * @return generated transfer object which represent<code>javaType</code>
+     */
+    private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition<?> typedef,
+            final Type javaType, final String moduleName) {
+        Preconditions.checkNotNull(javaType, "javaType cannot be null");
+        final String propertyName = "value";
+
+        final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef, moduleName);
+        genTOBuilder.setRestrictions(BindingGeneratorUtil.getRestrictions(typedef));
+        final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(propertyName);
+        genPropBuilder.setReturnType(javaType);
+        genTOBuilder.addEqualsIdentity(genPropBuilder);
+        genTOBuilder.addHashIdentity(genPropBuilder);
+        genTOBuilder.addToStringProperty(genPropBuilder);
+        if (javaType instanceof ConcreteType && "String".equals(javaType.getName()) && typedef instanceof ExtendedType) {
+            final List<String> regExps = resolveRegExpressionsFromTypedef((ExtendedType) typedef);
+            addStringRegExAsConstant(genTOBuilder, regExps);
+        }
+        addUnitsToGenTO(genTOBuilder, typedef.getUnits());
+        genTOBuilder.setTypedef(true);
+        makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
+        return genTOBuilder.toInstance();
+    }
+
+    /**
+     * Converts output list of generated TO builders to one TO builder (first
+     * from list) which contains the remaining builders as its enclosing TO.
+     *
+     * @param basePackageName
+     *            string with name of package to which the module belongs
+     * @param typedef
+     *            type definition which should be of type
+     *            <code>UnionTypeDefinition</code>
+     * @param typeDefName
+     *            string with name for generated TO
+     * @return generated TO builder with the list of enclosed generated TO
+     *         builders
+     */
+    public GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final String basePackageName,
+            final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode) {
+        final List<GeneratedTOBuilder> genTOBuilders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
+                typedef, typeDefName, parentNode);
+        GeneratedTOBuilder resultTOBuilder = null;
+        if (genTOBuilders.isEmpty()) {
+            throw new IllegalStateException("No GeneratedTOBuilder objects generated from union " + typedef);
+        }
+
+        resultTOBuilder = genTOBuilders.remove(0);
+        for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
+            resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
+        }
+
+        final GeneratedPropertyBuilder genPropBuilder = resultTOBuilder.addProperty("value");
+        genPropBuilder.setReturnType(Types.CHAR_ARRAY);
+        resultTOBuilder.addEqualsIdentity(genPropBuilder);
+        resultTOBuilder.addHashIdentity(genPropBuilder);
+        resultTOBuilder.addToStringProperty(genPropBuilder);
+
+        return resultTOBuilder;
+    }
+
+    /**
+     * Converts <code>typedef</code> to generated TO with
+     * <code>typeDefName</code>. Every union type from <code>typedef</code> is
+     * added to generated TO builder as property.
+     *
+     * @param basePackageName
+     *            string with name of package to which the module belongs
+     * @param typedef
+     *            type definition which should be of type
+     *            <code>UnionTypeDefinition</code>
+     * @param typeDefName
+     *            string with name for generated TO
+     * @return generated TO builder which represents <code>typedef</code>
+     * @throws NullPointerException
+     *             <ul>
+     *             <li>if <code>basePackageName</code> is null</li>
+     *             <li>if <code>typedef</code> is null</li>
+     *             <li>if Qname of <code>typedef</code> is null</li>
+     *             </ul>
+     */
+    public List<GeneratedTOBuilder> provideGeneratedTOBuildersForUnionTypeDef(final String basePackageName,
+            final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode) {
+        Preconditions.checkNotNull(basePackageName, "Base Package Name cannot be NULL!");
+        Preconditions.checkNotNull(typedef, "Type Definition cannot be NULL!");
+        Preconditions.checkNotNull(typedef.getQName(), "Type definition QName cannot be NULL!");
+
+        final List<GeneratedTOBuilder> generatedTOBuilders = new ArrayList<>();
+        final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
+        final Module module = findParentModule(schemaContext, parentNode);
+
+        final GeneratedTOBuilderImpl unionGenTOBuilder;
+        if (typeDefName != null && !typeDefName.isEmpty()) {
+            final String typeName = BindingMapping.getClassName(typeDefName);
+            unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+            unionGenTOBuilder.setDescription(typedef.getDescription());
+            unionGenTOBuilder.setReference(typedef.getReference());
+            unionGenTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
+            unionGenTOBuilder.setModuleName(module.getName());
+        } else {
+            unionGenTOBuilder = typedefToTransferObject(basePackageName, typedef, module.getName());
+        }
+
+        generatedTOBuilders.add(unionGenTOBuilder);
+        unionGenTOBuilder.setIsUnion(true);
+        final List<String> regularExpressions = new ArrayList<String>();
+        for (final TypeDefinition<?> unionType : unionTypes) {
+            final String unionTypeName = unionType.getQName().getLocalName();
+            if (unionType instanceof UnionType) {
+                generatedTOBuilders.addAll(resolveUnionSubtypeAsUnion(unionGenTOBuilder, (UnionType) unionType,
+                        basePackageName, parentNode));
+            } else if (unionType instanceof ExtendedType) {
+                resolveExtendedSubtypeAsUnion(unionGenTOBuilder, (ExtendedType) unionType, regularExpressions,
+                        parentNode);
+            } else if (unionType instanceof EnumTypeDefinition) {
+                final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType,
+                        unionTypeName, unionGenTOBuilder);
+                updateUnionTypeAsProperty(unionGenTOBuilder, enumeration, unionTypeName);
+            } else {
+                final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(unionType,
+                        parentNode);
+                updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName);
+            }
+        }
+        if (!regularExpressions.isEmpty()) {
+            addStringRegExAsConstant(unionGenTOBuilder, regularExpressions);
+        }
+
+        storeGenTO(typedef, unionGenTOBuilder, parentNode);
+
+        return generatedTOBuilders;
+    }
+
+    /**
+     * Wraps code which handle case when union subtype is also of the type
+     * <code>UnionType</code>.
+     *
+     * In this case the new generated TO is created for union subtype (recursive
+     * call of method
+     * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, UnionTypeDefinition,
+     * String, SchemaNode)}
+     * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder
+     * <code>parentUnionGenTOBuilder</code> is created property which type is
+     * equal to new generated TO.
+     *
+     * @param parentUnionGenTOBuilder
+     *            generated TO builder to which is the property with the child
+     *            union subtype added
+     * @param basePackageName
+     *            string with the name of the module package
+     * @param unionSubtype
+     *            type definition which represents union subtype
+     * @return list of generated TO builders. The number of the builders can be
+     *         bigger one due to recursive call of
+     *         <code>provideGeneratedTOBuildersForUnionTypeDef</code> method.
+     */
+    private List<GeneratedTOBuilder> resolveUnionSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
+            final UnionTypeDefinition unionSubtype, final String basePackageName, final SchemaNode parentNode) {
+        final String newTOBuilderName = provideAvailableNameForGenTOBuilder(parentUnionGenTOBuilder.getName());
+        final List<GeneratedTOBuilder> subUnionGenTOBUilders = provideGeneratedTOBuildersForUnionTypeDef(
+                basePackageName, unionSubtype, newTOBuilderName, parentNode);
+
+        final GeneratedPropertyBuilder propertyBuilder;
+        propertyBuilder = parentUnionGenTOBuilder.addProperty(BindingMapping.getPropertyName(newTOBuilderName));
+        propertyBuilder.setReturnType(subUnionGenTOBUilders.get(0));
+        parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder);
+        parentUnionGenTOBuilder.addToStringProperty(propertyBuilder);
+
+        return subUnionGenTOBUilders;
+    }
+
+    /**
+     * Wraps code which handle case when union subtype is of the type
+     * <code>ExtendedType</code>.
+     *
+     * If TO for this type already exists it is used for the creation of the
+     * property in <code>parentUnionGenTOBuilder</code>. In other case the base
+     * type is used for the property creation.
+     *
+     * @param parentUnionGenTOBuilder
+     *            generated TO builder in which new property is created
+     * @param unionSubtype
+     *            type definition of the <code>ExtendedType</code> type which
+     *            represents union subtype
+     * @param regularExpressions
+     *            list of strings with the regular expressions
+     * @param parentNode
+     *            parent Schema Node for Extended Subtype
+     *
+     */
+    private void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
+            final ExtendedType unionSubtype, final List<String> regularExpressions, final SchemaNode parentNode) {
+        final String unionTypeName = unionSubtype.getQName().getLocalName();
+        final Type genTO = findGenTO(unionTypeName, unionSubtype);
+        if (genTO != null) {
+            updateUnionTypeAsProperty(parentUnionGenTOBuilder, genTO, genTO.getName());
+        } else {
+            final TypeDefinition<?> baseType = baseTypeDefForExtendedType(unionSubtype);
+            if (unionTypeName.equals(baseType.getQName().getLocalName())) {
+                final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType,
+                        parentNode);
+                if (javaType != null) {
+                    updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
+                }
+            }
+            if (baseType instanceof StringType) {
+                regularExpressions.addAll(resolveRegExpressionsFromTypedef(unionSubtype));
+            }
+        }
+    }
+
+    /**
+     * Searches for generated TO for <code>searchedTypeDef</code> type
+     * definition in {@link #genTypeDefsContextMap genTypeDefsContextMap}
+     *
+     * @param searchedTypeName
+     *            string with name of <code>searchedTypeDef</code>
+     * @return generated TO for <code>searchedTypeDef</code> or
+     *         <code>null</code> it it doesn't exist
+     */
+    private Type findGenTO(final String searchedTypeName, final SchemaNode parentNode) {
+        final Module typeModule = findParentModule(schemaContext, parentNode);
+        if (typeModule != null && typeModule.getName() != null) {
+            final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(typeModule.getName());
+            final Map<String, Type> genTOs = modulesByDate.get(typeModule.getRevision());
+            if (genTOs != null) {
+                return genTOs.get(searchedTypeName);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Stores generated TO created from <code>genTOBuilder</code> for
+     * <code>newTypeDef</code> to {@link #genTypeDefsContextMap
+     * genTypeDefsContextMap} if the module for <code>newTypeDef</code> exists
+     *
+     * @param newTypeDef
+     *            type definition for which is <code>genTOBuilder</code> created
+     * @param genTOBuilder
+     *            generated TO builder which is converted to generated TO and
+     *            stored
+     */
+    private void storeGenTO(final TypeDefinition<?> newTypeDef, final GeneratedTOBuilder genTOBuilder,
+            final SchemaNode parentNode) {
+        if (!(newTypeDef instanceof UnionType)) {
+
+            final Module parentModule = findParentModule(schemaContext, parentNode);
+            if (parentModule != null && parentModule.getName() != null) {
+                Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(parentModule.getName());
+                Map<String, Type> genTOsMap = modulesByDate.get(parentModule.getRevision());
+                genTOsMap.put(newTypeDef.getQName().getLocalName(), genTOBuilder.toInstance());
+            }
+        }
+    }
+
+    /**
+     * Adds a new property with the name <code>propertyName</code> and with type
+     * <code>type</code> to <code>unonGenTransObject</code>.
+     *
+     * @param unionGenTransObject
+     *            generated TO to which should be property added
+     * @param type
+     *            JAVA <code>type</code> of the property which should be added
+     *            to <code>unionGentransObject</code>
+     * @param propertyName
+     *            string with name of property which should be added to
+     *            <code>unionGentransObject</code>
+     */
+    private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type,
+            final String propertyName) {
+        if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) {
+            final GeneratedPropertyBuilder propBuilder = unionGenTransObject
+                    .addProperty(BindingMapping.getPropertyName(propertyName));
+            propBuilder.setReturnType(type);
+
+            unionGenTransObject.addEqualsIdentity(propBuilder);
+            unionGenTransObject.addHashIdentity(propBuilder);
+            unionGenTransObject.addToStringProperty(propBuilder);
+        }
+    }
+
+    /**
+     * Converts <code>typedef</code> to the generated TO builder.
+     *
+     * @param basePackageName
+     *            string with name of package to which the module belongs
+     * @param typedef
+     *            type definition from which is the generated TO builder created
+     * @return generated TO builder which contains data from
+     *         <code>typedef</code> and <code>basePackageName</code>
+     */
+    private static GeneratedTOBuilderImpl typedefToTransferObject(final String basePackageName,
+            final TypeDefinition<?> typedef, final String moduleName) {
+
+        final String packageName = packageNameForGeneratedType(basePackageName, typedef.getPath());
+        final String typeDefTOName = typedef.getQName().getLocalName();
+
+        if ((packageName != null) && (typeDefTOName != null)) {
+            final String genTOName = BindingMapping.getClassName(typeDefTOName);
+            final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, genTOName);
+
+            newType.setDescription(typedef.getDescription());
+            newType.setReference(typedef.getReference());
+            newType.setSchemaPath(typedef.getPath().getPathFromRoot());
+            newType.setModuleName(moduleName);
+
+            return newType;
+        }
+        return null;
+    }
+
+    /**
+     * Converts <code>typeDef</code> which should be of the type
+     * <code>BitsTypeDefinition</code> to <code>GeneratedTOBuilder</code>.
+     *
+     * All the bits of the typeDef are added to returning generated TO as
+     * properties.
+     *
+     * @param basePackageName
+     *            string with name of package to which the module belongs
+     * @param typeDef
+     *            type definition from which is the generated TO builder created
+     * @param typeDefName
+     *            string with the name for generated TO builder
+     * @return generated TO builder which represents <code>typeDef</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>typeDef</code> equals null</li>
+     *             <li>if <code>basePackageName</code> equals null</li>
+     *             </ul>
+     */
+    public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName,
+            final TypeDefinition<?> typeDef, final String typeDefName, final String moduleName) {
+
+        Preconditions.checkArgument(typeDef != null, "typeDef cannot be NULL!");
+        Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
+
+        if (typeDef instanceof BitsTypeDefinition) {
+            BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
+
+            final String typeName = BindingMapping.getClassName(typeDefName);
+            final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
+
+            genTOBuilder.setDescription(typeDef.getDescription());
+            genTOBuilder.setReference(typeDef.getReference());
+            genTOBuilder.setSchemaPath(typeDef.getPath().getPathFromRoot());
+            genTOBuilder.setModuleName(moduleName);
+            genTOBuilder.setBaseType(typeDef);
+
+            final List<Bit> bitList = bitsTypeDefinition.getBits();
+            GeneratedPropertyBuilder genPropertyBuilder;
+            for (final Bit bit : bitList) {
+                String name = bit.getName();
+                genPropertyBuilder = genTOBuilder.addProperty(BindingMapping.getPropertyName(name));
+                genPropertyBuilder.setReadOnly(true);
+                genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE);
+
+                genTOBuilder.addEqualsIdentity(genPropertyBuilder);
+                genTOBuilder.addHashIdentity(genPropertyBuilder);
+                genTOBuilder.addToStringProperty(genPropertyBuilder);
+            }
+
+            return genTOBuilder;
+        }
+        return null;
+    }
+
+    /**
+     * Converts the pattern constraints from <code>typedef</code> to the list of
+     * the strings which represents these constraints.
+     *
+     * @param typedef
+     *            extended type in which are the pattern constraints sought
+     * @return list of strings which represents the constraint patterns
+     * @throws IllegalArgumentException
+     *             if <code>typedef</code> equals null
+     *
+     */
+    private List<String> resolveRegExpressionsFromTypedef(final ExtendedType typedef) {
+        final List<String> regExps = new ArrayList<String>();
+        Preconditions.checkArgument(typedef != null, "typedef can't be null");
+        final TypeDefinition<?> strTypeDef = baseTypeDefForExtendedType(typedef);
+        if (strTypeDef instanceof StringType) {
+            final List<PatternConstraint> patternConstraints = typedef.getPatternConstraints();
+            if (!patternConstraints.isEmpty()) {
+                String regEx;
+                String modifiedRegEx;
+                for (PatternConstraint patternConstraint : patternConstraints) {
+                    regEx = patternConstraint.getRegularExpression();
+                    modifiedRegEx = StringEscapeUtils.escapeJava(regEx);
+                    regExps.add(modifiedRegEx);
+                }
+            }
+        }
+        return regExps;
+    }
+
+    /**
+     *
+     * Adds to the <code>genTOBuilder</code> the constant which contains regular
+     * expressions from the <code>regularExpressions</code>
+     *
+     * @param genTOBuilder
+     *            generated TO builder to which are
+     *            <code>regular expressions</code> added
+     * @param regularExpressions
+     *            list of string which represent regular expressions
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>genTOBuilder</code> equals null</li>
+     *             <li>if <code>regularExpressions</code> equals null</li>
+     *             </ul>
+     */
+    private static void addStringRegExAsConstant(final GeneratedTOBuilder genTOBuilder, final List<String> regularExpressions) {
+        if (genTOBuilder == null) {
+            throw new IllegalArgumentException("Generated transfer object builder can't be null");
+        }
+        if (regularExpressions == null) {
+            throw new IllegalArgumentException("List of regular expressions can't be null");
+        }
+        if (!regularExpressions.isEmpty()) {
+            genTOBuilder.addConstant(Types.listTypeFor(BaseYangTypes.STRING_TYPE), TypeConstants.PATTERN_CONSTANT_NAME,
+                    regularExpressions);
+        }
+    }
+
+    /**
+     * Creates generated TO with data about inner extended type
+     * <code>innerExtendedType</code>, about the package name
+     * <code>typedefName</code> and about the generated TO name
+     * <code>typedefName</code>.
+     *
+     * It is supposed that <code>innerExtendedType</code> is already present in
+     * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap} to
+     * be possible set it as extended type for the returning generated TO.
+     *
+     * @param typedef
+     *            Type Definition
+     * @param innerExtendedType
+     *            extended type which is part of some other extended type
+     * @param basePackageName
+     *            string with the package name of the module
+     * @param moduleName
+     *            Module Name
+     * @return generated TO which extends generated TO for
+     *         <code>innerExtendedType</code>
+     * @throws IllegalArgumentException
+     *             <ul>
+     *             <li>if <code>extendedType</code> equals null</li>
+     *             <li>if <code>basePackageName</code> equals null</li>
+     *             <li>if <code>typedefName</code> equals null</li>
+     *             </ul>
+     */
+    private GeneratedTransferObject provideGeneratedTOFromExtendedType(final TypeDefinition<?> typedef,
+            final ExtendedType innerExtendedType, final String basePackageName, final String moduleName) {
+        Preconditions.checkArgument(innerExtendedType != null, "Extended type cannot be NULL!");
+        Preconditions.checkArgument(basePackageName != null, "String with base package name cannot be NULL!");
+
+        final String typedefName = typedef.getQName().getLocalName();
+        final String classTypedefName = BindingMapping.getClassName(typedefName);
+        final String innerTypeDef = innerExtendedType.getQName().getLocalName();
+        final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, classTypedefName);
+
+        genTOBuilder.setDescription(typedef.getDescription());
+        genTOBuilder.setReference(typedef.getReference());
+        genTOBuilder.setSchemaPath(typedef.getPath().getPathFromRoot());
+        genTOBuilder.setModuleName(moduleName);
+        genTOBuilder.setTypedef(true);
+        Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
+        genTOBuilder.setRestrictions(r);
+
+        if (baseTypeDefForExtendedType(innerExtendedType) instanceof UnionTypeDefinition) {
+            genTOBuilder.setIsUnion(true);
+        }
+
+        Map<Date, Map<String, Type>> modulesByDate = null;
+        Map<String, Type> typeMap = null;
+        final Module parentModule = findParentModule(schemaContext, innerExtendedType);
+        if (parentModule != null) {
+            modulesByDate = genTypeDefsContextMap.get(parentModule.getName());
+            typeMap = modulesByDate.get(parentModule.getRevision());
+        }
+
+        if (typeMap != null) {
+            Type type = typeMap.get(innerTypeDef);
+            if (type instanceof GeneratedTransferObject) {
+                genTOBuilder.setExtendsType((GeneratedTransferObject) type);
+            }
+        }
+        addUnitsToGenTO(genTOBuilder, typedef.getUnits());
+        makeSerializable(genTOBuilder);
+
+        return genTOBuilder.toInstance();
+    }
+
+    /**
+     * Add {@link Serializable} to implemented interfaces of this TO. Also
+     * compute and add serialVersionUID property.
+     *
+     * @param gto
+     *            transfer object which needs to be serializable
+     */
+    private static void makeSerializable(final GeneratedTOBuilderImpl gto) {
+        gto.addImplementsType(Types.typeForClass(Serializable.class));
+        GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
+        prop.setValue(Long.toString(BindingGeneratorUtil.computeDefaultSUID(gto)));
+        gto.setSUID(prop);
+    }
+
+    /**
+     * Finds out for each type definition how many immersion (depth) is
+     * necessary to get to the base type. Every type definition is inserted to
+     * the map which key is depth and value is list of type definitions with
+     * equal depth. In next step are lists from this map concatenated to one
+     * list in ascending order according to their depth. All type definitions
+     * are in the list behind all type definitions on which depends.
+     *
+     * @param unsortedTypeDefinitions
+     *            list of type definitions which should be sorted by depth
+     * @return list of type definitions sorted according their each other
+     *         dependencies (type definitions which are depend on other type
+     *         definitions are in list behind them).
+     */
+    private List<TypeDefinition<?>> sortTypeDefinitionAccordingDepth(
+            final Collection<TypeDefinition<?>> unsortedTypeDefinitions) {
+        List<TypeDefinition<?>> sortedTypeDefinition = new ArrayList<>();
+
+        Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();
+        for (TypeDefinition<?> unsortedTypeDefinition : unsortedTypeDefinitions) {
+            final int depth = getTypeDefinitionDepth(unsortedTypeDefinition);
+            List<TypeDefinition<?>> typeDefinitionsConcreteDepth = typeDefinitionsDepths.get(depth);
+            if (typeDefinitionsConcreteDepth == null) {
+                typeDefinitionsConcreteDepth = new ArrayList<TypeDefinition<?>>();
+                typeDefinitionsDepths.put(depth, typeDefinitionsConcreteDepth);
+            }
+            typeDefinitionsConcreteDepth.add(unsortedTypeDefinition);
+        }
+
+        // SortedMap guarantees order corresponding to keys in ascending order
+        for (List<TypeDefinition<?>> v : typeDefinitionsDepths.values()) {
+            sortedTypeDefinition.addAll(v);
+        }
+
+        return sortedTypeDefinition;
+    }
+
+    /**
+     * Returns how many immersion is necessary to get from the type definition
+     * to the base type.
+     *
+     * @param typeDefinition
+     *            type definition for which is depth sought.
+     * @return number of immersions which are necessary to get from the type
+     *         definition to the base type
+     */
+    private int getTypeDefinitionDepth(final TypeDefinition<?> typeDefinition) {
+        if (typeDefinition == null) {
+            return 1;
+        }
+        int depth = 1;
+        TypeDefinition<?> baseType = typeDefinition.getBaseType();
+
+        if (baseType instanceof ExtendedType) {
+            depth = depth + getTypeDefinitionDepth(typeDefinition.getBaseType());
+        } else if (baseType instanceof UnionType) {
+            List<TypeDefinition<?>> childTypeDefinitions = ((UnionType) baseType).getTypes();
+            int maxChildDepth = 0;
+            int childDepth = 1;
+            for (TypeDefinition<?> childTypeDefinition : childTypeDefinitions) {
+                childDepth = childDepth + getTypeDefinitionDepth(childTypeDefinition);
+                if (childDepth > maxChildDepth) {
+                    maxChildDepth = childDepth;
+                }
+            }
+            return maxChildDepth;
+        }
+        return depth;
+    }
+
+    /**
+     * Returns string which contains the same value as <code>name</code> but
+     * integer suffix is incremented by one. If <code>name</code> contains no
+     * number suffix then number 1 is added.
+     *
+     * @param name
+     *            string with name of augmented node
+     * @return string with the number suffix incremented by one (or 1 is added)
+     */
+    private static String provideAvailableNameForGenTOBuilder(final String name) {
+        Matcher mtch = NUMBERS_PATTERN.matcher(name);
+        if (mtch.find()) {
+            final int newSuffix = Integer.valueOf(name.substring(mtch.start())) + 1;
+            return name.substring(0, mtch.start()) + newSuffix;
+        } else {
+            return name + 1;
+        }
+    }
+
+    public void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) {
+        if (units != null && !units.isEmpty()) {
+            to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\"");
+            GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
+            prop.setReturnType(Types.STRING);
+            to.addToStringProperty(prop);
+        }
+    }
+
+    @Override
+    public String getTypeDefaultConstruction(final LeafSchemaNode node) {
+        return getTypeDefaultConstruction(node, node.getDefault());
+    }
+
+    public String getTypeDefaultConstruction(final LeafSchemaNode node, final String defaultValue) {
+        TypeDefinition<?> type = node.getType();
+        QName typeQName = type.getQName();
+        TypeDefinition<?> base = baseTypeDefForExtendedType(type);
+        Preconditions.checkNotNull(type, "Cannot provide default construction for null type of %s", node);
+        Preconditions.checkNotNull(defaultValue, "Cannot provide default construction for null default statement of %s",
+                node);
+
+        StringBuilder sb = new StringBuilder();
+        String result = null;
+        if (base instanceof BinaryTypeDefinition) {
+            result = binaryToDef(defaultValue);
+        } else if (base instanceof BitsTypeDefinition) {
+            String parentName;
+            String className;
+            Module parent = getParentModule(node);
+            Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
+            path.next();
+            if (!(path.hasNext())) {
+                parentName = BindingMapping.getClassName(parent.getName()) + "Data";
+                String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
+                className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
+            } else {
+                String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
+                String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
+                parentName = BindingMapping.getClassName(parent.getName());
+                className = packageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
+            }
+            result = bitsToDef((BitsTypeDefinition) base, className, defaultValue, type instanceof ExtendedType);
+        } else if (base instanceof BooleanTypeDefinition) {
+            result = typeToDef(Boolean.class, defaultValue);
+        } else if (base instanceof DecimalTypeDefinition) {
+            result = typeToDef(BigDecimal.class, defaultValue);
+        } else if (base instanceof EmptyTypeDefinition) {
+            result = typeToDef(Boolean.class, defaultValue);
+        } else if (base instanceof EnumTypeDefinition) {
+            char[] defValArray = defaultValue.toCharArray();
+            char first = Character.toUpperCase(defaultValue.charAt(0));
+            defValArray[0] = first;
+            String newDefVal = new String(defValArray);
+            String className;
+            if (type instanceof ExtendedType) {
+                Module m = getParentModule(type);
+                String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
+                String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
+                className = packageName + "." + BindingMapping.getClassName(typeQName);
+            } else {
+                Module parentModule = getParentModule(node);
+                String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
+                String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
+                className = packageName + "." + BindingMapping.getClassName(node.getQName());
+            }
+            result = className + "." + newDefVal;
+        } else if (base instanceof IdentityrefTypeDefinition) {
+            throw new UnsupportedOperationException("Cannot get default construction for identityref type");
+        } else if (base instanceof InstanceIdentifierTypeDefinition) {
+            throw new UnsupportedOperationException("Cannot get default construction for instance-identifier type");
+        } else if (base instanceof Int8) {
+            result = typeToDef(Byte.class, defaultValue);
+        } else if (base instanceof Int16) {
+            result = typeToDef(Short.class, defaultValue);
+        } else if (base instanceof Int32) {
+            result = typeToDef(Integer.class, defaultValue);
+        } else if (base instanceof Int64) {
+            result = typeToDef(Long.class, defaultValue);
+        } else if (base instanceof LeafrefTypeDefinition) {
+            result = leafrefToDef(node, (LeafrefTypeDefinition) base, defaultValue);
+        } else if (base instanceof StringTypeDefinition) {
+            result = "\"" + defaultValue + "\"";
+        } else if (base instanceof Uint8) {
+            result = typeToDef(Short.class, defaultValue);
+        } else if (base instanceof Uint16) {
+            result = typeToDef(Integer.class, defaultValue);
+        } else if (base instanceof Uint32) {
+            result = typeToDef(Long.class, defaultValue);
+        } else if (base instanceof Uint64) {
+            result = typeToDef(BigInteger.class, defaultValue);
+        } else if (base instanceof UnionTypeDefinition) {
+            result = unionToDef(node);
+        } else {
+            result = "";
+        }
+        sb.append(result);
+
+        if (type instanceof ExtendedType && !(base instanceof LeafrefTypeDefinition)
+                && !(base instanceof EnumerationType) && !(base instanceof UnionTypeDefinition)) {
+            Module m = getParentModule(type);
+            String basePackageName = BindingMapping.getRootPackageName(m.getQNameModule());
+            String packageName = packageNameForGeneratedType(basePackageName, type.getPath());
+            String className = packageName + "." + BindingMapping.getClassName(typeQName);
+            sb.insert(0, "new " + className + "(");
+            sb.insert(sb.length(), ')');
+        }
+
+        return sb.toString();
+    }
+
+    private static String typeToDef(final Class<?> clazz, final String defaultValue) {
+        return "new " + clazz.getName() + "(\"" + defaultValue + "\")";
+    }
+
+    private static String binaryToDef(final String defaultValue) {
+        StringBuilder sb = new StringBuilder();
+        BaseEncoding en = BaseEncoding.base64();
+        byte[] encoded = en.decode(defaultValue);
+        sb.append("new byte[] {");
+        for (int i = 0; i < encoded.length; i++) {
+            sb.append(encoded[i]);
+            if (i != encoded.length - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append('}');
+        return sb.toString();
+    }
+
+    private static String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue,
+            final boolean isExt) {
+        List<Bit> bits = new ArrayList<>(type.getBits());
+        Collections.sort(bits, new Comparator<Bit>() {
+            @Override
+            public int compare(final Bit o1, final Bit o2) {
+                return o1.getName().compareTo(o2.getName());
+            }
+        });
+        StringBuilder sb = new StringBuilder();
+        if (!isExt) {
+            sb.append("new ");
+            sb.append(className);
+            sb.append('(');
+        }
+        for (int i = 0; i < bits.size(); i++) {
+            if (bits.get(i).getName().equals(defaultValue)) {
+                sb.append(true);
+            } else {
+                sb.append(false);
+            }
+            if (i != bits.size() - 1) {
+                sb.append(", ");
+            }
+        }
+        if (!isExt) {
+            sb.append(')');
+        }
+        return sb.toString();
+    }
+
+    private Module getParentModule(final SchemaNode node) {
+        QName qname = node.getPath().getPathFromRoot().iterator().next();
+        URI namespace = qname.getNamespace();
+        Date revision = qname.getRevision();
+        return schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+    }
+
+    private String leafrefToDef(final LeafSchemaNode parentNode, final LeafrefTypeDefinition leafrefType, final String defaultValue) {
+        Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!");
+        Preconditions.checkArgument(leafrefType.getPathStatement() != null,
+                "The Path Statement for Leafref Type Definition cannot be NULL!");
+
+        final RevisionAwareXPath xpath = leafrefType.getPathStatement();
+        final String strXPath = xpath.toString();
+
+        if (strXPath != null) {
+            if (strXPath.indexOf('[') == -1) {
+                final Module module = findParentModule(schemaContext, parentNode);
+                if (module != null) {
+                    final SchemaNode dataNode;
+                    if (xpath.isAbsolute()) {
+                        dataNode = findDataSchemaNode(schemaContext, module, xpath);
+                    } else {
+                        dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
+                    }
+                    String result = getTypeDefaultConstruction((LeafSchemaNode) dataNode, defaultValue);
+                    return result;
+                }
+            } else {
+                return "new java.lang.Object()";
+            }
+        }
+
+        return null;
+    }
+
+    private String unionToDef(final LeafSchemaNode node) {
+        String parentName;
+        String className;
+
+        if (node.getType() instanceof ExtendedType) {
+            ExtendedType type = (ExtendedType) node.getType();
+            QName typeQName = type.getQName();
+            Module module = null;
+            Set<Module> modules = schemaContext.findModuleByNamespace(typeQName.getNamespace());
+            if (modules.size() > 1) {
+                for (Module m : modules) {
+                    if (m.getRevision().equals(typeQName.getRevision())) {
+                        module = m;
+                        break;
+                    }
+                }
+                if (module == null) {
+                    List<Module> modulesList = new ArrayList<>(modules);
+                    Collections.sort(modulesList, new Comparator<Module>() {
+                        @Override
+                        public int compare(final Module o1, final Module o2) {
+                            return o1.getRevision().compareTo(o2.getRevision());
+                        }
+                    });
+                    module = modulesList.get(0);
+                }
+            } else {
+                module = modules.iterator().next();
+            }
+
+            String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
+            className = basePackageName + "." + BindingMapping.getClassName(typeQName);
+        } else {
+            Iterator<QName> path = node.getPath().getPathFromRoot().iterator();
+            QName first = path.next();
+            if (!(path.hasNext())) {
+                URI namespace = first.getNamespace();
+                Date revision = first.getRevision();
+                Module parent = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+                parentName = BindingMapping.getClassName((parent).getName()) + "Data";
+                String basePackageName = BindingMapping.getRootPackageName(parent.getQNameModule());
+                className = basePackageName + "." + parentName + "." + BindingMapping.getClassName(node.getQName());
+            } else {
+                URI namespace = first.getNamespace();
+                Date revision = first.getRevision();
+                Module parentModule = schemaContext.findModuleByNamespaceAndRevision(namespace, revision);
+                String basePackageName = BindingMapping.getRootPackageName(parentModule.getQNameModule());
+                String packageName = packageNameForGeneratedType(basePackageName, node.getType().getPath());
+                className = packageName + "." + BindingMapping.getClassName(node.getQName());
+            }
+        }
+        return union(className, node.getDefault(), node);
+    }
+
+    private static String union(final String className, final String defaultValue, final LeafSchemaNode node) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("new ");
+        sb.append(className);
+        sb.append("(\"");
+        sb.append(defaultValue);
+        sb.append("\".toCharArray())");
+        return sb.toString();
+    }
+
+    @Override
+    public String getConstructorPropertyName(final SchemaNode node) {
+        if (node instanceof TypeDefinition<?>) {
+            return "value";
+        } else {
+            return "";
+        }
+    }
+
+    @Override
+    public String getParamNameFromType(final TypeDefinition<?> type) {
+        return BindingMapping.getPropertyName(type.getQName().getLocalName());
+    }
+
+}
diff --git a/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/UnionDependencySort.java b/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/UnionDependencySort.java
new file mode 100644 (file)
index 0000000..74b4c77
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+import org.opendaylight.yangtools.yang.parser.util.TopologicalSort;
+import org.opendaylight.yangtools.yang.parser.util.TopologicalSort.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+public class UnionDependencySort {
+    private static final Logger LOGGER = LoggerFactory.getLogger(UnionDependencySort.class);
+
+    /**
+     * Sorts union types by mutual dependencies.
+     * 
+     * At the beginning the union types are selected from
+     * <code>typeDefinitions</code> and wrapped to nodes. The nodes are sorted
+     * and then the wrapped payload is extracted.
+     * 
+     * @param typeDefinitions
+     *            set of type definitions.
+     * @return list of extended type which are sorted by mutual dependencies
+     * @throws IllegalArgumentException
+     *             if <code>typeDefinitions</code> equals <code>null</code>
+     */
+    public List<ExtendedType> sort(final Set<TypeDefinition<?>> typeDefinitions) {
+        if (typeDefinitions == null) {
+            LOGGER.error("Set of Type Definitions cannot be NULL!");
+            throw new IllegalArgumentException("Set of Type Definitions " + "cannot be NULL!");
+        }
+
+        final Set<ExtendedType> extUnionTypes = unionsFromTypeDefinitions(typeDefinitions);
+
+        final Set<Node> unsorted = unionTypesToNodes(extUnionTypes);
+
+        final List<Node> sortedNodes = TopologicalSort.sort(unsorted);
+        return Lists.transform(sortedNodes, new Function<Node, ExtendedType>() {
+            @Override
+            public ExtendedType apply(Node input) {
+                return (ExtendedType) (((NodeWrappedType) input).getWrappedType());
+            }
+        });
+    }
+
+    /**
+     * Extracts only union types from <code>typeDefinitions</code> set.
+     * 
+     * @param typeDefinitions
+     *            set of all type definitions
+     * @return set of extended type which are union type definition
+     */
+    private Set<ExtendedType> unionsFromTypeDefinitions(final Set<TypeDefinition<?>> typeDefinitions) {
+        final Set<ExtendedType> unions = Sets.newHashSet();
+
+        for (final TypeDefinition<?> typedef : typeDefinitions) {
+            if ((typedef != null) && (typedef.getBaseType() != null) && (typedef instanceof ExtendedType)
+                    && (typedef.getBaseType() instanceof UnionTypeDefinition)) {
+                unions.add((ExtendedType) typedef);
+            }
+        }
+        return unions;
+    }
+
+    /**
+     * Wraps every extended type which represents union to node type and adds to
+     * every node information about dependencies.
+     * 
+     * The mapping from union type to node is created. For every created node
+     * (next <i>nodeFrom</i>) is for its wrapped union type passed the list of
+     * inner types through and only those inner types which represent union type
+     * are next considered. For every inner union type is found its wrapping
+     * node (next as <i>nodeTo</i>). This dependency relationship between
+     * nodeFrom and all found nodesTo is modeled with creating of one edge from
+     * nodeFrom to nodeTo.
+     * 
+     * 
+     * @param extUnionTypes
+     *            set of extended types which represents union types
+     * @return set of nodes which contains wrapped union types set of node where
+     *         each one contains wrapped one union type
+     */
+    private Set<Node> unionTypesToNodes(final Set<ExtendedType> extUnionTypes) {
+        final Map<ExtendedType, Node> nodeMap = Maps.newHashMap();
+        final Set<Node> resultNodes = Sets.newHashSet();
+
+        for (final ExtendedType unionType : extUnionTypes) {
+            final Node node = new NodeWrappedType(unionType);
+            nodeMap.put(unionType, node);
+            resultNodes.add(node);
+        }
+
+        for (final Node node : resultNodes) {
+            final NodeWrappedType nodeFrom = (NodeWrappedType) node;
+            final ExtendedType extUnionType = (ExtendedType) nodeFrom.getWrappedType();
+
+            final UnionTypeDefinition unionType = (UnionTypeDefinition) extUnionType.getBaseType();
+
+            final List<TypeDefinition<?>> innerTypes = unionType.getTypes();
+            for (final TypeDefinition<?> typedef : innerTypes) {
+                if (extUnionTypes.contains(typedef)) {
+                    final Node toNode = nodeMap.get(typedef);
+                    nodeFrom.addEdge(toNode);
+                }
+            }
+        }
+
+        return resultNodes;
+    }
+
+}
diff --git a/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/package-info.java b/code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/package-info.java
new file mode 100644 (file)
index 0000000..947da5c
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * 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.sal.binding.yang.types;
\ No newline at end of file
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/BaseYangTypesTest.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/BaseYangTypesTest.java
new file mode 100644 (file)
index 0000000..e7a425b
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
+import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+/**
+ * Test class for testing BaseYangTypes class.
+ *
+ * @author Lukas Sedlak <lsedlak@cisco.com>
+ */
+public class BaseYangTypesTest {
+
+    private static SchemaContext schemaContext;
+
+    private static BinaryTypeDefinition binary = null;
+    private static DecimalTypeDefinition decimal64 = null;
+    private static EnumTypeDefinition enumeration = null;
+    private static IntegerTypeDefinition int8 = null;
+    private static IntegerTypeDefinition int16 = null;
+    private static IntegerTypeDefinition int32 = null;
+    private static IntegerTypeDefinition int64 = null;
+    private static StringTypeDefinition string = null;
+    private static UnsignedIntegerTypeDefinition uint8 = null;
+    private static UnsignedIntegerTypeDefinition uint16 = null;
+    private static UnsignedIntegerTypeDefinition uint32 = null;
+    private static UnsignedIntegerTypeDefinition uint64 = null;
+    private static UnionTypeDefinition union = null;
+    private static EmptyTypeDefinition empty = null;
+    private static BooleanTypeDefinition bool = null;
+
+    @SuppressWarnings("deprecation")
+    @BeforeClass
+    public static void setup() {
+        final List<InputStream> modelsToParse = Collections
+            .singletonList(BaseYangTypesTest.class.getResourceAsStream("/base-yang-types.yang"));
+        final YangContextParser parser = new YangParserImpl();
+        final Set<Module> modules = parser.parseYangModelsFromStreams(modelsToParse);
+        assertTrue(!modules.isEmpty());
+        schemaContext = parser.resolveSchemaContext(modules);
+        assertNotNull(schemaContext);
+        initTypeDefinitionsFromSchemaContext();
+    }
+
+    private static void initTypeDefinitionsFromSchemaContext() {
+        Set<TypeDefinition<?>> typedefs = schemaContext.getTypeDefinitions();
+        assertTrue(!typedefs.isEmpty());
+
+        for (final TypeDefinition<?> typedef : typedefs) {
+            assertNotNull(typedef);
+            assertTrue(typedef instanceof ExtendedType);
+
+            final TypeDefinition<?> baseType = typedef.getBaseType();
+            if (baseType instanceof BinaryTypeDefinition) {
+                binary = (BinaryTypeDefinition) baseType;
+            } else if (baseType instanceof DecimalTypeDefinition) {
+                decimal64 = (DecimalTypeDefinition) baseType;
+            } else if (baseType instanceof EnumTypeDefinition) {
+                enumeration = (EnumTypeDefinition) baseType;
+            } else if (baseType instanceof IntegerTypeDefinition) {
+                String typeName = baseType.getQName().getLocalName();
+                switch (typeName) {
+                case "int8":
+                    int8 = (IntegerTypeDefinition) baseType;
+                    break;
+                case "int16":
+                    int16 = (IntegerTypeDefinition) baseType;
+                    break;
+                case "int32":
+                    int32 = (IntegerTypeDefinition) baseType;
+                    break;
+                case "int64":
+                    int64 = (IntegerTypeDefinition) baseType;
+                    break;
+                }
+            } else if (baseType instanceof StringTypeDefinition) {
+                string = (StringTypeDefinition) baseType;
+            } else if (baseType instanceof UnsignedIntegerTypeDefinition) {
+                String typeName = baseType.getQName().getLocalName();
+                switch (typeName) {
+                case "uint8":
+                    uint8 = (UnsignedIntegerTypeDefinition) baseType;
+                    break;
+                case "uint16":
+                    uint16 = (UnsignedIntegerTypeDefinition) baseType;
+                    break;
+                case "uint32":
+                    uint32 = (UnsignedIntegerTypeDefinition) baseType;
+                    break;
+                case "uint64":
+                    uint64 = (UnsignedIntegerTypeDefinition) baseType;
+                    break;
+                }
+            } else if (baseType instanceof UnionTypeDefinition) {
+                union = (UnionTypeDefinition) baseType;
+            } else if (baseType instanceof EmptyTypeDefinition) {
+                empty = (EmptyTypeDefinition) baseType;
+            } else if (baseType instanceof BooleanTypeDefinition) {
+                bool = (BooleanTypeDefinition) baseType;
+            }
+        }
+        assertNotNull(binary);
+        assertNotNull(decimal64);
+        assertNotNull(enumeration);
+        assertNotNull(int8);
+        assertNotNull(int16);
+        assertNotNull(int32);
+        assertNotNull(int64);
+        assertNotNull(string);
+        assertNotNull(uint8);
+        assertNotNull(uint16);
+        assertNotNull(uint32);
+        assertNotNull(uint64);
+        assertNotNull(union);
+        assertNotNull(empty);
+        assertNotNull(bool);
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionTypeTest() {
+        final TypeProvider typeProvider = BaseYangTypes.BASE_YANG_TYPES_PROVIDER;
+
+        Type javaType = typeProvider.javaTypeForSchemaDefinitionType(binary, binary);
+        assertNotNull(javaType);
+        assertEquals("byte[]", javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(decimal64, decimal64);
+        assertNotNull(javaType);
+        assertEquals(BigDecimal.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(enumeration, enumeration);
+        assertNotNull(javaType);
+        assertEquals(Enum.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(int8, int8);
+        assertNotNull(javaType);
+        assertEquals(Byte.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(int16, int16);
+        assertNotNull(javaType);
+        assertEquals(Short.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(int32, int32);
+        assertNotNull(javaType);
+        assertEquals(Integer.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(int64, int64);
+        assertNotNull(javaType);
+        assertEquals(Long.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(string, string);
+        assertNotNull(javaType);
+        assertEquals(String.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(uint8, uint8);
+        assertNotNull(javaType);
+        assertEquals(Short.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(uint16, uint16);
+        assertNotNull(javaType);
+        assertEquals(Integer.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(uint32, uint32);
+        assertNotNull(javaType);
+        assertEquals(Long.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(uint64, uint64);
+        assertNotNull(javaType);
+        assertEquals(BigInteger.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(union, union);
+        assertNotNull(javaType);
+        assertEquals("Union", javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(empty, empty);
+        assertNotNull(javaType);
+        assertEquals(Boolean.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(bool, bool);
+        assertNotNull(javaType);
+        assertEquals(Boolean.class.getCanonicalName(), javaType.getFullyQualifiedName());
+    }
+
+    @Test
+    public void javaTypeForRestrictedSchemaDefinitionTypeTest() {
+        final TypeProvider typeProvider = BaseYangTypes.BASE_YANG_TYPES_PROVIDER;
+
+        Type javaType = typeProvider.javaTypeForSchemaDefinitionType(binary, binary, BindingGeneratorUtil.getRestrictions(binary));
+        assertNotNull(javaType);
+        assertEquals("byte[]", javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(decimal64, decimal64, BindingGeneratorUtil.getRestrictions(decimal64));
+        assertNotNull(javaType);
+        assertEquals(BigDecimal.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(enumeration, enumeration, BindingGeneratorUtil.getRestrictions(enumeration));
+        assertNotNull(javaType);
+        assertEquals(Enum.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(int8, int8, BindingGeneratorUtil.getRestrictions(int8));
+        assertNotNull(javaType);
+        assertEquals(Byte.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(int16, int16, BindingGeneratorUtil.getRestrictions(int16));
+        assertNotNull(javaType);
+        assertEquals(Short.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(int32, int32, BindingGeneratorUtil.getRestrictions(int32));
+        assertNotNull(javaType);
+        assertEquals(Integer.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(int64, int64, BindingGeneratorUtil.getRestrictions(int64));
+        assertNotNull(javaType);
+        assertEquals(Long.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(string, string, BindingGeneratorUtil.getRestrictions(string));
+        assertNotNull(javaType);
+        assertEquals(String.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(uint8, uint8, BindingGeneratorUtil.getRestrictions(uint8));
+        assertNotNull(javaType);
+        assertEquals(Short.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(uint16, uint16, BindingGeneratorUtil.getRestrictions(uint16));
+        assertNotNull(javaType);
+        assertEquals(Integer.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(uint32, uint32, BindingGeneratorUtil.getRestrictions(uint32));
+        assertNotNull(javaType);
+        assertEquals(Long.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(uint64, uint64, BindingGeneratorUtil.getRestrictions(uint64));
+        assertNotNull(javaType);
+        assertEquals(BigInteger.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(union, union, BindingGeneratorUtil.getRestrictions(union));
+        assertNotNull(javaType);
+        assertEquals("Union", javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(empty, empty, BindingGeneratorUtil.getRestrictions(empty));
+        assertNotNull(javaType);
+        assertEquals(Boolean.class.getCanonicalName(), javaType.getFullyQualifiedName());
+
+        javaType = typeProvider.javaTypeForSchemaDefinitionType(bool, bool, BindingGeneratorUtil.getRestrictions(bool));
+        assertNotNull(javaType);
+        assertEquals(Boolean.class.getCanonicalName(), javaType.getFullyQualifiedName());
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/GroupingDefinitionDependencySortTest.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/GroupingDefinitionDependencySortTest.java
new file mode 100644 (file)
index 0000000..88ed766
--- /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.sal.binding.yang.types;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.parser.builder.impl.GroupingBuilderImpl;
+
+public class GroupingDefinitionDependencySortTest {
+
+    @Rule
+    public ExpectedException expException = ExpectedException.none();
+
+    @Test
+    public void testSortMethod() {
+        GroupingDefinitionDependencySort groupingDefinitionDependencySort = new GroupingDefinitionDependencySort();
+        List<GroupingDefinition> unsortedGroupingDefs = new ArrayList<>();
+
+        GroupingBuilderImpl groupingBuilderImpl = new GroupingBuilderImpl("test-module", 111, QName.create("leaf1"), SchemaPath.create(false, QName.create("Cont1"), QName.create("Cont2")));
+        GroupingBuilderImpl groupingBuilderImpl2 = new GroupingBuilderImpl("test-module", 222, QName.create("leaf2"), SchemaPath.create(false, QName.create("Cont1")));
+        GroupingBuilderImpl groupingBuilderImpl3 = new GroupingBuilderImpl("test-module2", 111, QName.create("leaf3"), SchemaPath.create(false, QName.create("Cont1"), QName.create("Cont2")));
+        GroupingBuilderImpl groupingBuilderImpl4 = new GroupingBuilderImpl("test-module2", 222, QName.create("leaf4"), SchemaPath.create(false, QName.create("Cont1"), QName.create("Cont2"), QName.create("List1")));
+        GroupingBuilderImpl groupingBuilderImpl5 = new GroupingBuilderImpl("test-module2", 333, QName.create("leaf5"), SchemaPath.create(false, QName.create("Cont1")));
+
+        unsortedGroupingDefs.add(groupingBuilderImpl.build());
+        unsortedGroupingDefs.add(groupingBuilderImpl.build());
+        unsortedGroupingDefs.add(groupingBuilderImpl2.build());
+        unsortedGroupingDefs.add(groupingBuilderImpl3.build());
+        unsortedGroupingDefs.add(groupingBuilderImpl4.build());
+        unsortedGroupingDefs.add(groupingBuilderImpl5.build());
+
+        List<GroupingDefinition> sortedGroupingDefs = groupingDefinitionDependencySort.sort(unsortedGroupingDefs);
+        assertNotNull(sortedGroupingDefs);
+
+        expException.expect(IllegalArgumentException.class);
+        expException.expectMessage("Set of Type Definitions cannot be NULL!");
+        groupingDefinitionDependencySort.sort(null);
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/LeafrefTypeWithNullToStringInXpath.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/LeafrefTypeWithNullToStringInXpath.java
new file mode 100644 (file)
index 0000000..7ec51a1
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import java.util.List;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+
+/**
+ * Mock LeafrefDypeDefinition implementation with non-null referenced RevisionAwareXPath.
+ *
+ * Although RevisionAwareXPath has implemented Override for toString to return null value to reach specific branch
+ * in TypeProviderImpl#provideTypeForLeafref method.
+ *
+ * Created by lukas on 9/17/14.
+ */
+public class LeafrefTypeWithNullToStringInXpath implements LeafrefTypeDefinition {
+    @Override public RevisionAwareXPath getPathStatement() {
+        return new RevisionAwareXPath() {
+            @Override
+            public boolean isAbsolute() {
+                return false;
+            }
+
+            @Override
+            public String toString() {
+                return null;
+            }
+        };
+    }
+
+    @Override public LeafrefTypeDefinition getBaseType() {
+        return null;
+    }
+
+    @Override public String getUnits() {
+        return null;
+    }
+
+    @Override public Object getDefaultValue() {
+        return null;
+    }
+
+    @Override public QName getQName() {
+        return null;
+    }
+
+    @Override public SchemaPath getPath() {
+        return null;
+    }
+
+    @Override public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+        return null;
+    }
+
+    @Override public String getDescription() {
+        return null;
+    }
+
+    @Override public String getReference() {
+        return null;
+    }
+
+    @Override public Status getStatus() {
+        return null;
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/LeafrefTypeWithNullXpath.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/LeafrefTypeWithNullXpath.java
new file mode 100644 (file)
index 0000000..e1e18b6
--- /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.sal.binding.yang.types;
+
+import java.util.List;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+
+/**
+ * Mock LeafrefDypeDefinition implementation with RevisionAwareXPath null reference
+ *
+ * @author Lukas Sedlak <lsedlak@cisco.com>
+ */
+public class LeafrefTypeWithNullXpath implements LeafrefTypeDefinition {
+    @Override public RevisionAwareXPath getPathStatement() {
+        return null;
+    }
+
+    @Override public LeafrefTypeDefinition getBaseType() {
+        return null;
+    }
+
+    @Override public String getUnits() {
+        return null;
+    }
+
+    @Override public Object getDefaultValue() {
+        return null;
+    }
+
+    @Override public QName getQName() {
+        return null;
+    }
+
+    @Override public SchemaPath getPath() {
+        return null;
+    }
+
+    @Override public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+        return null;
+    }
+
+    @Override public String getDescription() {
+        return null;
+    }
+
+    @Override public String getReference() {
+        return null;
+    }
+
+    @Override public Status getStatus() {
+        return null;
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/NodeWrappedTypeTest.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/NodeWrappedTypeTest.java
new file mode 100644 (file)
index 0000000..e6d895d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class NodeWrappedTypeTest {
+
+    @Test
+    public void test() {
+        NodeWrappedType nwt1 = new NodeWrappedType("obj1");
+        NodeWrappedType nwt2 = new NodeWrappedType("obj2");
+        NodeWrappedType nwt3 = new NodeWrappedType("obj1");
+        String str = "obj3";
+
+        assertTrue("Node nwt1 should equal to itself.", nwt1.equals(nwt1));
+        assertFalse("It can't be possible to compare nwt with string.", nwt1.equals(str));
+        assertFalse("nwt1 shouldn't equal to nwt2.", nwt1.equals(nwt2));
+        assertTrue("Node nwt1 should equal to nwt3.", nwt1.equals(nwt3));
+
+        assertEquals("toString method is returning incorrect value.", "NodeWrappedType{wrappedType=obj1}",
+                nwt1.toString());
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TestIntegerTypeDefinition.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TestIntegerTypeDefinition.java
new file mode 100644 (file)
index 0000000..c924125
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import java.util.List;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+
+/**
+ * Mock Integer Type Definition designated to increase branch coverage in test cases.
+ *
+ * @author Lukas Sedlak <lsedlak@cisco.com>
+ */
+final class TestIntegerTypeDefinition implements IntegerTypeDefinition {
+
+    @Override public List<RangeConstraint> getRangeConstraints() {
+        return null;
+    }
+
+    @Override public IntegerTypeDefinition getBaseType() {
+        return null;
+    }
+
+    @Override public String getUnits() {
+        return null;
+    }
+
+    @Override public Object getDefaultValue() {
+        return null;
+    }
+
+    @Override public QName getQName() {
+        return null;
+    }
+
+    @Override public SchemaPath getPath() {
+        return null;
+    }
+
+    @Override public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+        return null;
+    }
+
+    @Override public String getDescription() {
+        return null;
+    }
+
+    @Override public String getReference() {
+        return null;
+    }
+
+    @Override public Status getStatus() {
+        return null;
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TestLeafSchemaNode.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TestLeafSchemaNode.java
new file mode 100644 (file)
index 0000000..efdb6af
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import java.util.List;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.*;
+
+/**
+ * Mock Leaf Schema Node designated to increase branch coverage in test cases.
+ *
+ * @author Lukas Sedlak <lsedlak@cisco.com>
+ */
+public class TestLeafSchemaNode implements LeafSchemaNode {
+    @Override public TypeDefinition<?> getType() {
+        return null;
+    }
+
+    @Override public String getDefault() {
+        return null;
+    }
+
+    @Override public String getUnits() {
+        return null;
+    }
+
+    @Override public boolean isAugmenting() {
+        return false;
+    }
+
+    @Override public boolean isAddedByUses() {
+        return false;
+    }
+
+    @Override public boolean isConfiguration() {
+        return false;
+    }
+
+    @Override public ConstraintDefinition getConstraints() {
+        return null;
+    }
+
+    @Override public QName getQName() {
+        return null;
+    }
+
+    @Override public SchemaPath getPath() {
+        return null;
+    }
+
+    @Override public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+        return null;
+    }
+
+    @Override public String getDescription() {
+        return null;
+    }
+
+    @Override public String getReference() {
+        return null;
+    }
+
+    @Override public Status getStatus() {
+        return null;
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImplTest.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImplTest.java
new file mode 100644 (file)
index 0000000..1742adc
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * 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.sal.binding.yang.types;
+
+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 com.google.common.base.Optional;
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.NoSuchElementException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTypeBuilderImpl;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+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.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition.EnumPair;
+import org.opendaylight.yangtools.yang.model.util.BinaryType;
+import org.opendaylight.yangtools.yang.model.util.BooleanType;
+import org.opendaylight.yangtools.yang.model.util.Decimal64;
+import org.opendaylight.yangtools.yang.model.util.EmptyType;
+import org.opendaylight.yangtools.yang.model.util.EnumerationType;
+import org.opendaylight.yangtools.yang.model.util.IdentityrefType;
+import org.opendaylight.yangtools.yang.model.util.StringType;
+import org.opendaylight.yangtools.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.LeafSchemaNodeBuilder;
+import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.opendaylight.yangtools.yang.parser.util.YangValidationException;
+
+public class TypeProviderImplTest {
+
+    @Rule
+    public ExpectedException expException = ExpectedException.none();
+
+    @Test (expected = YangValidationException.class)
+    public void testLeafRefRelativeSelfReference() throws Exception {
+        File relative = new File(getClass().getResource("/leafref/leafref-relative-invalid.yang").toURI());
+
+        final YangParserImpl yangParser = new YangParserImpl();
+        final SchemaContext schemaContext = yangParser.parseFiles(Arrays.asList(relative));
+        final Module moduleRelative = schemaContext.findModuleByNamespace(new URI("urn:xml:ns:yang:lrr")).iterator().next();
+        final TypeProviderImpl typeProvider = new TypeProviderImpl(schemaContext);
+
+        DataSchemaNode leafref = ((ListSchemaNode) moduleRelative.getDataChildByName("neighbor")).getDataChildByName("neighbor-id");
+        LeafSchemaNode leaf = (LeafSchemaNode) leafref;
+        TypeDefinition<?> leafType = leaf.getType();
+        Type leafrefResolvedType = typeProvider.javaTypeForSchemaDefinitionType(leafType, leaf);
+    }
+
+    @Test (expected = YangValidationException.class)
+    public void testLeafRefAbsoluteSelfReference() throws Exception {
+        File relative = new File(getClass().getResource("/leafref/leafref-absolute-invalid.yang").toURI());
+
+        final YangParserImpl yangParser = new YangParserImpl();
+        final SchemaContext schemaContext = yangParser.parseFiles(Arrays.asList(relative));
+        final Module moduleRelative = schemaContext.findModuleByNamespace(new URI("urn:xml:ns:yang:lra")).iterator().next();
+        final TypeProviderImpl typeProvider = new TypeProviderImpl(schemaContext);
+
+        DataSchemaNode leafref = ((ListSchemaNode) moduleRelative.getDataChildByName("neighbor")).getDataChildByName("neighbor-id");
+        LeafSchemaNode leaf = (LeafSchemaNode) leafref;
+        TypeDefinition<?> leafType = leaf.getType();
+        Type leafrefResolvedType = typeProvider.javaTypeForSchemaDefinitionType(leafType, leaf);
+    }
+
+    @Test
+    public void testLeafRefRelativeAndAbsoluteValidReference() throws URISyntaxException {
+        File valid = new File(getClass().getResource("/leafref/leafref-valid.yang").toURI());
+
+        final YangParserImpl yangParser = new YangParserImpl();
+        final SchemaContext schemaContext = yangParser.parseFiles(Arrays.asList(valid));
+        final Module moduleValid = schemaContext.findModuleByNamespace(new URI("urn:xml:ns:yang:lrv")).iterator().next();
+        final TypeProviderImpl typeProvider = new TypeProviderImpl(schemaContext);
+
+        DataSchemaNode leafrefRel = ((ListSchemaNode) moduleValid.getDataChildByName("neighbor")).getDataChildByName
+                ("neighbor-id");
+        LeafSchemaNode leafRel = (LeafSchemaNode) leafrefRel;
+        TypeDefinition<?> leafTypeRel = leafRel.getType();
+        Type leafrefRelResolvedType = typeProvider.javaTypeForSchemaDefinitionType(leafTypeRel, leafRel);
+        assertNotNull(leafrefRelResolvedType);
+
+        DataSchemaNode leafrefAbs = ((ListSchemaNode) moduleValid.getDataChildByName("neighbor")).getDataChildByName
+                ("neighbor2-id");
+        LeafSchemaNode leafAbs = (LeafSchemaNode) leafrefAbs;
+        TypeDefinition<?> leafTypeAbs = leafAbs.getType();
+        Type leafrefAbsResolvedType = typeProvider.javaTypeForSchemaDefinitionType(leafTypeAbs, leafAbs);
+        assertNotNull(leafrefAbsResolvedType);
+    }
+
+    @Test
+    public void testMethodsOfTypeProviderImpl() throws URISyntaxException {
+        final YangParserImpl yangParser = new YangParserImpl();
+        final File abstractTopology = new File(BaseYangTypes.class.getResource("/base-yang-types.yang")
+                .toURI());
+        final SchemaContext schemaContext = yangParser.parseFiles(Arrays.asList(abstractTopology));
+        final TypeProviderImpl typeProvider = new TypeProviderImpl(schemaContext);
+
+        final SchemaPath refTypePath = SchemaPath.create(true, QName.create("cont1"), QName.create("list1"));
+        final GeneratedTypeBuilderImpl refType = new GeneratedTypeBuilderImpl("org.opendaylight.yangtools.test", "TestType");
+        typeProvider.putReferencedType(refTypePath, refType);
+        final StringType stringType = StringType.getInstance();
+        LeafSchemaNodeBuilder leafSchemaNodeBuilder = new LeafSchemaNodeBuilder("test-module", 111, QName.create("Cont1"), SchemaPath.ROOT);
+        leafSchemaNodeBuilder.setType(stringType);
+        LeafSchemaNode leafSchemaNode = leafSchemaNodeBuilder.build();
+
+        // test constructor
+        assertNotNull(typeProvider);
+
+        // test getAdditionalTypes() method
+        assertFalse(typeProvider.getAdditionalTypes().isEmpty());
+
+        // test getConstructorPropertyName() method
+        assertTrue(typeProvider.getConstructorPropertyName(null).isEmpty());
+        assertEquals("value", typeProvider.getConstructorPropertyName(stringType));
+
+        // test getParamNameFromType() method
+        assertEquals("string", typeProvider.getParamNameFromType(stringType));
+
+        // test getTypeDefaultConstruction() method for string type
+        assertEquals("\"default value\"", typeProvider.getTypeDefaultConstruction(leafSchemaNode, "default value"));
+
+        // binary type
+        final BinaryType binaryType = BinaryType.getInstance();
+        leafSchemaNodeBuilder = new LeafSchemaNodeBuilder("test-module", 111, QName.create("Cont1"), SchemaPath.ROOT);
+        leafSchemaNodeBuilder.setType(binaryType);
+        leafSchemaNode = leafSchemaNodeBuilder.build();
+        assertEquals("new byte[] {-45}", typeProvider.getTypeDefaultConstruction(leafSchemaNode, "01"));
+
+        // boolean type
+        final BooleanType booleanType = BooleanType.getInstance();
+        leafSchemaNodeBuilder = new LeafSchemaNodeBuilder("test-module", 111, QName.create("Cont1"), SchemaPath.ROOT);
+        leafSchemaNodeBuilder.setType(booleanType);
+        leafSchemaNode = leafSchemaNodeBuilder.build();
+        assertEquals("new java.lang.Boolean(\"false\")", typeProvider.getTypeDefaultConstruction(leafSchemaNode, "false"));
+
+        // decimal type
+        final Decimal64 decimalType = Decimal64.create(refTypePath, 4);
+        leafSchemaNodeBuilder = new LeafSchemaNodeBuilder("test-module", 111, QName.create("Cont1"), SchemaPath.ROOT);
+        leafSchemaNodeBuilder.setType(decimalType);
+        leafSchemaNode = leafSchemaNodeBuilder.build();
+        assertEquals("new java.math.BigDecimal(\"111\")", typeProvider.getTypeDefaultConstruction(leafSchemaNode, "111"));
+
+        // empty type
+        final EmptyType emptyType = EmptyType.getInstance();
+        leafSchemaNodeBuilder = new LeafSchemaNodeBuilder("test-module", 111, QName.create("Cont1"), SchemaPath.ROOT);
+        leafSchemaNodeBuilder.setType(emptyType);
+        leafSchemaNode = leafSchemaNodeBuilder.build();
+        assertEquals("new java.lang.Boolean(\"default value\")", typeProvider.getTypeDefaultConstruction(leafSchemaNode, "default value"));
+
+        // enum type
+        expException.expect(NoSuchElementException.class);
+        final EnumerationType enumType = EnumerationType.create(refTypePath, new ArrayList<EnumTypeDefinition.EnumPair>(), Optional.<EnumPair> absent());
+        leafSchemaNodeBuilder = new LeafSchemaNodeBuilder("test-module", 111, QName.create("Cont1"), SchemaPath.ROOT);
+        leafSchemaNodeBuilder.setType(enumType);
+        leafSchemaNode = leafSchemaNodeBuilder.build();
+        assertEquals("\"default value\"", typeProvider.getTypeDefaultConstruction(leafSchemaNode, "default value"));
+
+        // identityref type
+        expException.expect(UnsupportedOperationException.class);
+        expException.expectMessage("Cannot get default construction for identityref type");
+
+        final ModuleBuilder testModBuilder = new ModuleBuilder("test-module", "/test");
+        final IdentitySchemaNodeBuilder identityNodeBuilder = testModBuilder.addIdentity(QName.create("IdentityRefTest"), 111, SchemaPath.ROOT);
+        final IdentitySchemaNode identitySchemaNode = identityNodeBuilder.build();
+        final IdentityrefType identityRef = IdentityrefType.create(refTypePath, identitySchemaNode);
+        leafSchemaNodeBuilder = new LeafSchemaNodeBuilder("test-module", 111, QName.create("Cont1"), SchemaPath.ROOT);
+        leafSchemaNodeBuilder.setType(identityRef);
+
+        leafSchemaNodeBuilder.setParent(identityNodeBuilder);
+        leafSchemaNode = leafSchemaNodeBuilder.build();
+        assertEquals("\"default value\"", typeProvider.getTypeDefaultConstruction(leafSchemaNode, "default value"));
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderModel.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderModel.java
new file mode 100644 (file)
index 0000000..a6d124c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+/**
+ * Test Model Provider designated to load test resources and provide Schema Context
+ * for testing of TypeProviderImpl
+ *
+ * @author Lukas Sedlak <lsedlak@cisco.com>
+ */
+final class TypeProviderModel {
+
+    public static final String TEST_TYPE_PROVIDER_MODULE_NAME = "test-type-provider";
+
+    private static final String BASE_YANG_TYPES_PATH = "/base-yang-types.yang";
+    private static final String TEST_TYPE_PROVIDER_PATH = "/"+TEST_TYPE_PROVIDER_MODULE_NAME+".yang";
+    private static final String TEST_TYPE_PROVIDER_B_PATH = "/test-type-provider-b.yang";
+
+    private static InputStream getInputStream(final String resourceName) {
+        return TypeProviderModel.class.getResourceAsStream(resourceName);
+    }
+
+    private static List<InputStream> provideTestModelStreams() {
+        final List<InputStream> arrayList = new ArrayList<>();
+
+        arrayList.add(getInputStream(BASE_YANG_TYPES_PATH));
+        arrayList.add(getInputStream(TEST_TYPE_PROVIDER_PATH));
+        arrayList.add(getInputStream(TEST_TYPE_PROVIDER_B_PATH));
+        return arrayList;
+    }
+
+    public static SchemaContext createTestContext() {
+        YangParserImpl parser = new YangParserImpl();
+        Set<Module> modules = parser.parseYangModelsFromStreams(provideTestModelStreams());
+        return parser.resolveSchemaContext(modules);
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderTest.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderTest.java
new file mode 100644 (file)
index 0000000..ee40141
--- /dev/null
@@ -0,0 +1,931 @@
+/**
+ * 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.sal.binding.yang.types;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
+import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
+import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
+import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
+import org.opendaylight.yangtools.sal.binding.model.api.*;
+import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
+import org.opendaylight.yangtools.yang.model.api.*;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+
+/**
+ * Test suite for testing public methods in TypeProviderImpl class
+ *
+ * @see org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl
+ *
+ * @author Lukas Sedlak <lsedlak@cisco.com>
+ */
+@RunWith(JUnit4.class)
+public class TypeProviderTest {
+
+    private SchemaContext schemaContext;
+    private Set<Module> schemaModules;
+    private Module testTypeProviderModule;
+
+    @Mock
+    private SchemaPath schemaPath;
+
+    @Mock
+    private SchemaNode schemaNode;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        schemaContext = TypeProviderModel.createTestContext();
+        assertNotNull(schemaContext);
+        schemaModules = schemaContext.getModules();
+        assertNotNull(schemaModules);
+        testTypeProviderModule = resolveModule(TypeProviderModel.TEST_TYPE_PROVIDER_MODULE_NAME);
+        assertNotNull(testTypeProviderModule);
+    }
+
+    private Module resolveModule(final String moduleName) {
+        assertNotNull(moduleName);
+        for (Module m : schemaModules) {
+            if (moduleName.equals(m.getName())) {
+                return m;
+            }
+        }
+        assertTrue("Unable to resolve module " + moduleName + ". No module present within Schema Context!" , false);
+        return null;
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void typeProviderInstanceWithNullSchemaContextTest() {
+        final TypeProvider provider = new TypeProviderImpl(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void putReferencedTypeWithNullSchemaPathParamTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+
+        ((TypeProviderImpl) provider).putReferencedType(null, null);
+        ((TypeProviderImpl) provider).putReferencedType(schemaPath, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void putReferencedTypeWithNullRefTypeParamTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+
+        ((TypeProviderImpl) provider).putReferencedType(schemaPath, null);
+    }
+
+    @Test
+    public void getAdditionalTypesTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+
+        assertNotNull(((TypeProviderImpl) provider).getAdditionalTypes());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void javaTypeForSchemaDefinitionTypeNullTypedefTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+
+        provider.javaTypeForSchemaDefinitionType(null, null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void javaTypeForSchemaDefinitionTypeTypedefNullQNameTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+
+        TestIntegerTypeDefinition testTypedef = new TestIntegerTypeDefinition();
+        provider.javaTypeForSchemaDefinitionType(testTypedef, null, null);
+    }
+
+    private static LeafSchemaNode provideLeafNodeFromTopLevelContainer(final Module module, final String containerName, final String leafNodeName) {
+        final DataSchemaNode rootNode = module.getDataChildByName(containerName);
+        assertNotNull("Container foo is not present in root of module "+ module.getName(), rootNode);
+        assertTrue(rootNode instanceof DataNodeContainer);
+
+        final DataNodeContainer rootContainer = (DataNodeContainer) rootNode;
+        final DataSchemaNode node = rootContainer.getDataChildByName(leafNodeName);
+        assertNotNull(node);
+        assertTrue(node instanceof LeafSchemaNode);
+        return (LeafSchemaNode) node;
+    }
+
+    private static LeafListSchemaNode provideLeafListNodeFromTopLevelContainer(final Module module, final String containerName, final String leafListNodeName) {
+        final DataSchemaNode rootNode = module.getDataChildByName(containerName);
+        assertNotNull("Container foo is not present in root of module "+ module.getName(), rootNode);
+        assertTrue(rootNode instanceof DataNodeContainer);
+
+        final DataNodeContainer rootContainer = (DataNodeContainer) rootNode;
+        final DataSchemaNode node = rootContainer.getDataChildByName(leafListNodeName);
+        assertNotNull(node);
+        assertTrue(node instanceof LeafListSchemaNode);
+        return (LeafListSchemaNode) node;
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionExtTypeTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "yang-int8-type");
+
+        final TypeDefinition<?> leafType = leaf.getType();
+        final Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(result);
+        assertTrue(result instanceof GeneratedTransferObject);
+
+        final GeneratedTransferObject genTO = (GeneratedTransferObject) result;
+        assertEquals("base-yang-types", genTO.getModuleName());
+        assertEquals("org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914", genTO.getPackageName());
+        assertEquals("YangInt8", genTO.getName());
+        assertTrue(genTO.getProperties().size() == 1);
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionRestrictedExtTypeTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "restricted-int8-type");
+
+        final TypeDefinition<?> leafType = leaf.getType();
+        final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(leafType);
+
+        final Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf, restrictions);
+        assertNotNull(result);
+        assertTrue(result instanceof GeneratedTransferObject);
+
+        final GeneratedTransferObject genTO = (GeneratedTransferObject) result;
+        assertEquals("org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914", genTO.getPackageName());
+        assertEquals("YangInt8Restricted", genTO.getName());
+        assertTrue(genTO.getProperties().size() == 1);
+        final List<RangeConstraint> rangeConstraints = genTO.getRestrictions().getRangeConstraints();
+
+        assertTrue(!rangeConstraints.isEmpty());
+        final RangeConstraint constraint = rangeConstraints.get(0);
+        assertEquals(BigInteger.ONE, constraint.getMin());
+        assertEquals(BigInteger.valueOf(100), constraint.getMax());
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionEmptyStringPatternTypeTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final Module testTypeProvider = resolveModule("test-type-provider");
+        final TypeDefinition<?> emptyPatternString = resolveTypeDefinitionFromModule(testTypeProvider, "empty-pattern-string");
+
+        assertNotNull(emptyPatternString);
+        final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(emptyPatternString);
+
+        Type result = provider.javaTypeForSchemaDefinitionType(emptyPatternString, emptyPatternString, restrictions);
+        assertNotNull(result);
+        assertTrue(result instanceof GeneratedTransferObject);
+
+        result = provider.generatedTypeForExtendedDefinitionType(emptyPatternString, emptyPatternString);
+        assertNotNull(result);
+        assertTrue(result instanceof GeneratedTransferObject);
+    }
+
+    private static TypeDefinition<?> resolveTypeDefinitionFromModule(final Module module, final String typedefName) {
+        TypeDefinition<?> result = null;
+        final Set<TypeDefinition<?>> typeDefs = module.getTypeDefinitions();
+        for (final TypeDefinition<?> typedef : typeDefs) {
+            if (typedef.getQName().getLocalName().equals(typedefName)) {
+                result = typedef;
+            }
+        }
+        return result;
+    }
+
+    /**
+     * FIXME: Remove @Ignore annotation once the bug https://bugs.opendaylight.org/show_bug.cgi?id=1862 is fixed
+     */
+    @Ignore
+    @Test
+    public void bug1862RestrictedTypedefTransformationTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "bug-1862-restricted-typedef");
+
+        final TypeDefinition<?> leafType = leaf.getType();
+        final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(leafType);
+        final Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf, restrictions);
+        assertNotNull(result);
+        assertTrue(result instanceof GeneratedTransferObject);
+        //TODO: complete test after bug 1862 is fixed
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionEnumExtTypeTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "resolve-enum-leaf");
+        TypeDefinition<?> leafType = leaf.getType();
+        Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(result);
+        assertTrue(result instanceof Enumeration);
+
+        final Enumeration enumType = (Enumeration) result;
+        final List<Enumeration.Pair> enumValues = enumType.getValues();
+        assertTrue(!enumValues.isEmpty());
+        assertEquals("A", enumValues.get(0).getName());
+        assertEquals("B", enumValues.get(1).getName());
+
+        leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "resolve-direct-use-of-enum");
+        leafType = leaf.getType();
+        result = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(result);
+        assertTrue(result instanceof ConcreteType);
+
+        assertEquals("java.lang", result.getPackageName());
+        assertEquals("Enum", result.getName());
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionLeafrefExtTypeTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "bar", "leafref-value");
+        TypeDefinition<?> leafType = leaf.getType();
+        final Type leafrefResolvedType1 = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(leafrefResolvedType1);
+        assertTrue(leafrefResolvedType1 instanceof GeneratedTransferObject);
+
+        final Module module = resolveModule("test-type-provider-b");
+        final DataSchemaNode rootNode = module.getDataChildByName("id");
+        assertNotNull("leaf id is not present in root of module "+ module.getName(), rootNode);
+        assertTrue(rootNode instanceof LeafSchemaNode);
+        leaf = (LeafSchemaNode) rootNode;
+        leafType = leaf.getType();
+
+        final Type leafrefResolvedType2 = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(leafrefResolvedType2);
+        assertTrue(leafrefResolvedType2 instanceof GeneratedTransferObject);
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionLeafrefToEnumTypeTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+
+        setReferencedTypeForTypeProvider(provider);
+
+        final Module module = resolveModule("test-type-provider-b");
+
+        final DataSchemaNode enumNode = module.getDataChildByName("enum");
+        assertNotNull("leaf enum is not present in root of module " + module.getName(), enumNode);
+        assertTrue(enumNode instanceof LeafSchemaNode);
+        LeafSchemaNode leaf = (LeafSchemaNode) enumNode;
+        final TypeDefinition<?> leafType = leaf.getType();
+
+        final Type leafrefResolvedType1 = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(leafrefResolvedType1);
+        assertTrue(leafrefResolvedType1 instanceof ReferencedTypeImpl);
+
+        final DataSchemaNode enumListNode = module.getDataChildByName("enums");
+        assertNotNull("leaf-list enums is not present in root of module "+ module.getName(), enumNode);
+        assertTrue(enumListNode instanceof LeafListSchemaNode);
+        LeafListSchemaNode leafList = (LeafListSchemaNode) enumListNode;
+        TypeDefinition<?> leafListType = leafList.getType();
+
+        final Type leafrefResolvedType2 = provider.javaTypeForSchemaDefinitionType(leafListType, leafList);
+        assertNotNull(leafrefResolvedType2);
+        assertTrue(leafrefResolvedType2 instanceof ParameterizedType);
+    }
+
+    private void setReferencedTypeForTypeProvider(TypeProvider provider) {
+        final LeafSchemaNode enumLeafNode = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo",
+            "resolve-direct-use-of-enum");
+        final TypeDefinition<?> enumLeafTypedef = enumLeafNode.getType();
+        Type enumType = provider.javaTypeForSchemaDefinitionType(enumLeafTypedef, enumLeafNode);
+
+        Type refType = new ReferencedTypeImpl(enumType.getPackageName(), enumType.getName());
+        ((TypeProviderImpl) provider).putReferencedType(enumLeafNode.getPath(), refType);
+
+        final LeafListSchemaNode enumListNode = provideLeafListNodeFromTopLevelContainer(testTypeProviderModule, "foo",
+            "list-of-enums");
+        final TypeDefinition<?> enumLeafListTypedef = enumListNode.getType();
+        enumType = provider.javaTypeForSchemaDefinitionType(enumLeafListTypedef, enumListNode);
+
+        refType = new ReferencedTypeImpl(enumType.getPackageName(), enumType.getPackageName());
+        ((TypeProviderImpl) provider).putReferencedType(enumListNode.getPath(), refType);
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionConditionalLeafrefTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        final Module module = resolveModule("test-type-provider-b");
+
+        final DataSchemaNode condLeaf = module.getDataChildByName("conditional-leafref");
+        assertNotNull("leaf conditional-leafref is not present in root of module "+ module.getName(), condLeaf);
+        assertTrue(condLeaf instanceof LeafSchemaNode);
+        LeafSchemaNode leaf = (LeafSchemaNode) condLeaf;
+        final TypeDefinition<?> leafType = leaf.getType();
+
+        final Type resultType = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(resultType);
+        assertTrue(resultType instanceof ConcreteType);
+        assertEquals("java.lang", resultType.getPackageName());
+        assertEquals("Object", resultType.getName());
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void javaTypeForSchemaDefinitionInvalidLeafrefPathTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        final Module module = resolveModule("test-type-provider-b");
+
+        final DataSchemaNode condLeaf = module.getDataChildByName("unreslovable-leafref");
+        assertNotNull("leaf unreslovable-leafref is not present in root of module "+ module.getName(), condLeaf);
+        assertTrue(condLeaf instanceof LeafSchemaNode);
+        LeafSchemaNode leaf = (LeafSchemaNode) condLeaf;
+        final TypeDefinition<?> leafType = leaf.getType();
+
+        provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void provideTypeForLeafrefWithNullLeafrefTypeTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        provider.provideTypeForLeafref(null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void provideTypeForLeafrefWithNullLeafrefTypePathStatementTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final LeafrefTypeWithNullXpath leafrePath = new LeafrefTypeWithNullXpath();
+        provider.provideTypeForLeafref(leafrePath, schemaNode);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void provideTypeForLeafrefWithNullRewisionAwareXPathTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final LeafrefTypeWithNullToStringInXpath leafrePath = new LeafrefTypeWithNullToStringInXpath();
+        provider.provideTypeForLeafref(leafrePath, schemaNode);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void provideTypeForLeafrefWithNullParentModuleTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+        LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "bar", "leafref-value");
+        TypeDefinition<?> leafType = leaf.getType();
+        assertTrue(leafType instanceof LeafrefTypeDefinition);
+        provider.provideTypeForLeafref((LeafrefTypeDefinition) leafType, schemaNode);
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionIdentityrefExtTypeTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "crypto");
+        final TypeDefinition<?> leafType = leaf.getType();
+
+        final Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(result);
+        assertTrue(result instanceof ParameterizedType);
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionForExtUnionWithSimpleTypesTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "use-of-unions", "simple-int-types-union");
+        final TypeDefinition<?> leafType = leaf.getType();
+
+        final Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(result);
+        assertTrue(result instanceof GeneratedTransferObject);
+        assertEquals("YangUnion", result.getName());
+        //TODO: write additional asserts to compare whole GeneratedTrasnferObject against yang union definition
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionForExtComplexUnionWithInnerUnionTypesTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "use-of-unions", "complex-union");
+        final TypeDefinition<?> leafType = leaf.getType();
+
+        final Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(result);
+        assertTrue(result instanceof GeneratedTransferObject);
+        assertEquals("ComplexUnion", result.getName());
+        //TODO: write additional asserts to compare whole GeneratedTrasnferObject against yang union definition
+    }
+
+    @Test
+    public void javaTypeForSchemaDefinitionForExtUnionWithInnerUnionAndSimpleTypeTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "use-of-unions", "complex-string-int-union");
+        final TypeDefinition<?> leafType = leaf.getType();
+
+        final Type result = provider.javaTypeForSchemaDefinitionType(leafType, leaf);
+        assertNotNull(result);
+        assertTrue(result instanceof GeneratedTransferObject);
+        assertEquals("ComplexStringIntUnion", result.getName());
+        //TODO: write additional asserts to compare whole GeneratedTrasnferObject against yang union definition
+    }
+
+    @Test
+    public void provideGeneratedTOBuilderForUnionTypeDefWithInnerUnionTypesTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final Module testTypeProvider = resolveModule("test-type-provider");
+        final TypeDefinition<?> unionTypeDef = resolveTypeDefinitionFromModule(testTypeProvider, "complex-union");
+
+        assertNotNull(unionTypeDef);
+        assertTrue(unionTypeDef.getBaseType() instanceof UnionTypeDefinition);
+        GeneratedTOBuilder unionTypeBuilder = provider.provideGeneratedTOBuilderForUnionTypeDef("test.package.name",
+            (UnionTypeDefinition)unionTypeDef.getBaseType(), "ComplexUnionType", unionTypeDef);
+
+        assertNotNull(unionTypeBuilder);
+
+        GeneratedTransferObject unionType = unionTypeBuilder.toInstance();
+        assertEquals("ComplexUnionType", unionType.getName());
+
+        unionTypeBuilder = provider.provideGeneratedTOBuilderForUnionTypeDef("test.package.name",
+            (UnionTypeDefinition)unionTypeDef.getBaseType(), "", unionTypeDef);
+
+        assertNotNull(unionTypeBuilder);
+
+        unionType = unionTypeBuilder.toInstance();
+        assertEquals("Union", unionType.getName());
+
+        unionTypeBuilder = provider.provideGeneratedTOBuilderForUnionTypeDef("test.package.name",
+            (UnionTypeDefinition)unionTypeDef.getBaseType(), null, unionTypeDef);
+
+        assertNotNull(unionTypeBuilder);
+
+        unionType = unionTypeBuilder.toInstance();
+        assertEquals("Union", unionType.getName());
+    }
+
+    @Test
+    public void provideGeneratedTOBuilderForUnionTypeDefWithInnerUnionAndSimpleTypeTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final Module testTypeProvider = resolveModule("test-type-provider");
+        final TypeDefinition<?> unionTypeDef = resolveTypeDefinitionFromModule(testTypeProvider, "complex-string-int-union");
+
+        assertNotNull(unionTypeDef);
+        assertTrue(unionTypeDef.getBaseType() instanceof UnionTypeDefinition);
+        final GeneratedTOBuilder unionTypeBuilder = provider.provideGeneratedTOBuilderForUnionTypeDef("test.package.name",
+            (UnionTypeDefinition)unionTypeDef.getBaseType(), "ComplexStringIntUnionType", unionTypeDef);
+
+        assertNotNull(unionTypeBuilder);
+
+        GeneratedTransferObject unionType = unionTypeBuilder.toInstance();
+        assertEquals("ComplexStringIntUnionType", unionType.getName());
+    }
+
+    @Test
+    public void generatedTypeForExtendedDefinitionTypeTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final Module baseYangTypes = resolveModule("base-yang-types");
+        final Set<TypeDefinition<?>> typeDefs = baseYangTypes.getTypeDefinitions();
+
+        Type yangBoolean = null;
+        Type yangEmpty = null;
+        Type yangEnumeration = null;
+        Type yangInt8 = null;
+        Type yangInt8Restricted = null;
+        Type yangInt16 = null;
+        Type yangInt32 = null;
+        Type yangInt64 = null;
+        Type yangString = null;
+        Type yangDecimal = null;
+        Type yangUint8 = null;
+        Type yangUint16 = null;
+        Type yangUint32 = null;
+        Type yangUint64 = null;
+        Type yangUnion = null;
+        Type yangBinary = null;
+        Type yangBits = null;
+        Type yangInstanceIdentifier = null;
+
+        for (TypeDefinition<?> typedef : typeDefs) {
+            Type type = provider.generatedTypeForExtendedDefinitionType(typedef, typedef);
+            if (type instanceof GeneratedTransferObject) {
+                if (type.getName().equals("YangBoolean")) {
+                    yangBoolean = type;
+                } else if (type.getName().equals("YangEmpty")) {
+                    yangEmpty = type;
+                } else if (type.getName().equals("YangInt8")) {
+                    yangInt8 = type;
+                } else if (type.getName().equals("YangInt8Restricted")) {
+                    yangInt8Restricted = type;
+                } else if (type.getName().equals("YangInt16")) {
+                    yangInt16 = type;
+                } else if (type.getName().equals("YangInt32")) {
+                    yangInt32 = type;
+                } else if (type.getName().equals("YangInt64")) {
+                    yangInt64 = type;
+                } else if (type.getName().equals("YangString")) {
+                    yangString = type;
+                } else if (type.getName().equals("YangDecimal64")) {
+                    yangDecimal = type;
+                } else if (type.getName().equals("YangUint8")) {
+                    yangUint8 = type;
+                } else if (type.getName().equals("YangUint16")) {
+                    yangUint16 = type;
+                } else if (type.getName().equals("YangUint32")) {
+                    yangUint32 = type;
+                } else if (type.getName().equals("YangUint64")) {
+                    yangUint64 = type;
+                } else if (type.getName().equals("YangUnion")) {
+                    yangUnion = type;
+                } else if (type.getName().equals("YangBinary")) {
+                    yangBinary = type;
+                } else if (type.getName().equals("YangInstanceIdentifier")) {
+                    yangInstanceIdentifier = type;
+                } else if (type.getName().equals("YangBits")) {
+                    yangBits = type;
+                }
+            } else if (type instanceof Enumeration) {
+                if (type.getName().equals("YangEnumeration")) {
+                    yangEnumeration = type;
+                }
+            }
+        }
+
+        assertNotNull(yangBoolean);
+        assertNotNull(yangEmpty);
+        assertNotNull(yangEnumeration);
+        assertNotNull(yangInt8);
+        assertNotNull(yangInt8Restricted);
+        assertNotNull(yangInt16);
+        assertNotNull(yangInt32);
+        assertNotNull(yangInt64);
+        assertNotNull(yangString);
+        assertNotNull(yangDecimal);
+        assertNotNull(yangUint8);
+        assertNotNull(yangUint16);
+        assertNotNull(yangUint32);
+        assertNotNull(yangUint64);
+        assertNotNull(yangUnion);
+        assertNotNull(yangBinary);
+        assertNotNull(yangBits);
+        assertNotNull(yangInstanceIdentifier);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void generatedTypeForExtendedDefinitionTypeWithTypedefNullTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+        provider.generatedTypeForExtendedDefinitionType(null, null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void generatedTypeForExtendedDefinitionTypeWithTypedefQNameNullTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+        TestIntegerTypeDefinition testInt = new TestIntegerTypeDefinition();
+        provider.generatedTypeForExtendedDefinitionType(testInt, testInt);
+    }
+
+    @Test
+    public void generatedTypeForExtendedDefinitionTypeWithInnerExtendedTypeTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final Module baseYangTypes = resolveModule("test-type-provider");
+        TypeDefinition<?> extYangInt8Typedef = resolveTypeDefinitionFromModule(baseYangTypes, "extended-yang-int8");
+        assertNotNull(extYangInt8Typedef);
+        Type extType = provider.generatedTypeForExtendedDefinitionType(extYangInt8Typedef, extYangInt8Typedef);
+        assertNotNull(extType);
+        assertTrue(extType instanceof GeneratedTransferObject);
+    }
+
+    @Test
+    public void generatedTypeForExtendedDefinitionTypeWithLeafrefBaseTypeTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final Module baseYangTypes = resolveModule("test-type-provider");
+        TypeDefinition<?> barItemLeafrefId = resolveTypeDefinitionFromModule(baseYangTypes, "bar-item-leafref-id");
+        assertNotNull(barItemLeafrefId);
+        Type extType = provider.generatedTypeForExtendedDefinitionType(barItemLeafrefId, barItemLeafrefId);
+        assertEquals(null, extType);
+    }
+
+    @Test
+    public void generatedTypeForExtendedDefinitionTypeWithIdentityrefBaseTypeTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final Module baseYangTypes = resolveModule("test-type-provider");
+
+        TypeDefinition<?> aesIdentityrefType = resolveTypeDefinitionFromModule(baseYangTypes, "aes-identityref-type");
+
+        assertNotNull(aesIdentityrefType);
+        Type extType = provider.generatedTypeForExtendedDefinitionType(aesIdentityrefType, aesIdentityrefType);
+        assertEquals(null, extType);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void provideGeneratedTOBuilderForBitsTypeDefinitionWithNullTypedefTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+        provider.provideGeneratedTOBuilderForBitsTypeDefinition("", null, "", "");
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void provideGeneratedTOBuilderForBitsTypeDefinitionWithBasePackageNullTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "yang-int8-type");
+        final TypeDefinition<?> leafType = leaf.getType();
+        provider.provideGeneratedTOBuilderForBitsTypeDefinition(null, leafType, "", "");
+    }
+
+    @Test
+    public void provideGeneratedTOBuilderForBitsTypeDefinitionWithNonBitsTypedefTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "yang-int8-type");
+        final TypeDefinition<?> leafType = leaf.getType();
+        Type type = provider.provideGeneratedTOBuilderForBitsTypeDefinition("", leafType, "", "");
+
+        assertEquals(null, type);
+    }
+
+    @Test
+    public void getConstructorPropertyNameTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "yang-int8-type");
+        final TypeDefinition<?> leafType = leaf.getType();
+
+        final String ctorPropertyName = provider.getConstructorPropertyName(leafType);
+        assertEquals("value", ctorPropertyName);
+
+        final String emptyStringName = provider.getConstructorPropertyName(leaf);
+        assertTrue(emptyStringName.isEmpty());
+    }
+
+    @Test
+    public void getParamNameFromTypeTest() {
+        final TypeProvider provider = new TypeProviderImpl(schemaContext);
+
+        final LeafSchemaNode leaf = provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "foo", "yang-int8-type");
+        final TypeDefinition<?> leafType = leaf.getType();
+
+        final String paramName = provider.getParamNameFromType(leafType);
+        assertEquals("yangInt8", paramName);
+    }
+
+    @Test
+    public void addUnitsToGenTOTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        GeneratedTOBuilder builder = new GeneratedTOBuilderImpl("test.package", "TestBuilder");
+
+        provider.addUnitsToGenTO(builder, null);
+        GeneratedTransferObject genTO = builder.toInstance();
+        assertTrue(genTO.getConstantDefinitions().isEmpty());
+
+        provider.addUnitsToGenTO(builder, "");
+        genTO = builder.toInstance();
+        assertTrue(genTO.getConstantDefinitions().isEmpty());
+
+        provider.addUnitsToGenTO(builder, "125");
+        genTO = builder.toInstance();
+        assertTrue(!genTO.getConstantDefinitions().isEmpty());
+        assertEquals(1, genTO.getConstantDefinitions().size());
+        assertEquals("_UNITS", genTO.getConstantDefinitions().get(0).getName());
+        assertEquals(genTO.getConstantDefinitions().get(0).getValue(), "\"125\"");
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void getTypeDefaultConstructionLeafTypeNullTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+        TestLeafSchemaNode leafSchemaNode = new TestLeafSchemaNode();
+        provider.getTypeDefaultConstruction(leafSchemaNode, null);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void getTypeDefaultConstructionDefaultValueNullTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+        final LeafSchemaNode leaf = provideLeafForGetDefaultConstructionTestCase("yang-boolean");
+        provider.getTypeDefaultConstruction(leaf, null);
+    }
+
+    private LeafSchemaNode provideLeafForGetDefaultConstructionTestCase(final String leafName) {
+        return provideLeafNodeFromTopLevelContainer(testTypeProviderModule, "construction-type-test",
+            leafName);
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void getTypeDefaultConstructionDefaultValueForInstanceIdentifierTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+        LeafSchemaNode leaf = provideLeafForGetDefaultConstructionTestCase("foo-container-id");
+        provider.getTypeDefaultConstruction(leaf, "NAN");
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void getTypeDefaultConstructionDefaultValueForIdentityrefTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+        LeafSchemaNode leaf = provideLeafForGetDefaultConstructionTestCase("aes-identityref-type");
+        provider.getTypeDefaultConstruction(leaf, "NAN");
+    }
+
+    @Test
+    public void getTypeDefaultConstructionDefaultValueTest() {
+        final TypeProviderImpl provider = new TypeProviderImpl(schemaContext);
+
+        LeafSchemaNode leaf = provideLeafForGetDefaultConstructionTestCase("yang-boolean");
+        String result = provider.getTypeDefaultConstruction(leaf, "true");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangBoolean(new java.lang.Boolean(\"true\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-empty");
+        result = provider.getTypeDefaultConstruction(leaf, "true");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangEmpty(new java.lang.Boolean(\"true\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-enumeration");
+        result = provider.getTypeDefaultConstruction(leaf, "a");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangEnumeration.A",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("direct-use-of-enum");
+        result = provider.getTypeDefaultConstruction(leaf, "y");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.type.provider.model.rev140912.construction.type.test.DirectUseOfEnum.Y",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-int8");
+        result = provider.getTypeDefaultConstruction(leaf, "17");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangInt8(new java.lang.Byte(\"17\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-int8-restricted");
+        result = provider.getTypeDefaultConstruction(leaf, "99");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangInt8Restricted(new java.lang.Byte(\"99\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-int16");
+        result = provider.getTypeDefaultConstruction(leaf, "1024");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangInt16(new java.lang.Short(\"1024\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-int32");
+        result = provider.getTypeDefaultConstruction(leaf, "1048576");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangInt32(new java.lang.Integer(\"1048576\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-int64");
+        result = provider.getTypeDefaultConstruction(leaf, "1099511627776");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangInt64(new java.lang.Long(\"1099511627776\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-string");
+        result = provider.getTypeDefaultConstruction(leaf, "TEST");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangString(\"TEST\")",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-decimal64");
+        result = provider.getTypeDefaultConstruction(leaf, "1274.25");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangDecimal64(new java.math.BigDecimal(\"1274.25\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-uint8");
+        result = provider.getTypeDefaultConstruction(leaf, "128");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangUint8(new java.lang.Short(\"128\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-uint16");
+        result = provider.getTypeDefaultConstruction(leaf, "1048576");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangUint16(new java.lang.Integer(\"1048576\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-uint32");
+        result = provider.getTypeDefaultConstruction(leaf, "1099511627776");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangUint32(new java.lang.Long(\"1099511627776\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-uint64");
+        result = provider.getTypeDefaultConstruction(leaf, "1208925819614629174706176");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangUint64(new java.math.BigInteger(\"1208925819614629174706176\"))",
+            result);
+
+        //FIXME: Is this correct scenario and correct result?
+        leaf = provideLeafForGetDefaultConstructionTestCase("complex-union");
+        result = provider.getTypeDefaultConstruction(leaf, "75");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.type.provider.model.rev140912.ComplexUnion(\"null\".toCharArray())",
+            result);
+
+        //FIXME: Is this correct scenario and correct result?
+        leaf = provideLeafForGetDefaultConstructionTestCase("complex-string-int-union");
+        result = provider.getTypeDefaultConstruction(leaf, "TEST_UNION_STRING_DEFAULT");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.type.provider.model.rev140912.ComplexStringIntUnion(\"null\".toCharArray())",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("simple-int-types-union");
+        result = provider.getTypeDefaultConstruction(leaf, "2048");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangUnion(\"null\".toCharArray())",
+            result);
+
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("direct-union-leaf");
+        result = provider.getTypeDefaultConstruction(leaf);
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.type.provider.model.rev140912.DirectUnionLeaf(\"128\".toCharArray())",
+            result);
+
+        final Module module = resolveModule("test-type-provider");
+        DataSchemaNode rootNode = module.getDataChildByName("root-union-leaf");
+        assertNotNull("leaf root-union-leaf is not present in root of module "+ module.getName(), rootNode);
+        assertTrue(rootNode instanceof LeafSchemaNode);
+        leaf = (LeafSchemaNode) rootNode;
+        result = provider.getTypeDefaultConstruction(leaf);
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.type.provider.model.rev140912.TestTypeProviderData.RootUnionLeaf(\"256\".toCharArray())",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-binary");
+        result = provider.getTypeDefaultConstruction(leaf, "0xffffff");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangBinary(new byte[] {-45, 23, -33, 125, -9, -33})",
+            result);
+
+        rootNode = module.getDataChildByName("root-bits-leaf");
+        assertNotNull("leaf bits-leaf is not present in root of module "+ module.getName(), rootNode);
+        assertTrue(rootNode instanceof LeafSchemaNode);
+        leaf = (LeafSchemaNode) rootNode;
+        result = provider.getTypeDefaultConstruction(leaf);
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.type.provider.model.rev140912.TestTypeProviderData.RootBitsLeaf(false, true, false)",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("yang-bits");
+        result = provider.getTypeDefaultConstruction(leaf, "10-Mb-only");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangBits(true, false, false)",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("bar-id");
+        result = provider.getTypeDefaultConstruction(leaf, "128");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangInt16(new java.lang.Short(\"128\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("foo-leafref-value");
+        result = provider.getTypeDefaultConstruction(leaf, "32");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new org.opendaylight.yang.gen.v1.urn.opendaylight.org.test.base.yang.types.rev140914.YangInt8(new java.lang.Byte(\"32\"))",
+            result);
+
+        leaf = provideLeafForGetDefaultConstructionTestCase("foo-cond-bar-item");
+        result = provider.getTypeDefaultConstruction(leaf, "10");
+        assertNotNull(result);
+        assertTrue(!result.isEmpty());
+        assertEquals("new java.lang.Object()",
+            result);
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/UnionDependencySortTest.java b/code-generator/binding-type-provider/src/test/java/org/opendaylight/yangtools/sal/binding/yang/types/UnionDependencySortTest.java
new file mode 100644 (file)
index 0000000..5a8a282
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.sal.binding.yang.types;
+
+import static org.junit.Assert.assertNotNull;
+
+import com.google.common.base.Optional;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.ExtendedType;
+import org.opendaylight.yangtools.yang.model.util.StringType;
+
+public class UnionDependencySortTest {
+
+    @Rule
+    public ExpectedException expException = ExpectedException.none();
+
+    @Test
+    public void testSortMethod() {
+
+        final UnionDependencySort unionDependencySort = new UnionDependencySort();
+        final Set<TypeDefinition<?>> typeDefs = new HashSet<>();
+
+        final StringType stringType = StringType.getInstance();
+        final ExtendedType extendedType = ExtendedType.builder(QName.create("ExtendedType1"), stringType, Optional.<String> absent(), Optional.<String> absent(), SchemaPath.create(false, QName.create("Cont1"), QName.create("List1"))).build();
+
+        typeDefs.add(stringType);
+        typeDefs.add(extendedType);
+
+        final List<ExtendedType> sortedExtendedTypes = unionDependencySort.sort(typeDefs);
+        assertNotNull(sortedExtendedTypes);
+
+        expException.expect(IllegalArgumentException.class);
+        expException.expectMessage("Set of Type Definitions cannot be NULL!");
+        unionDependencySort.sort(null);
+    }
+}
diff --git a/code-generator/binding-type-provider/src/test/resources/base-yang-types.yang b/code-generator/binding-type-provider/src/test/resources/base-yang-types.yang
new file mode 100644 (file)
index 0000000..4dbd079
--- /dev/null
@@ -0,0 +1,111 @@
+module base-yang-types {
+    yang-version 1;
+    namespace "urn:opendaylight:org:test:base:yang:types";
+    prefix "tp";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "This module contains definitions of all Yang base types.";
+
+    revision "2014-09-14" {
+        reference "Added yang-int8-restricted type.";
+     }
+
+    revision "2014-07-23" {
+        reference "Initial Revision.";
+    }
+
+    typedef yang-boolean {
+        type boolean;
+    }
+
+    typedef yang-empty {
+        type empty;
+    }
+
+    typedef yang-enumeration {
+        type enumeration {
+            enum a;
+            enum b;
+        }
+    }
+
+    typedef yang-int8 {
+        type int8;
+    }
+
+    typedef yang-int8-restricted {
+        type int8 {
+            range 1..100;
+        }
+    }
+
+    typedef yang-int16 {
+        type int16;
+    }
+
+    typedef yang-int32 {
+        type int32;
+    }
+
+    typedef yang-int64 {
+        type int64;
+    }
+
+    typedef yang-string {
+        type string;
+    }
+
+    typedef yang-decimal64 {
+        type decimal64 {
+            fraction-digits 2;
+        }
+    }
+
+    typedef yang-uint8 {
+        type uint8;
+    }
+
+    typedef yang-uint16 {
+        type uint16;
+    }
+
+    typedef yang-uint32 {
+        type uint32;
+    }
+
+    typedef yang-uint64 {
+        type uint64;
+    }
+
+    typedef yang-union {
+        type union {
+            type int32;
+            type int16;
+        }
+    }
+
+    typedef yang-binary {
+        type binary;
+    }
+
+    typedef yang-bits {
+        type bits {
+            bit disable-nagle {
+                position 0;
+            }
+            bit auto-sense-speed {
+                position 1;
+            }
+            bit 10-Mb-only {
+                position 2;
+            }
+        }
+        default "auto-sense-speed";
+    }
+
+    typedef yang-instance-identifier {
+        type instance-identifier;
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-type-provider/src/test/resources/leafref/leafref-absolute-invalid.yang b/code-generator/binding-type-provider/src/test/resources/leafref/leafref-absolute-invalid.yang
new file mode 100644 (file)
index 0000000..97d1503
--- /dev/null
@@ -0,0 +1,16 @@
+module leafref-absolute-invalid {
+    namespace "urn:xml:ns:yang:lra";
+    prefix lra;
+    revision "2015-02-25";
+
+    list neighbor {
+        description
+           "List of neighbors.";
+        leaf neighbor-id {
+            type leafref {
+                path "/lra:neighbor/lra:neighbor-id";
+            }
+            description "Neighbor.";
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-type-provider/src/test/resources/leafref/leafref-relative-invalid.yang b/code-generator/binding-type-provider/src/test/resources/leafref/leafref-relative-invalid.yang
new file mode 100644 (file)
index 0000000..a933ae4
--- /dev/null
@@ -0,0 +1,16 @@
+module leafref-relative-invalid {
+    namespace "urn:xml:ns:yang:lrr";
+    prefix lrr;
+    revision "2015-02-25";
+
+    list neighbor {
+         description
+           "List of neighbors.";
+         leaf neighbor-id {
+             type leafref {
+                 path "../../neighbor/neighbor-id";
+             }
+             description "Neighbor.";
+         }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-type-provider/src/test/resources/leafref/leafref-valid.yang b/code-generator/binding-type-provider/src/test/resources/leafref/leafref-valid.yang
new file mode 100644 (file)
index 0000000..fdfa25c
--- /dev/null
@@ -0,0 +1,26 @@
+module leafref-valid {
+     namespace "urn:xml:ns:yang:lrv";
+     prefix lrv;
+     revision "2015-02-25";
+
+    list neighbor {
+        description
+           "List of neighbors.";
+        leaf neighbor-id {
+            type leafref {
+                path "../../neighbor/mystring";
+            }
+            description "Neighbor.";
+        }
+
+        leaf neighbor2-id {
+            type leafref {
+                path "/lrv:neighbor/lrv:mystring";
+            }
+        }
+
+        leaf mystring {
+            type string;
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-type-provider/src/test/resources/test-type-provider-b.yang b/code-generator/binding-type-provider/src/test/resources/test-type-provider-b.yang
new file mode 100644 (file)
index 0000000..0cd10d1
--- /dev/null
@@ -0,0 +1,46 @@
+module test-type-provider-b {
+    yang-version 1;
+    namespace "urn:opendaylight:org:test:type:provider:b:model";
+    prefix "tp";
+
+    import test-type-provider { prefix prov; }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "This module contains model for providing test data for Type Provider Test implementation.";
+
+    revision "2014-09-15" {
+        reference "Initial Revision.";
+    }
+
+    leaf id {
+        type leafref {
+            path "/prov:foo/prov:bars/prov:bar-item/prov:id";
+        }
+    }
+
+    leaf enum {
+        type leafref {
+            path "/prov:foo/prov:resolve-direct-use-of-enum";
+        }
+    }
+
+    leaf-list enums {
+        type leafref {
+            path "/prov:foo/prov:list-of-enums";
+        }
+    }
+
+    leaf conditional-leafref {
+        type leafref {
+            path "/prov:foo/prov:bars/prov:bar-item/[prov:id=10]";
+        }
+    }
+
+    leaf unreslovable-leafref {
+        type leafref {
+            path "/somewhere/i/bellong";
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/binding-type-provider/src/test/resources/test-type-provider.yang b/code-generator/binding-type-provider/src/test/resources/test-type-provider.yang
new file mode 100644 (file)
index 0000000..8f5c455
--- /dev/null
@@ -0,0 +1,308 @@
+module test-type-provider {
+    yang-version 1;
+    namespace "urn:opendaylight:org:test:type:provider:model";
+    prefix "tp";
+
+    import base-yang-types { prefix types; }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "This module contains model for providing test data for Type Provider Test implementation.";
+
+    revision "2014-09-12" {
+        reference "Initial Revision.";
+    }
+
+    identity crypto-alg {
+        description
+            "Base identity from which all crypto algorithms
+            are derived.";
+    }
+
+    identity aes {
+        base "crypto-alg";
+    }
+
+    typedef extended-yang-int8 {
+        type types:yang-int8 {
+            range 1..100;
+        }
+        default 10;
+    }
+
+    typedef inner-union {
+        type union {
+            type int32;
+            type int16;
+        }
+    }
+
+    typedef restricted-string {
+        type string {
+            length "0..4";
+            pattern "[0-9a-fA-F]*";
+        }
+    }
+
+    typedef empty-pattern-string {
+        type string {
+            pattern "";
+        }
+    }
+
+    typedef complex-union {
+        type union {
+            type restricted-string;
+            type inner-union;
+            type union {
+                type enumeration {
+                    enum a;
+                    enum b;
+                    enum c;
+                }
+            }
+        }
+    }
+
+    typedef complex-string-int-union {
+        type union {
+            type inner-union;
+            type string;
+        }
+    }
+
+    typedef aes-identityref-type {
+        type identityref {
+            base "aes";
+        }
+    }
+
+    typedef bar-item-leafref-id {
+        type leafref {
+            path "/foo/bars/bar-item/id";
+        }
+    }
+
+    container foo {
+        container bars {
+            list bar-item {
+                key "id";
+
+                leaf id {
+                    type types:yang-int16;
+                }
+            }
+        }
+
+        leaf yang-int8-type {
+            type types:yang-int8;
+        }
+
+        leaf bug-1862-restricted-typedef {
+            type types:yang-int8 {
+                range "1..100";
+            }
+        }
+
+        leaf restricted-int8-type {
+            type types:yang-int8-restricted;
+        }
+
+        leaf restricted-int {
+            type int16 {
+                range "1..100";
+            }
+        }
+
+        leaf resolve-enum-leaf {
+            type types:yang-enumeration;
+        }
+
+        leaf resolve-direct-use-of-enum {
+            type enumeration {
+                enum x;
+                enum y;
+                enum z;
+            }
+        }
+
+        leaf-list list-of-enums {
+            type enumeration {
+                enum x;
+                enum y;
+                enum z;
+            }
+        }
+
+        leaf crypto {
+            type identityref {
+                base "crypto-alg";
+            }
+        }
+    }
+
+    container bar {
+        leaf leafref-value {
+            type leafref {
+                path "../../foo/yang-int8-type";
+            }
+        }
+    }
+
+    container use-of-unions {
+        leaf complex-union {
+            type complex-union;
+        }
+
+        leaf complex-string-int-union {
+            type complex-string-int-union;
+        }
+
+        leaf simple-int-types-union {
+            type types:yang-union;
+        }
+    }
+
+    container construction-type-test {
+        leaf yang-boolean {
+            type types:yang-boolean;
+        }
+
+        leaf yang-empty {
+            type types:yang-empty;
+        }
+
+        leaf yang-enumeration {
+            type types:yang-enumeration;
+        }
+
+        leaf direct-use-of-enum {
+            type enumeration {
+                enum x;
+                enum y;
+                enum z;
+            }
+        }
+
+        leaf yang-int8 {
+            type types:yang-int8;
+        }
+
+        leaf yang-int8-restricted {
+            type types:yang-int8-restricted;
+        }
+
+        leaf yang-int16 {
+            type types:yang-int16;
+        }
+
+        leaf yang-int32 {
+            type types:yang-int32;
+        }
+
+        leaf yang-int64 {
+            type types:yang-int64;
+        }
+
+        leaf yang-string {
+            type types:yang-string;
+        }
+
+        leaf yang-decimal64 {
+            type types:yang-decimal64;
+        }
+
+        leaf yang-uint8 {
+            type types:yang-uint8;
+        }
+
+        leaf yang-uint16 {
+            type types:yang-uint16;
+        }
+
+        leaf yang-uint32 {
+            type types:yang-uint32;
+        }
+
+        leaf yang-uint64 {
+            type types:yang-uint64;
+        }
+
+        leaf complex-union {
+            type complex-union;
+        }
+
+        leaf complex-string-int-union {
+            type complex-string-int-union;
+        }
+
+        leaf simple-int-types-union {
+            type types:yang-union;
+        }
+
+        leaf direct-union-leaf {
+            type union {
+                type int32;
+                type int64;
+            }
+            default "128";
+        }
+
+        leaf yang-binary {
+            type types:yang-binary;
+        }
+
+        leaf yang-bits {
+            type types:yang-bits;
+        }
+
+        leaf bar-id {
+            type bar-item-leafref-id;
+            default "128";
+        }
+
+        leaf foo-leafref-value {
+            type leafref {
+                path "../../foo/yang-int8-type";
+            }
+        }
+
+        leaf foo-cond-bar-item {
+            type leafref {
+                path "../../foo/bars/bar-item/[id=10]";
+            }
+        }
+
+        leaf aes-identityref-type {
+            type aes-identityref-type;
+        }
+
+        leaf foo-container-id {
+            type instance-identifier;
+        }
+    }
+
+    leaf root-bits-leaf {
+        type bits {
+            bit disable-nagle {
+                position 0;
+            }
+            bit auto-sense-speed {
+                position 1;
+            }
+            bit 10-Mb-only {
+                position 2;
+            }
+        }
+        default "auto-sense-speed";
+    }
+
+    leaf root-union-leaf {
+        type union {
+            type int32;
+            type int64;
+        }
+        default "256";
+    }
+}
\ No newline at end of file
diff --git a/code-generator/maven-sal-api-gen-plugin/pom.xml b/code-generator/maven-sal-api-gen-plugin/pom.xml
new file mode 100644 (file)
index 0000000..c82c75a
--- /dev/null
@@ -0,0 +1,97 @@
+<?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>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>maven-sal-api-gen-plugin</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-maven-plugin-spi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-model-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-generator-impl</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-java-api-generator</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-data-api</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.sonatype.plexus</groupId>
+            <artifactId>plexus-build-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+                    </archive>
+                </configuration>
+            </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>
+                        <Import-Package>
+                            !org.apache.maven.plugin.logging,
+                            !org.apache.maven.project
+                            *
+                        </Import-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.eclipse.xtend</groupId>
+                <artifactId>xtend-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
diff --git a/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/maven/sal/api/gen/plugin/CodeGeneratorImpl.java b/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/maven/sal/api/gen/plugin/CodeGeneratorImpl.java
new file mode 100644 (file)
index 0000000..40387d8
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * 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.maven.sal.api.gen.plugin;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.maven.project.MavenProject;
+import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
+import org.opendaylight.yangtools.sal.binding.generator.api.BindingGenerator;
+import org.opendaylight.yangtools.sal.binding.generator.impl.BindingGeneratorImpl;
+import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.sal.java.api.generator.GeneratorJavaFile;
+import org.opendaylight.yangtools.sal.java.api.generator.YangModuleInfoTemplate;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator;
+import org.opendaylight.yangtools.yang2sources.spi.BuildContextAware;
+import org.opendaylight.yangtools.yang2sources.spi.MavenProjectAware;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonatype.plexus.build.incremental.BuildContext;
+
+public final class CodeGeneratorImpl implements BasicCodeGenerator, BuildContextAware, MavenProjectAware {
+    private static final Logger LOG = LoggerFactory.getLogger(CodeGeneratorImpl.class);
+    private static final String FS = File.separator;
+    private BuildContext buildContext;
+    private File projectBaseDir;
+    private Map<String, String> additionalConfig;
+    private MavenProject mavenProject;
+    private File resourceBaseDir;
+
+    @Override
+    public Collection<File> generateSources(final SchemaContext context, final File outputDir,
+            final Set<Module> yangModules) throws IOException {
+        final File outputBaseDir;
+
+        outputBaseDir = outputDir == null ? getDefaultOutputBaseDir() : outputDir;
+
+        final BindingGenerator bindingGenerator = new BindingGeneratorImpl(true);
+        final List<Type> types = bindingGenerator.generateTypes(context, yangModules);
+        final GeneratorJavaFile generator = new GeneratorJavaFile(buildContext, types);
+
+        File persistentSourcesDir = null;
+        if (additionalConfig != null) {
+            String persistenSourcesPath = additionalConfig.get("persistentSourcesDir");
+            if (persistenSourcesPath != null) {
+                persistentSourcesDir = new File(persistenSourcesPath);
+            }
+        }
+        if (persistentSourcesDir == null) {
+            persistentSourcesDir = new File(projectBaseDir, "src" + FS + "main" + FS + "java");
+        }
+
+        List<File> result = generator.generateToFile(outputBaseDir, persistentSourcesDir);
+
+        result.addAll(generateModuleInfos(outputBaseDir, yangModules, context));
+        return result;
+    }
+
+    private Collection<? extends File> generateModuleInfos(final File outputBaseDir, final Set<Module> yangModules,
+                                                           final SchemaContext context) {
+        Builder<File> result = ImmutableSet.builder();
+        Builder<String> bindingProviders = ImmutableSet.builder();
+        for (Module module : yangModules) {
+            Builder<String> currentProvidersBuilder = ImmutableSet.builder();
+            // TODO: do not mutate parameters, output of a method is defined by its return value
+            Set<File> moduleInfoProviders = generateYangModuleInfo(outputBaseDir, module, context, currentProvidersBuilder);
+            ImmutableSet<String> currentProviders = currentProvidersBuilder.build();
+            LOG.info("Adding ModuleInfo providers {}", currentProviders);
+            bindingProviders.addAll(currentProviders);
+            result.addAll(moduleInfoProviders);
+        }
+
+        result.add(writeMetaInfServices(resourceBaseDir, YangModelBindingProvider.class, bindingProviders.build()));
+        return result.build();
+    }
+
+    private File writeMetaInfServices(final File outputBaseDir, final Class<YangModelBindingProvider> serviceClass,
+            final ImmutableSet<String> services) {
+        File metainfServicesFolder = new File(outputBaseDir, "META-INF" + File.separator + "services");
+        metainfServicesFolder.mkdirs();
+        File serviceFile = new File(metainfServicesFolder, serviceClass.getName());
+
+        String src = Joiner.on('\n').join(services);
+
+        return writeFile(serviceFile, src);
+    }
+
+    public static final String DEFAULT_OUTPUT_BASE_DIR_PATH = "target" + File.separator + "generated-sources"
+            + File.separator + "maven-sal-api-gen";
+
+    private File getDefaultOutputBaseDir() {
+        File outputBaseDir;
+        outputBaseDir = new File(DEFAULT_OUTPUT_BASE_DIR_PATH);
+        setOutputBaseDirAsSourceFolder(outputBaseDir, mavenProject);
+        LOG.debug("Adding " + outputBaseDir.getPath() + " as compile source root");
+        return outputBaseDir;
+    }
+
+    private static void setOutputBaseDirAsSourceFolder(final File outputBaseDir, final MavenProject mavenProject) {
+        Preconditions.checkNotNull(mavenProject, "Maven project needs to be set in this phase");
+        mavenProject.addCompileSourceRoot(outputBaseDir.getPath());
+    }
+
+    @Override
+    public void setAdditionalConfig(final Map<String, String> additionalConfiguration) {
+        this.additionalConfig = additionalConfiguration;
+    }
+
+    @Override
+    public void setResourceBaseDir(final File resourceBaseDir) {
+        this.resourceBaseDir = resourceBaseDir;
+    }
+
+    @Override
+    public void setMavenProject(final MavenProject project) {
+        this.mavenProject = project;
+        this.projectBaseDir = project.getBasedir();
+    }
+
+    @Override
+    public void setBuildContext(final BuildContext buildContext) {
+        this.buildContext = Preconditions.checkNotNull(buildContext);
+    }
+
+    private Set<File> generateYangModuleInfo(final File outputBaseDir, final Module module, final SchemaContext ctx,
+            final Builder<String> providerSourceSet) {
+        Builder<File> generatedFiles = ImmutableSet.<File> builder();
+
+        final YangModuleInfoTemplate template = new YangModuleInfoTemplate(module, ctx);
+        String moduleInfoSource = template.generate();
+        if (moduleInfoSource.isEmpty()) {
+            throw new IllegalStateException("Generated code should not be empty!");
+        }
+        String providerSource = template.generateModelProvider();
+
+        final File packageDir = GeneratorJavaFile.packageToDirectory(outputBaseDir,
+                BindingGeneratorUtil.moduleNamespaceToPackageName(module));
+
+        generatedFiles.add(writeJavaSource(packageDir, BindingMapping.MODULE_INFO_CLASS_NAME, moduleInfoSource));
+        generatedFiles
+                .add(writeJavaSource(packageDir, BindingMapping.MODEL_BINDING_PROVIDER_CLASS_NAME, providerSource));
+        providerSourceSet.add(template.getModelBindingProviderName());
+
+        return generatedFiles.build();
+
+    }
+
+    private File writeJavaSource(final File packageDir, final String className, final String source) {
+        if (!packageDir.exists()) {
+            packageDir.mkdirs();
+        }
+        final File file = new File(packageDir, className + ".java");
+        writeFile(file, source);
+        return file;
+    }
+
+    private File writeFile(final File file, final String source) {
+        try (final OutputStream stream = buildContext.newFileOutputStream(file)) {
+            try (final Writer fw = new OutputStreamWriter(stream)) {
+                try (final BufferedWriter bw = new BufferedWriter(fw)) {
+                    bw.write(source);
+                }
+            } catch (Exception e) {
+                LOG.error("Could not write file: {}",file,e);
+            }
+        } catch (Exception e) {
+            LOG.error("Could not create file: {}",file,e);
+        }
+        return file;
+    }
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend b/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/GeneratorImpl.xtend
new file mode 100644 (file)
index 0000000..6cd4960
--- /dev/null
@@ -0,0 +1,1496 @@
+/*
+ * 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.unified.doc.generator
+
+import com.google.common.collect.Iterables
+import java.io.BufferedWriter
+import java.io.File
+import java.io.IOException
+import java.io.OutputStreamWriter
+import java.text.SimpleDateFormat
+import java.util.ArrayList
+import java.util.Collection
+import java.util.HashMap
+import java.util.HashSet
+import java.util.LinkedHashMap
+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.YangInstanceIdentifier
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode
+import org.opendaylight.yangtools.yang.model.api.AugmentationTarget
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode
+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.ExtensionDefinition
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition
+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.NotificationDefinition
+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.TypeDefinition
+import org.opendaylight.yangtools.yang.model.api.UsesNode
+import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint
+import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition
+import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition
+import org.opendaylight.yangtools.yang.model.util.ExtendedType
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import org.sonatype.plexus.build.incremental.BuildContext
+import org.sonatype.plexus.build.incremental.DefaultBuildContext
+
+class GeneratorImpl {
+
+    File path
+    static val REVISION_FORMAT = new SimpleDateFormat("yyyy-MM-dd")
+    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;
+    
+    StringBuilder augmentChildNodesAsString
+    
+    DataSchemaNode lastNodeInTargetPath = null
+
+    def generate(SchemaContext context, File targetPath, Set<Module> modulesToGen) throws IOException {
+        path = targetPath;
+        path.mkdirs();
+        val it = new HashSet;
+        for (module : modulesToGen) {
+            add(generateDocumentation(module, context));
+        }
+        return it;
+    }
+
+    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)
+            currentModule = module;
+            bw.append(generate(module, ctx));
+            bw.close();
+            fw.close();
+        } catch (IOException e) {
+            LOG.error(e.getMessage());
+        }
+        return destination;
+    }
+
+    def generate(Module module, SchemaContext ctx) '''
+        <!DOCTYPE html>
+        <html lang="en">
+          <head>
+            <title>«module.name»</title>
+          </head>
+          <body>
+            Â«body(module, ctx)»
+          </body>
+        </html>
+    '''
+
+    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)»
+
+        Â«groupings(module)»
+
+        Â«dataStore(module)»
+
+        Â«childNodes(module)»
+
+        Â«notifications(module)»
+
+        Â«augmentations(module, ctx)»
+
+        Â«rpcs(module)»
+
+        Â«extensions(module)»
+
+        Â«features(module)»
+
+    '''
+
+
+    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) {
+            return '';
+        }
+        return '''
+            <h2>Type Definitions</h2>
+            <ul>
+            Â«FOR typedef : typedefs»
+                <li>
+                    <h3 id="«typedef.QName.localName»">«typedef.QName.localName»</h3>
+                    <ul>
+                    Â«typedef.descAndRefLi»
+                    Â«typedef.restrictions»
+                    </ul>
+                </li>
+            Â«ENDFOR»
+            </ul>
+        '''
+    }
+
+    private def identities(Module module) {
+        if (module.identities.empty) {
+            return '';
+        }
+        return '''
+            <h2>Identities</h2>
+            <ul>
+            Â«FOR identity : module.identities»
+                <li>
+                    <h3 id="«identity.QName.localName»">«identity.QName.localName»</h3>
+                    <ul>
+                    Â«identity.descAndRefLi»
+                    Â«IF identity.baseIdentity !== null»
+                        Â«listItem("base", identity.baseIdentity.QName.localName)»
+                    Â«ENDIF»
+                    </ul>
+                </li>
+            Â«ENDFOR»
+            </ul>
+        '''
+    }
+
+    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 '';
+        }
+        return '''
+            <h2>Groupings</h2>
+            <ul>
+            Â«FOR grouping : module.groupings»
+                <li>
+                    <h3 id="«grouping.QName.localName»">«grouping.QName.localName»</h3>
+                    <ul>
+                        Â«grouping.descAndRefLi»
+                        Â«FOR childNode : grouping.childNodes»
+                            Â«childNode.printSchemaNodeInfo»
+                        Â«ENDFOR»
+                    </ul>
+                </li>
+            Â«ENDFOR»
+            </ul>
+        '''
+    }
+
+    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 '';
+        }
+        return '''
+            <h2>Datastore Structure</h2>
+            Â«tree(module)»
+        '''
+    }
+
+    def augmentations(Module module, SchemaContext context) {
+        if (module.augmentations.empty) {
+            return '';
+        }
+        return '''
+            <h2>Augmentations</h2>
+            
+            <ul>
+            Â«FOR augment : module.augmentations»
+                <li>
+                    <h3 id="«schemaPathToString(module, augment.targetPath, context, augment)»">
+                    Target [«typeAnchorLink(augment.targetPath,schemaPathToString(module, augment.targetPath, context, augment))»]</h3>
+                    Â«augment.description»
+                        Status: Â«strong(String.valueOf(augment.status))»
+                    Â«IF augment.reference !== null»
+                        Reference Â«augment.reference»
+                    Â«ENDIF»
+                    Â«IF augment.whenCondition !== null»
+                        When Â«augment.whenCondition.toString»
+                    Â«ENDIF»
+                    Â«FOR childNode : augment.childNodes»
+                        Â«childNode.printSchemaNodeInfo»
+                    Â«ENDFOR»
+                    
+                    <h3>Example</h3>
+                    Â«createAugmentChildNodesAsString(new ArrayList(augment.childNodes))»
+                    Â«printNodeChildren(parseTargetPath(augment.targetPath))»
+                </li>
+            Â«ENDFOR»
+            </ul>
+        '''
+    }
+    
+    private def createAugmentChildNodesAsString(List<DataSchemaNode> childNodes) {
+        augmentChildNodesAsString = new StringBuilder();
+        augmentChildNodesAsString.append(printNodeChildren(childNodes))
+        return ''
+    }
+    
+    private def parseTargetPath(SchemaPath path) {
+        val List<DataSchemaNode> nodes = new ArrayList<DataSchemaNode>();
+        for (QName pathElement : path.pathFromRoot) {
+            val module = ctx.findModuleByNamespaceAndRevision(pathElement.namespace, pathElement.revision);
+            if (module !== null) {
+                var foundNode = module.getDataChildByName(pathElement)
+                if(foundNode == null) {
+                    val child = nodes.last
+                    if (child instanceof DataNodeContainer) {
+                        val dataContNode = child as DataNodeContainer
+                        foundNode = findNodeInChildNodes(pathElement, dataContNode.childNodes)
+                    }
+                }
+                if(foundNode != null) {
+                    nodes.add(foundNode);
+                }
+            }
+        }
+        if(! nodes.empty) {
+            lastNodeInTargetPath = nodes.get(nodes.size() - 1)
+        }
+        
+        val List<DataSchemaNode> targetPathNodes = new ArrayList<DataSchemaNode>();
+        targetPathNodes.add(lastNodeInTargetPath)
+        
+        return targetPathNodes
+    }
+    
+    private def DataSchemaNode findNodeInChildNodes(QName findingNode, Iterable<DataSchemaNode> childNodes) {
+        for(child : childNodes) {
+            if (child.QName.equals(findingNode))
+                return child;
+        }
+        // find recursively
+        for(child : childNodes) {
+            if(child instanceof ContainerSchemaNode) {
+                val foundChild = findNodeInChildNodes(findingNode, child.childNodes)
+                if (foundChild != null)
+                    return foundChild;
+            }
+            else if(child instanceof ListSchemaNode) {
+                val foundChild = findNodeInChildNodes(findingNode, child.childNodes)
+                if (foundChild != null)
+                    return foundChild;
+            }
+        }
+    }
+    
+    private def printNodeChildren(List<DataSchemaNode> childNodes) {
+        if (childNodes.empty) {
+            return ''
+        }
+        
+        return 
+        '''
+        <pre>
+        Â«printAugmentedNode(childNodes.get(0))»
+        </pre>
+        '''
+    }
+    
+    private def CharSequence printAugmentedNode(DataSchemaNode child) {
+        
+        if(child instanceof ChoiceCaseNode)
+            return ''
+            
+        return
+        '''
+        Â«IF child instanceof ContainerSchemaNode»
+            Â«printContainerNode(child)»
+        Â«ENDIF»
+        Â«IF child instanceof AnyXmlSchemaNode»
+            Â«printAnyXmlNode(child)»
+        Â«ENDIF»
+        Â«IF child instanceof LeafSchemaNode»
+            Â«printLeafNode(child)»
+        Â«ENDIF»
+        Â«IF child instanceof LeafListSchemaNode»
+            Â«printLeafListNode(child)»
+        Â«ENDIF»
+        Â«IF child instanceof ListSchemaNode»
+            Â«printListNode(child)»
+        Â«ENDIF»
+        Â«IF child instanceof ChoiceSchemaNode»
+            Â«printChoiceNode(child)»
+        Â«ENDIF»
+        '''
+    }
+    
+    private def printChoiceNode(ChoiceSchemaNode child) {
+        val List<ChoiceCaseNode> cases = new ArrayList(child.cases);
+        if(!cases.empty) {
+            val ChoiceCaseNode aCase = cases.get(0)
+            for(caseChildNode : aCase.childNodes)
+                printAugmentedNode(caseChildNode)
+        }
+    }
+    
+    private def printListNode(ListSchemaNode listNode) {
+        return
+        '''
+            &lt;«listNode.QName.localName»«IF !listNode.QName.namespace.equals(currentModule.namespace)» xmlns="«listNode.QName.namespace»"«ENDIF»&gt;
+                Â«FOR child : listNode.childNodes»
+                    Â«printAugmentedNode(child)»
+                Â«ENDFOR»
+            &lt;/«listNode.QName.localName»&gt;
+        '''
+    }
+    
+    private def printContainerNode(ContainerSchemaNode containerNode) {
+        return
+        '''
+            &lt;«containerNode.QName.localName»«IF !containerNode.QName.namespace.equals(currentModule.namespace)» xmlns="«containerNode.QName.namespace»"«ENDIF»&gt;
+                Â«FOR child : containerNode.childNodes»
+                    Â«printAugmentedNode(child)»
+                Â«ENDFOR»
+            &lt;/«containerNode.QName.localName»&gt;
+        '''
+    }
+    
+    private def printLeafListNode(LeafListSchemaNode leafListNode) {
+        return
+        '''
+            &lt;«leafListNode.QName.localName»&gt;. . .&lt;/«leafListNode.QName.localName»&gt;
+            &lt;«leafListNode.QName.localName»&gt;. . .&lt;/«leafListNode.QName.localName»&gt;
+            &lt;«leafListNode.QName.localName»&gt;. . .&lt;/«leafListNode.QName.localName»&gt;
+        '''
+    }
+    
+    private def printAnyXmlNode(AnyXmlSchemaNode anyXmlNode) {
+        return 
+        '''
+            &lt;«anyXmlNode.QName.localName»&gt;. . .&lt;/«anyXmlNode.QName.localName»&gt;
+        '''
+    }
+    
+    private def printLeafNode(LeafSchemaNode leafNode) {
+        return 
+        '''
+            &lt;«leafNode.QName.localName»&gt;. . .&lt;/«leafNode.QName.localName»&gt;
+        '''
+    }
+
+    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) {
+            return '';
+        }
+
+        return '''
+            <h2>Notifications</h2>
+            Â«FOR notificationdef : notificationdefs»
+
+                <h3 id="«notificationdef.path.schemaPathToId»">«notificationdef.nodeName»</h3>
+                    Â«notificationdef.descAndRef»
+                    Â«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>
+        '''
+    }
+
+    def rpcs(Module module) {
+        if (module.rpcs.empty) {
+            return '';
+        }
+
+        return '''
+            <h2>RPC Definitions</h2>
+            Â«FOR rpc : module.rpcs»
+                <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 '';
+        }
+        return '''
+            <h2>Extensions</h2>
+            Â«FOR ext : module.extensionSchemaNodes»
+                <li>
+                    <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 '';
+        }
+        return '''
+            <h2>Features</h2>
+
+            <ul>
+            Â«FOR feature : module.features»
+                <li>
+                    <h3 id="«feature.QName.localName»">«feature.QName.localName»</h3>
+                    <ul>
+                        Â«feature.descAndRefLi»
+                    </ul>
+                </li>
+            Â«ENDFOR»
+            </ul>
+        '''
+    }
+
+    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>
+        <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) {
+        throw new UnsupportedOperationException("TODO: auto-generated method stub")
+    }
+
+    def CharSequence tree(Module module) '''
+        Â«strong(module.name)»
+        Â«module.childNodes.treeSet(YangInstanceIdentifier.builder.build())»
+    '''
+
+    private def dispatch CharSequence tree(ChoiceSchemaNode node,YangInstanceIdentifier path) '''
+        Â«node.nodeName» (choice)
+        Â«casesTree(node.cases,path)»
+    '''
+
+    def casesTree(Set<ChoiceCaseNode> nodes,YangInstanceIdentifier path) '''
+        <ul>
+        Â«FOR node : nodes»
+            <li>
+            Â«node.nodeName»
+            Â«node.childNodes.treeSet(path)»
+            </li>
+        Â«ENDFOR»
+        </ul>
+    '''
+
+    private def dispatch CharSequence tree(DataSchemaNode node,YangInstanceIdentifier path) '''
+        Â«node.nodeName»
+    '''
+
+    private def dispatch CharSequence tree(ListSchemaNode node,YangInstanceIdentifier path) '''
+        Â«val newPath = path.append(node)»
+        Â«localLink(newPath,node.nodeName)»
+        Â«node.childNodes.treeSet(newPath)»
+    '''
+
+    private def dispatch CharSequence tree(ContainerSchemaNode node,YangInstanceIdentifier path) '''
+        Â«val newPath = path.append(node)»
+        Â«localLink(newPath,node.nodeName)»
+        Â«node.childNodes.treeSet(newPath)»
+    '''
+
+    def CharSequence childNodes(Module module) '''
+        Â«val childNodes = module.childNodes»
+        Â«IF !childNodes.nullOrEmpty»
+            <h2>Child nodes</h2>
+
+            Â«childNodes.printChildren(3,YangInstanceIdentifier.builder().build())»
+        Â«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>
+                Â«val Set<TypeDefinition<?>> typeDefinitions = dataNode.typeDefinitions»
+                Â«FOR typeDef : 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 lastElement = Iterables.getLast(path.pathFromRoot)
+            val ns = lastElement.namespace
+            if (ns == this.currentModule.namespace) {
+                return '''<a href="#«path.schemaPathToId»">«text»</a>'''
+            } else {
+                return '''(«ns»)«text»'''
+                //to enable external (import) links
+                //return '''<a href="«module».html#«path.schemaPathToId»">«prefix»:«text»</a>'''
+            }
+        }
+    }
+
+    def CharSequence printBaseInfo(SchemaNode node) {
+        if(node instanceof LeafSchemaNode) {
+            return '''
+                Â«printInfo(node, "leaf")»
+                Â«listItem("type", typeAnchorLink(node.type?.path, node.type.QName.localName))»
+                Â«listItem("units", node.units)»
+                Â«listItem("default", node.^default)»
+                </ul>
+            '''
+        } else if(node instanceof LeafListSchemaNode) {
+            return '''
+                Â«printInfo(node, "leaf-list")»
+                Â«listItem("type", node.type?.QName.localName)»
+                </ul>
+            '''
+        } else if(node instanceof ListSchemaNode) {
+            return '''
+                Â«printInfo(node, "list")»
+                Â«FOR keyDef : node.keyDefinition»
+                    Â«listItem("key definition", keyDef.localName)»
+                Â«ENDFOR»
+                </ul>
+            '''
+        } else if(node instanceof ChoiceSchemaNode) {
+            return '''
+                Â«printInfo(node, "choice")»
+                Â«listItem("default case", node.defaultCase)»
+                Â«FOR caseNode : node.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.constraints.whenCondition?.toString)»
+                Â«listItem("min elements", node.constraints.minElements?.toString)»
+                Â«listItem("max elements", node.constraints.maxElements?.toString)»
+            Â«ENDIF»
+        '''
+    }
+
+    def CharSequence printUses(UsesNode usesNode) {
+        return '''
+            Â«strong(listItem("uses", typeAnchorLink(usesNode.groupingPath, usesNode.groupingPath.pathTowardsRoot.iterator.next.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(Iterable<DataSchemaNode> nodes, int level, YangInstanceIdentifier path) {
+        val anyxmlNodes = nodes.filter(AnyXmlSchemaNode)
+        val leafNodes = nodes.filter(LeafSchemaNode)
+        val leafListNodes = nodes.filter(LeafListSchemaNode)
+        val choices = nodes.filter(ChoiceSchemaNode)
+        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.pathArguments.iterator.hasNext»
+            <h3>XML example</h3>
+            Â«nodes.xmlExample(path.pathArguments.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(Iterable<DataSchemaNode> nodes, QName name,YangInstanceIdentifier path) '''
+    <pre>
+        Â«xmlExampleTag(name,nodes.xmplExampleTags(path))»
+    </pre>
+    '''
+
+    def CharSequence xmplExampleTags(Iterable<DataSchemaNode> nodes, YangInstanceIdentifier identifier) '''
+        <!-- Child nodes -->
+        Â«FOR node : nodes»
+        <!-- Â«node.QName.localName» -->
+            Â«node.asXmlExampleTag(identifier)»
+        Â«ENDFOR»
+
+    '''
+
+    private def dispatch CharSequence asXmlExampleTag(LeafSchemaNode node, YangInstanceIdentifier identifier) '''
+        Â«node.QName.xmlExampleTag("...")»
+    '''
+
+    private def dispatch CharSequence asXmlExampleTag(LeafListSchemaNode node, YangInstanceIdentifier identifier) '''
+        &lt!-- This node could appear multiple times --&gt
+        Â«node.QName.xmlExampleTag("...")»
+    '''
+
+    private def dispatch CharSequence asXmlExampleTag(ContainerSchemaNode node, YangInstanceIdentifier identifier) '''
+        &lt!-- See Â«localLink(identifier.append(node),"definition")» for child nodes.  --&gt
+        Â«node.QName.xmlExampleTag("...")»
+    '''
+
+
+    private def dispatch CharSequence asXmlExampleTag(ListSchemaNode node, YangInstanceIdentifier identifier) '''
+        &lt!-- See Â«localLink(identifier.append(node),"definition")» for child nodes.  --&gt
+        &lt!-- This node could appear multiple times --&gt
+        Â«node.QName.xmlExampleTag("...")»
+    '''
+
+
+    private def dispatch CharSequence asXmlExampleTag(DataSchemaNode node, YangInstanceIdentifier identifier) '''
+        <!-- noop -->
+    '''
+
+
+    def xmlExampleTag(QName name, CharSequence data) {
+        return '''&lt;«name.localName» xmlns="«name.namespace»"&gt;«data»&lt;/«name.localName»&gt;'''
+    }
+
+    def header(int level,QName name) '''<h«level»>«name.localName»</h«level»>'''
+
+
+    def header(int level,YangInstanceIdentifier name) '''
+        <h«level» id="«FOR cmp : name.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">
+            Â«FOR cmp : name.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»
+        </h«level»>
+    '''
+
+
+
+    private def dispatch CharSequence printInfo(DataSchemaNode node, int level, YangInstanceIdentifier path) '''
+        Â«header(level+1,node.QName)»
+    '''
+
+    private def dispatch CharSequence printInfo(ContainerSchemaNode node, int level, YangInstanceIdentifier path) '''
+        Â«val newPath = path.append(node)»
+        Â«header(level,newPath)»
+        <dl>
+          <dt>XML Path</dt>
+          <dd>«newPath.asXmlPath»</dd>
+          <dt>Restconf path</dt>
+          <dd>«code(newPath.asRestconfPath)»</dd>
+        </dl>
+        Â«node.childNodes.printChildren(level,newPath)»
+    '''
+
+    private def dispatch CharSequence printInfo(ListSchemaNode node, int level, YangInstanceIdentifier path) '''
+        Â«val newPath = path.append(node)»
+        Â«header(level,newPath)»
+        <dl>
+          <dt>XML Path</dt>
+          <dd>«newPath.asXmlPath»</dd>
+          <dt>Restconf path</dt>
+          <dd>«code(newPath.asRestconfPath)»</dd>
+        </dl>
+        Â«node.childNodes.printChildren(level,newPath)»
+    '''
+
+    private def dispatch CharSequence printInfo(ChoiceSchemaNode node, int level, YangInstanceIdentifier path) '''
+        Â«val Set<DataSchemaNode> choiceCases = new HashSet(node.cases)»
+        Â«choiceCases.printChildren(level,path)»
+    '''
+
+    private def dispatch CharSequence printInfo(ChoiceCaseNode node, int level, YangInstanceIdentifier path) '''
+        Â«node.childNodes.printChildren(level,path)»
+    '''
+
+
+
+    def CharSequence printShortInfo(ContainerSchemaNode node, int level, YangInstanceIdentifier path) {
+        val newPath = path.append(node);
+        return '''
+            <li>«strong(localLink(newPath,node.QName.localName))» (container)
+            <ul>
+                <li>configuration data: Â«strong(String.valueOf(node.configuration))»</li>
+            </ul>
+            </li>
+        '''
+    }
+
+    def CharSequence printShortInfo(ListSchemaNode node, int level, YangInstanceIdentifier path) {
+        val newPath = path.append(node);
+        return '''
+            <li>«strong(localLink(newPath,node.QName.localName))» (list)
+            <ul>
+                <li>configuration data: Â«strong(String.valueOf(node.configuration))»</li>
+            </ul>
+            </li>
+        '''
+    }
+
+    def CharSequence printShortInfo(AnyXmlSchemaNode node, int level, YangInstanceIdentifier path) {
+        return '''
+            <li>«strong((node.QName.localName))» (anyxml)
+            <ul>
+                <li>configuration data: Â«strong(String.valueOf(node.configuration))»</li>
+                <li>mandatory: Â«strong(String.valueOf(node.constraints.mandatory))»</li>
+            </ul>
+            </li>
+        '''
+    }
+
+    def CharSequence printShortInfo(LeafSchemaNode node, int level, YangInstanceIdentifier path) {
+        return '''
+            <li>«strong((node.QName.localName))» (leaf)
+            <ul>
+                <li>configuration data: Â«strong(String.valueOf(node.configuration))»</li>
+                <li>mandatory: Â«strong(String.valueOf(node.constraints.mandatory))»</li>
+            </ul>
+            </li>
+        '''
+    }
+
+    def CharSequence printShortInfo(LeafListSchemaNode node, int level, YangInstanceIdentifier path) {
+        return '''
+            <li>«strong((node.QName.localName))» (leaf-list)
+            <ul>
+                <li>configuration data: Â«strong(String.valueOf(node.configuration))»</li>
+            </ul>
+            </li>
+        '''
+    }
+
+    def CharSequence anchorLink(CharSequence anchor, CharSequence text) {
+        return '''
+            <a href="#«anchor»">«text»</a>
+        '''
+    }
+
+    def CharSequence localLink(YangInstanceIdentifier identifier, CharSequence text) '''
+        <a href="#«FOR cmp : identifier.pathArguments SEPARATOR "/"»«cmp.nodeType.localName»«ENDFOR»">«text»</a>
+    '''
+
+
+    private def dispatch YangInstanceIdentifier append(YangInstanceIdentifier identifier, ContainerSchemaNode node) {
+        return identifier.node(node.QName);
+    }
+
+    private def dispatch YangInstanceIdentifier append(YangInstanceIdentifier identifier, ListSchemaNode node) {
+        val keyValues = new LinkedHashMap<QName,Object>();
+        if(node.keyDefinition !== null) {
+            for(definition : node.keyDefinition) {
+                keyValues.put(definition,new Object);
+            }
+        }
+
+        return identifier.node(new NodeIdentifierWithPredicates(node.QName, keyValues));
+    }
+
+
+    def asXmlPath(YangInstanceIdentifier identifier) {
+        return "";
+    }
+
+    def asRestconfPath(YangInstanceIdentifier identifier) {
+        val it = new StringBuilder();
+        append(currentModule.name)
+        append(':')
+        var previous = false;
+        for(arg : identifier.pathArguments) {
+            if(previous) append('/')
+            append(arg.nodeType.localName);
+            previous = true;
+            if(arg instanceof NodeIdentifierWithPredicates) {
+                for(qname : arg.getKeyValues.keySet) {
+                    append("/{");
+                    append(qname.localName)
+                    append('}')
+                }
+            }
+        }
+
+        return it.toString;
+    }
+
+    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('/')
+        }
+
+        val QName qname = path.get(0)
+        var Object parent = ctx.findModuleByNamespaceAndRevision(qname.namespace, qname.revision)
+
+        for (name : path) {
+            if (parent instanceof DataNodeContainer) {
+                var SchemaNode node = parent.getDataChildByName(name)
+                if (node == null && (parent instanceof Module)) {
+                    val notifications = (parent as Module).notifications;
+                    for (notification : notifications) {
+                        if (notification.QName.equals(name)) {
+                            node = notification
+                        }
+                    }
+                }
+                if (node == null && (parent instanceof Module)) {
+                    val rpcs = (parent as Module).rpcs;
+                    for (rpc : rpcs) {
+                        if (rpc.QName.equals(name)) {
+                            node = rpc
+                        }
+                    }
+                }
+
+                val pathElementModule = ctx.findModuleByNamespaceAndRevision(name.namespace, name.revision)
+                val String moduleName = pathElementModule.name
+                pathString.append(moduleName)
+                pathString.append(':')
+                pathString.append(name.localName)
+                pathString.append('/')
+                if(node instanceof ChoiceSchemaNode && dataNode !== null) {
+                    val DataSchemaNode caseNode = dataNode.childNodes.findFirst[DataSchemaNode e | e instanceof ChoiceCaseNode];
+                    if(caseNode !== null) {
+                        pathString.append("(case)");
+                        pathString.append(caseNode.QName.localName);
+                    }
+                }
+                parent = node
+            }
+        }
+        return pathString.toString;
+    }
+
+
+    def CharSequence childNodesInfoTree(Map<SchemaPath, DataSchemaNode> childNodes) '''
+        Â«IF childNodes !== null && !childNodes.empty»
+            Â«FOR child : childNodes.values»
+                Â«childInfo(child, childNodes)»
+            Â«ENDFOR»
+        Â«ENDIF»
+    '''
+
+    def CharSequence childInfo(DataSchemaNode node, Map<SchemaPath, DataSchemaNode> childNodes) '''
+        Â«val String path = nodeSchemaPathToPath(node, childNodes)»
+        Â«IF path != null»
+            Â«code(path)»
+                Â«IF node !== null»
+                <ul>
+                Â«node.descAndRefLi»
+                </ul>
+            Â«ENDIF»
+        Â«ENDIF»
+    '''
+
+    private def CharSequence treeSet(Collection<DataSchemaNode> childNodes, YangInstanceIdentifier path) '''
+        Â«IF childNodes !== null && !childNodes.empty»
+            <ul>
+            Â«FOR child : childNodes»
+                <li>
+                    Â«child.tree(path)»
+                </li>
+            Â«ENDFOR»
+            </ul>
+        Â«ENDIF»
+    '''
+
+    def listKeys(ListSchemaNode node) '''
+        [«FOR key : node.keyDefinition SEPARATOR " "»«key.localName»«ENDFOR»]
+    '''
+
+    private def CharSequence extensionInfo(ExtensionDefinition ext) '''
+        <ul>
+            Â«ext.descAndRefLi»
+            Â«listItem("Argument", ext.argument)»
+        </ul>
+    '''
+
+    private def dispatch CharSequence tree(Void obj, YangInstanceIdentifier path) '''
+    '''
+
+
+
+    /* #################### RESTRICTIONS #################### */
+    private def restrictions(TypeDefinition<?> type) '''
+        Â«type.baseType.toBaseStmt»
+        Â«type.toLength»
+        Â«type.toRange»
+    '''
+
+    private def dispatch toLength(TypeDefinition<?> type) {
+    }
+
+    private def dispatch toLength(BinaryTypeDefinition type) '''
+        Â«type.lengthConstraints.toLengthStmt»
+    '''
+
+    private def dispatch toLength(StringTypeDefinition type) '''
+        Â«type.lengthConstraints.toLengthStmt»
+    '''
+
+    private def dispatch toLength(ExtendedType type) '''
+        Â«type.lengthConstraints.toLengthStmt»
+    '''
+
+    private def dispatch toRange(TypeDefinition<?> type) {
+    }
+
+    private def dispatch toRange(DecimalTypeDefinition type) '''
+        Â«type.rangeConstraints.toRangeStmt»
+    '''
+
+    private def dispatch toRange(IntegerTypeDefinition type) '''
+        Â«type.rangeConstraints.toRangeStmt»
+    '''
+
+    private def dispatch toRange(UnsignedIntegerTypeDefinition type) '''
+        Â«type.rangeConstraints.toRangeStmt»
+    '''
+
+    private def dispatch toRange(ExtendedType type) '''
+        Â«type.rangeConstraints.toRangeStmt»
+    '''
+
+    def toLengthStmt(Collection<LengthConstraint> lengths) '''
+        Â«IF lengths != null && !lengths.empty»
+            Â«listItem("Length restrictions:")»
+            <ul>
+            Â«FOR length : lengths»
+                <li>
+                Â«IF length.min == length.max»
+                    Â«length.min»
+                Â«ELSE»
+                    &lt;«length.min», Â«length.max»&gt;
+                Â«ENDIF»
+                </li>
+            Â«ENDFOR»
+            </ul>
+        Â«ENDIF»
+    '''
+
+    def toRangeStmt(Collection<RangeConstraint> ranges) '''
+        Â«IF ranges != null && !ranges.empty»
+            Â«listItem("Range restrictions:")»
+            <ul>
+            Â«FOR range : ranges»
+                <li>
+                Â«IF range.min == range.max»
+                    Â«range.min»
+                Â«ELSE»
+                    &lt;«range.min», Â«range.max»&gt;
+                Â«ENDIF»
+                </li>
+            Â«ENDFOR»
+            </ul>
+        Â«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>'''
+
+    def CharSequence descAndRefLi(SchemaNode node) '''
+        Â«listItem("Description", node.description)»
+        Â«listItem("Reference", node.reference)»
+    '''
+
+    def CharSequence descAndRef(SchemaNode node) '''
+        Â«node.description»
+        Â«IF node.reference !== null»
+            Reference Â«node.reference»
+        Â«ENDIF»
+    '''
+
+    private def listItem(String value) '''
+        Â«IF value !== null && !value.empty»
+            <li>
+                Â«value»
+            </li>
+        Â«ENDIF»
+    '''
+
+    private def listItem(String name, String value) '''
+        Â«IF value !== null && !value.empty»
+            <li>
+                Â«name»: Â«value»
+            </li>
+        Â«ENDIF»
+    '''
+
+    private def String nodeSchemaPathToPath(DataSchemaNode node, Map<SchemaPath, DataSchemaNode> childNodes) {
+        if (node instanceof ChoiceSchemaNode || node instanceof ChoiceCaseNode) {
+            return null
+        }
+
+        val path = node.path.path
+        val absolute = node.path.absolute;
+        var StringBuilder result = new StringBuilder
+        if (absolute) {
+            result.append("/")
+        }
+        if (path !== null && !path.empty) {
+            val List<QName> actual = new ArrayList()
+            var i = 0;
+            for (pathElement : path) {
+                actual.add(pathElement)
+                val DataSchemaNode nodeByPath = childNodes.get(SchemaPath.create(actual, absolute))
+                if (!(nodeByPath instanceof ChoiceSchemaNode) && !(nodeByPath instanceof ChoiceCaseNode)) {
+                    result.append(pathElement.localName)
+                    if (i != path.size - 1) {
+                        result.append("/")
+                    }
+                }
+                i = i + 1
+            }
+        }
+        return result.toString
+    }
+
+    private def void collectChildNodes(Collection<DataSchemaNode> source, Map<SchemaPath, DataSchemaNode> destination) {
+        for (node : source) {
+            destination.put(node.path, node)
+            if (node instanceof DataNodeContainer) {
+                collectChildNodes((node as DataNodeContainer).childNodes, destination)
+            }
+            if (node instanceof ChoiceSchemaNode) {
+                val List<DataSchemaNode> choiceCases = new ArrayList()
+                for (caseNode : node.cases) {
+                    choiceCases.add(caseNode)
+                }
+                collectChildNodes(choiceCases, destination)
+            }
+        }
+    }
+
+    private def dispatch addedByInfo(SchemaNode node) '''
+    '''
+
+    private def dispatch addedByInfo(DataSchemaNode node) '''
+        Â«IF node.augmenting»(A)«ENDIF»«IF node.addedByUses»(U)«ENDIF»
+    '''
+
+    private def dispatch isAddedBy(SchemaNode node) {
+        return false;
+    }
+
+    private def dispatch isAddedBy(DataSchemaNode node) {
+        if (node.augmenting || node.addedByUses) {
+            return true
+        } else {
+            return false;
+        }
+    }
+
+    private def dispatch nodeName(SchemaNode node) '''
+        Â«IF node.isAddedBy»
+            Â«italic(node.QName.localName)»«node.addedByInfo»
+        Â«ELSE»
+            Â«node.QName.localName»«node.addedByInfo»
+        Â«ENDIF»
+    '''
+
+    private def dispatch nodeName(ContainerSchemaNode node) '''
+        Â«IF node.isAddedBy»
+            Â«strong(italic(node.QName.localName))»«node.addedByInfo»
+        Â«ELSE»
+            Â«strong(node.QName.localName)»«node.addedByInfo»
+        Â«ENDIF»
+    '''
+
+    private def dispatch nodeName(ListSchemaNode node) '''
+        Â«IF node.isAddedBy»
+            Â«strong(italic(node.QName.localName))» Â«IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»«node.addedByInfo»
+        Â«ELSE»
+            Â«strong(node.QName.localName)» Â«IF node.keyDefinition !== null && !node.keyDefinition.empty»«node.listKeys»«ENDIF»
+        Â«ENDIF»
+    '''
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/DocumentationGeneratorImpl.java b/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/DocumentationGeneratorImpl.java
new file mode 100644 (file)
index 0000000..fafb859
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.unified.doc.generator.maven;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.unified.doc.generator.GeneratorImpl;
+import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator;
+
+public class DocumentationGeneratorImpl extends GeneratorImpl implements BasicCodeGenerator {
+
+    @Override
+    public Collection<File> generateSources(SchemaContext arg0, File arg1, Set<Module> arg2) throws IOException {
+        // TODO Auto-generated method stub
+         return generate(arg0, arg1, arg2);
+    }
+
+    @Override
+    public void setAdditionalConfig(Map<String, String> additionalConfiguration) {
+        // no additional config utilized
+    }
+
+    @Override
+    public void setResourceBaseDir(File resourceBaseDir) {
+        // no resource processing necessary
+    }
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/wadl/generator/WadlRestconfGenerator.xtend b/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/wadl/generator/WadlRestconfGenerator.xtend
new file mode 100644 (file)
index 0000000..2a02f37
--- /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.wadl.generator
+
+import java.io.BufferedWriter
+import java.io.File
+import java.io.OutputStreamWriter
+import java.net.URI
+import java.util.ArrayList
+import java.util.HashSet
+import java.util.List
+import java.util.Set
+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.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.sonatype.plexus.build.incremental.BuildContext
+import org.sonatype.plexus.build.incremental.DefaultBuildContext
+
+class WadlRestconfGenerator {
+       
+       File path
+       static val BuildContext CTX = new DefaultBuildContext();
+       static val PATH_DELIMETER = '/'
+       var SchemaContext context;
+       var List<DataSchemaNode> configData;
+       var List<DataSchemaNode> operationalData;
+       var Module module;
+       var List<LeafSchemaNode> pathListParams;
+
+       new(File targetPath) {
+               if (!targetPath.exists) targetPath.mkdirs
+               path = targetPath
+       }
+
+       def generate(SchemaContext context, Set<Module> modules) {
+        val result = new HashSet;
+               this.context = context
+               for (module : modules) {
+                       val dataContainers = module.childNodes.filter[it|it.listOrContainer]
+                       if (!dataContainers.empty || !module.rpcs.nullOrEmpty) {
+                               configData = new ArrayList
+                               operationalData = new ArrayList
+                               
+                               for (data : dataContainers) {
+                                       if (data.configuration) {
+                                               configData.add(data)    
+                                       } else {
+                                               operationalData.add(data)
+                                       }
+                               }
+                               
+                               this.module = module
+                               val destination = new File(path, '''«module.name».wadl''')
+                   val fw = new OutputStreamWriter(CTX.newFileOutputStream(destination))
+                   val bw = new BufferedWriter(fw)
+                   bw.append(application);
+                   bw.close();
+                   fw.close();
+                       result.add(destination)
+                       }
+               }
+               return result
+       }
+       
+       private def application() '''
+               <?xml version="1.0"?>
+               <application xmlns="http://wadl.dev.java.net/2009/02" Â«module.importsAsNamespaces» xmlns:«module.prefix»="«module.namespace»">
+               
+                       Â«grammars»
+                       
+                       Â«resources»
+               </application>
+       '''
+       
+       private def importsAsNamespaces(Module module) '''
+               Â«FOR imprt : module.imports»
+                       xmlns:«imprt.prefix»="«context.findModuleByName(imprt.moduleName, imprt.revision).namespace»"
+               Â«ENDFOR»
+       '''
+       
+       private def grammars() '''
+               <grammars>
+                       <include href="«module.name».yang"/>
+                       Â«FOR imprt : module.imports»
+                               <include href="«imprt.moduleName».yang"/>
+                       Â«ENDFOR»
+               </grammars>
+       '''
+       
+       private def resources() '''
+               <resources base="http://localhost:9998/restconf">
+                       Â«resourceOperational»
+                       Â«resourceConfig»
+                       Â«resourceOperations»
+               </resources>
+       '''
+       
+       private def resourceOperational() '''
+               Â«IF !operationalData.nullOrEmpty»
+                       <resource path="operational">
+                               Â«FOR schemaNode : operationalData»
+                                       Â«schemaNode.firstResource(false)»
+                               Â«ENDFOR»
+                       </resource>
+               Â«ENDIF»
+       '''
+       
+       private def resourceConfig() '''
+               Â«IF !configData.nullOrEmpty»
+                       <resource path="config">
+                               Â«FOR schemaNode : configData»
+                                       Â«schemaNode.mehodPost»
+                               Â«ENDFOR»
+                               Â«FOR schemaNode : configData»
+                                       Â«schemaNode.firstResource(true)»
+                               Â«ENDFOR»
+                       </resource>
+               Â«ENDIF»
+       '''
+       
+       private def resourceOperations() '''
+               Â«IF !module.rpcs.nullOrEmpty»
+                       <resource path="operations">
+                               Â«FOR rpc : module.rpcs»
+                                       <resource path="«module.name»:«rpc.QName.localName»">
+                                               Â«methodPostRpc(rpc.input != null, rpc.output !== null)»
+                                       </resource>
+                               Â«ENDFOR»
+                       </resource>
+               Â«ENDIF»
+       '''
+       
+       private def String firstResource(DataSchemaNode schemaNode, boolean config) '''
+               <resource path="«module.name»:«schemaNode.createPath»">
+                       Â«resourceBody(schemaNode, config)»
+               </resource>
+       '''
+               
+       private def String resource(DataSchemaNode schemaNode, boolean config) '''
+               <resource path="«schemaNode.createPath»">
+                       Â«resourceBody(schemaNode, config)»
+               </resource>
+       '''
+       
+       private def String createPath(DataSchemaNode schemaNode) {
+               pathListParams = new ArrayList
+               var StringBuilder path = new StringBuilder
+               path.append(schemaNode.QName.localName)
+               if (schemaNode instanceof ListSchemaNode) {
+                       for (listKey : schemaNode.keyDefinition) {
+                               pathListParams.add((schemaNode as DataNodeContainer).getDataChildByName(listKey) as LeafSchemaNode)
+                               path.append(PATH_DELIMETER)
+                               path.append('{')
+                               path.append(listKey.localName)
+                               path.append('}')
+                       }
+               }
+               return path.toString
+       }
+       
+       private def String resourceBody(DataSchemaNode schemaNode, boolean config) '''
+               Â«IF !pathListParams.nullOrEmpty»
+                       Â«resourceParams»
+               Â«ENDIF»
+               Â«schemaNode.methodGet»
+               Â«val children = (schemaNode as DataNodeContainer).childNodes.filter[it|it.listOrContainer]»
+               Â«IF config»
+                       Â«schemaNode.methodDelete»
+                       Â«schemaNode.mehodPut»
+                       Â«FOR child : children»
+                               Â«child.mehodPost»
+                       Â«ENDFOR»
+               Â«ENDIF»
+               Â«FOR child : children»
+                       Â«child.resource(config)»
+               Â«ENDFOR»
+       '''
+       
+       private def resourceParams() '''
+               Â«FOR pathParam : pathListParams»
+                   Â«IF pathParam != null»
+                       Â«val type = pathParam.type.QName.localName»
+                       <param required="true" style="template" name="«pathParam.QName.localName»" type="«type»"/>
+                       Â«ENDIF»
+               Â«ENDFOR»
+       '''
+       
+       private def methodGet(DataSchemaNode schemaNode) '''
+               <method name="GET">
+                       <response>
+                               Â«representation(schemaNode.QName.namespace, schemaNode.QName.localName)»
+                       </response>
+               </method>
+       '''
+       
+       private def mehodPut(DataSchemaNode schemaNode) '''
+               <method name="PUT">
+                       <request>
+                               Â«representation(schemaNode.QName.namespace, schemaNode.QName.localName)»
+                       </request>
+               </method>
+       '''
+       
+       private def mehodPost(DataSchemaNode schemaNode) '''
+               <method name="POST">
+                       <request>
+                               Â«representation(schemaNode.QName.namespace, schemaNode.QName.localName)»
+                       </request>
+               </method>
+       '''
+       
+       private def methodPostRpc(boolean input, boolean output) '''
+               <method name="POST">
+                       Â«IF input»
+                       <request>
+                               Â«representation(null, "input")»
+                       </request>
+                       Â«ENDIF»
+                       Â«IF output»
+                       <response>
+                               Â«representation(null, "output")»
+                       </response>
+                       Â«ENDIF»
+               </method>
+       '''
+
+       private def methodDelete(DataSchemaNode schemaNode) '''
+               <method name="DELETE" />
+       '''
+
+       private def representation(URI prefix, String name) '''
+               Â«val elementData = name»
+               <representation mediaType="application/xml" element="«elementData»"/>
+               <representation mediaType="text/xml" element="«elementData»"/>
+               <representation mediaType="application/json" element="«elementData»"/>
+               <representation mediaType="application/yang.data+xml" element="«elementData»"/>
+               <representation mediaType="application/yang.data+json" element="«elementData»"/>
+       '''
+       
+       private def boolean isListOrContainer(DataSchemaNode schemaNode) {
+               return (schemaNode instanceof ListSchemaNode || schemaNode instanceof ContainerSchemaNode)
+       }
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/wadl/generator/maven/WadlGenerator.java b/code-generator/maven-sal-api-gen-plugin/src/main/java/org/opendaylight/yangtools/yang/wadl/generator/maven/WadlGenerator.java
new file mode 100644 (file)
index 0000000..6a05f75
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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.wadl.generator.maven;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.wadl.generator.WadlRestconfGenerator;
+import org.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator;
+
+public class WadlGenerator implements BasicCodeGenerator {
+    
+    @Override
+    public Collection<File> generateSources(SchemaContext context, File outputDir, Set<Module> currentModules)
+            throws IOException {
+        
+        final File outputBaseDir;
+        if (outputDir == null) {
+            // FIXME: this hard-codes the destination
+            outputBaseDir = new File("target" + File.separator + "generated-sources" + File.separator
+                    + "maven-sal-api-gen" + File.separator + "wadl");
+        } else {
+            outputBaseDir = outputDir;
+        }
+
+        final WadlRestconfGenerator generator = new WadlRestconfGenerator(outputBaseDir);
+        return generator.generate(context, currentModules);
+    }
+
+    @Override
+    public void setAdditionalConfig(Map<String, String> additionalConfiguration) {
+        // TODO Auto-generated method stub
+        
+    }
+
+    @Override
+    public void setResourceBaseDir(File resourceBaseDir) {
+        // TODO Auto-generated method stub
+        
+    }
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/DocGenTest.java b/code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/DocGenTest.java
new file mode 100644 (file)
index 0000000..4e0e254
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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.unified.doc.generator.maven;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+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;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+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.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator;
+
+public class DocGenTest {
+    public static final String FS = File.separator;
+    private static final String TEST_PATH = "target" + FS + "test" + FS + "site";
+    private static final File GENERATOR_OUTPUT_DIR = new File(TEST_PATH);
+    private YangParserImpl parser;
+
+    @Before
+    public void init() {
+        if (GENERATOR_OUTPUT_DIR.exists()) {
+            deleteTestDir(GENERATOR_OUTPUT_DIR);
+        }
+        assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
+        parser = new YangParserImpl();
+    }
+
+    @After
+    public void cleanUp() {
+        if (GENERATOR_OUTPUT_DIR.exists()) {
+            deleteTestDir(GENERATOR_OUTPUT_DIR);
+        }
+    }
+
+    @Test
+    public void testListGeneration() throws Exception {
+        final List<File> sourceFiles = getSourceFiles("/doc-gen");
+        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
+        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
+        final BasicCodeGenerator generator = new DocumentationGeneratorImpl();
+        Collection<File> generatedFiles = generator.generateSources(context, GENERATOR_OUTPUT_DIR, modulesToBuild);
+        assertEquals(4, generatedFiles.size());
+    }
+
+    private static List<File> getSourceFiles(String path) throws Exception {
+        final URI resPath = DocGenTest.class.getResource(path).toURI();
+        final File sourcesDir = new File(resPath);
+        if (sourcesDir.exists()) {
+            final List<File> sourceFiles = new ArrayList<>();
+            final File[] fileArray = sourcesDir.listFiles();
+            if (fileArray == null) {
+                throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
+            }
+            sourceFiles.addAll(Arrays.asList(fileArray));
+            return sourceFiles;
+        } else {
+            throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
+        }
+    }
+
+    private static void deleteTestDir(File file) {
+        if (file.isDirectory()) {
+            File[] filesToDelete = file.listFiles();
+            if (filesToDelete != null) {
+                for (File f : filesToDelete) {
+                    deleteTestDir(f);
+                }
+            }
+        }
+        if (!file.delete()) {
+            throw new RuntimeException("Failed to clean up after test");
+        }
+    }
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/YangModuleInfoCompilationTest.java b/code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/unified/doc/generator/maven/YangModuleInfoCompilationTest.java
new file mode 100644 (file)
index 0000000..1a1052b
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * 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.unified.doc.generator.maven;
+
+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 java.io.File;
+import java.io.FileNotFoundException;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.ToolProvider;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+import org.sonatype.plexus.build.incremental.DefaultBuildContext;
+
+/**
+ * Test correct generation of YangModuleInfo class.
+ *
+ */
+// TODO: most of private static methods are copied from
+// binding-java-api-generator project - reorganize compilation tests
+public class YangModuleInfoCompilationTest {
+    public static final String FS = File.separator;
+    private static final String BASE_PKG = "org.opendaylight.yang.gen.v1";
+
+    private static final String TEST_PATH = "target" + FS + "test";
+    private static final File TEST_DIR = new File(TEST_PATH);
+
+    private static final String GENERATOR_OUTPUT_PATH = TEST_PATH + FS + "src";
+    private static final File GENERATOR_OUTPUT_DIR = new File(GENERATOR_OUTPUT_PATH);
+    private static final String COMPILER_OUTPUT_PATH = TEST_PATH + FS + "bin";
+    private static final File COMPILER_OUTPUT_DIR = new File(COMPILER_OUTPUT_PATH);
+
+    @BeforeClass
+    public static void createTestDirs() {
+        if (TEST_DIR.exists()) {
+            deleteTestDir(TEST_DIR);
+        }
+        assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
+        assertTrue(COMPILER_OUTPUT_DIR.mkdirs());
+    }
+
+    @Test
+    public void compilationTest() throws Exception {
+        final File sourcesOutputDir = new File(GENERATOR_OUTPUT_PATH + FS + "yang");
+        assertTrue("Failed to create test file '" + sourcesOutputDir + "'", sourcesOutputDir.mkdirs());
+        final File compiledOutputDir = new File(COMPILER_OUTPUT_PATH + FS + "yang");
+        assertTrue("Failed to create test file '" + compiledOutputDir + "'", compiledOutputDir.mkdirs());
+
+        generateTestSources("/yang-module-info", sourcesOutputDir);
+
+        // Test if $YangModuleInfoImpl.java file is generated
+        final String BASE_PATH = "org" + FS + "opendaylight" + FS + "yang" + FS + "gen" + FS + "v1";
+        final String NS_TEST = BASE_PATH + FS + "yang" + FS + "test" + FS + "main" + FS + "rev140630";
+        File parent = new File(sourcesOutputDir, NS_TEST);
+        File keyArgs = new File(parent, "$YangModuleInfoImpl.java");
+        assertTrue(keyArgs.exists());
+
+        // Test if sources are compilable
+        testCompilation(sourcesOutputDir, compiledOutputDir);
+
+        // Create URLClassLoader
+        URL[] urls = new URL[2];
+        urls[0] = compiledOutputDir.toURI().toURL();
+        urls[1] = new File(System.getProperty("user.dir")).toURI().toURL();
+        ClassLoader loader = new URLClassLoader(urls);
+
+        // Load class
+        Class<?> yangModuleInfoClass = Class.forName(BASE_PKG + ".yang.test.main.rev140630.$YangModuleInfoImpl", true,
+                loader);
+
+        // Test generated $YangModuleInfoImpl class
+        assertFalse(yangModuleInfoClass.isInterface());
+        Method getInstance = assertContainsMethod(yangModuleInfoClass, YangModuleInfo.class, "getInstance");
+        Object yangModuleInfo = getInstance.invoke(null);
+
+        // Test getImportedModules method
+        Method getImportedModules = assertContainsMethod(yangModuleInfoClass, Set.class, "getImportedModules");
+        Object importedModules = getImportedModules.invoke(yangModuleInfo);
+        assertTrue(importedModules instanceof Set);
+
+        YangModuleInfo infoImport = null;
+        YangModuleInfo infoSub1 = null;
+        YangModuleInfo infoSub2 = null;
+        YangModuleInfo infoSub3 = null;
+        for (Object importedModule : (Set<?>) importedModules) {
+            assertTrue(importedModule instanceof YangModuleInfo);
+            YangModuleInfo ymi = (YangModuleInfo) importedModule;
+            String name = ymi.getName();
+
+            switch (name) {
+            case "import-module":
+                infoImport = ymi;
+                break;
+            case "submodule1":
+                infoSub1 = ymi;
+                break;
+            case "submodule2":
+                infoSub2 = ymi;
+                break;
+            case "submodule3":
+                infoSub3 = ymi;
+            }
+        }
+        assertNotNull(infoImport);
+        assertNotNull(infoSub1);
+        assertNotNull(infoSub2);
+        assertNotNull(infoSub3);
+
+        cleanUp(sourcesOutputDir, compiledOutputDir);
+    }
+
+    private void generateTestSources(String resourceDirPath, File sourcesOutputDir) throws Exception {
+        final List<File> sourceFiles = getSourceFiles(resourceDirPath);
+        YangContextParser parser = new YangParserImpl();
+        final SchemaContext context = parser.parseFiles(sourceFiles);
+        CodeGeneratorImpl codegen = new CodeGeneratorImpl();
+        codegen.setBuildContext(new DefaultBuildContext());
+        codegen.generateSources(context, sourcesOutputDir, context.getModules());
+    }
+
+    private static void testCompilation(File sourcesOutputDir, File compiledOutputDir) {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
+        List<File> filesList = getJavaFiles(sourcesOutputDir);
+        Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjectsFromFiles(filesList);
+        Iterable<String> options = Arrays.asList("-d", compiledOutputDir.getAbsolutePath());
+        boolean compiled = compiler.getTask(null, null, null, options, null, compilationUnits).call();
+        assertTrue(compiled);
+    }
+
+    private static List<File> getJavaFiles(File directory) {
+        List<File> result = new ArrayList<>();
+        File[] filesToRead = directory.listFiles();
+        if (filesToRead != null) {
+            for (File file : filesToRead) {
+                if (file.isDirectory()) {
+                    result.addAll(getJavaFiles(file));
+                } else {
+                    String absPath = file.getAbsolutePath();
+                    if (absPath.endsWith(".java")) {
+                        result.add(file);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    private static List<File> getSourceFiles(String path) throws Exception {
+        final URI resPath = YangModuleInfoCompilationTest.class.getResource(path).toURI();
+        final File sourcesDir = new File(resPath);
+        final URI currentDir = new File(System.getProperty("user.dir")).toURI();
+        if (sourcesDir.exists()) {
+            final List<File> sourceFiles = new ArrayList<>();
+            final File[] fileArray = sourcesDir.listFiles();
+            if (fileArray == null) {
+                throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
+            }
+            for (File sourceFile : fileArray) {
+                sourceFiles.add(new File(currentDir.relativize(sourceFile.toURI()).toString()));
+            }
+            return sourceFiles;
+        } else {
+            throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
+        }
+    }
+
+    private static void deleteTestDir(File file) {
+        if (file.isDirectory()) {
+            File[] filesToDelete = file.listFiles();
+            if (filesToDelete != null) {
+                for (File f : filesToDelete) {
+                    deleteTestDir(f);
+                }
+            }
+        }
+        if (!file.delete()) {
+            throw new RuntimeException("Failed to clean up after test");
+        }
+    }
+
+    private static Method assertContainsMethod(Class<?> clazz, Class<?> returnType, String name, Class<?>... args) {
+        try {
+            Method m = clazz.getDeclaredMethod(name, args);
+            assertEquals(returnType, m.getReturnType());
+            return m;
+        } catch (NoSuchMethodException e) {
+            throw new AssertionError("Method " + name + " with args " + Arrays.toString(args)
+                    + " does not exists in class " + clazz.getSimpleName());
+        }
+    }
+
+    private static void cleanUp(File... resourceDirs) {
+        for (File resourceDir : resourceDirs) {
+            if (resourceDir.exists()) {
+                deleteTestDir(resourceDir);
+            }
+        }
+    }
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/wadl/generator/maven/WadlGenTest.java b/code-generator/maven-sal-api-gen-plugin/src/test/java/org/opendaylight/yangtools/yang/wadl/generator/maven/WadlGenTest.java
new file mode 100644 (file)
index 0000000..4485b42
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * 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.wadl.generator.maven;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+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;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+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.opendaylight.yangtools.yang2sources.spi.BasicCodeGenerator;
+
+public class WadlGenTest {
+    public static final String FS = File.separator;
+    private static final String TEST_PATH = "target" + FS + "test" + FS + "site";
+    private static final File GENERATOR_OUTPUT_DIR = new File(TEST_PATH);
+    private YangParserImpl parser;
+
+    @Before
+    public void init() {
+        if (GENERATOR_OUTPUT_DIR.exists()) {
+            deleteTestDir(GENERATOR_OUTPUT_DIR);
+        }
+        assertTrue(GENERATOR_OUTPUT_DIR.mkdirs());
+        parser = new YangParserImpl();
+    }
+
+    @After
+    public void cleanUp() {
+        if (GENERATOR_OUTPUT_DIR.exists()) {
+            deleteTestDir(GENERATOR_OUTPUT_DIR);
+        }
+    }
+
+    @Test
+    public void testListGeneration() throws Exception {
+        final List<File> sourceFiles = getSourceFiles("/wadl-gen");
+        final Set<Module> modulesToBuild = parser.parseYangModels(sourceFiles);
+        final SchemaContext context = parser.resolveSchemaContext(modulesToBuild);
+        final BasicCodeGenerator generator = new WadlGenerator();
+        Collection<File> generatedWadlFiles = generator.generateSources(context, GENERATOR_OUTPUT_DIR, modulesToBuild);
+        assertEquals(3, generatedWadlFiles.size());
+    }
+
+    private static List<File> getSourceFiles(String path) throws Exception {
+        final URI resPath = WadlGenTest.class.getResource(path).toURI();
+        final File sourcesDir = new File(resPath);
+        if (sourcesDir.exists()) {
+            final List<File> sourceFiles = new ArrayList<>();
+            final File[] fileArray = sourcesDir.listFiles();
+            if (fileArray == null) {
+                throw new IllegalArgumentException("Unable to locate files in " + sourcesDir);
+            }
+            sourceFiles.addAll(Arrays.asList(fileArray));
+            return sourceFiles;
+        } else {
+            throw new FileNotFoundException("Testing files were not found(" + sourcesDir.getName() + ")");
+        }
+    }
+
+    private static void deleteTestDir(File file) {
+        if (file.isDirectory()) {
+            File[] filesToDelete = file.listFiles();
+            if (filesToDelete != null) {
+                for (File f : filesToDelete) {
+                    deleteTestDir(f);
+                }
+            }
+        }
+        if (!file.delete()) {
+            throw new RuntimeException("Failed to clean up after test");
+        }
+    }
+
+}
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/network-topology@2013-07-12.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/doc-gen/network-topology@2013-07-12.yang
new file mode 100644 (file)
index 0000000..30353ba
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * 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 network-topology  {
+    yang-version 1;
+    namespace "urn:TBD:params:xml:ns:yang:network-topology";
+    // replace with IANA namespace when assigned
+    prefix "nt";
+
+    organization "TBD";
+
+    contact "WILL-BE-DEFINED-LATER";
+/*
+    description 
+        "This module defines a model for the topology of a network.
+        Key design decisions are as follows:
+        A topology consists of a set of nodes and links.  
+        Links are point-to-point and unidirectional.  
+        Bidirectional connections need to be represented through
+        two separate links.  
+        Multipoint connections, broadcast domains etc can be represented 
+        through a hierarchy of nodes, then connecting nodes at 
+        upper layers of the hierarchy.";  
+*/
+    revision 2013-07-12 {
+        description
+            "Initial revision.";
+    }
+        
+    typedef topology-id {
+        type string;
+        description 
+            "An identifier for a topology.";
+    }
+
+    typedef node-id {
+        type string;
+        description
+            "An identifier for a node in a topology.  
+            The identifier may be opaque.  
+            The identifier SHOULD be chosen such that the same node in a 
+            real network topology will always be identified through the 
+            same identifier, even if the model is instantiated in separate 
+            datastores. An implementation MAY choose to capture semantics 
+            in the identifier, for example to indicate the type of node 
+            and/or the type of topology that the node is a part of.";  
+    }
+
+    typedef link-id {
+        type string;
+        description
+            "An identifier for a link in a topology.  
+            The identifier may be opaque.  
+            The identifier SHOULD be chosen such that the same link in a 
+            real network topology will always be identified through the 
+            same identifier, even if the model is instantiated in separate 
+            datastores. An implementation MAY choose to capture semantics 
+            in the identifier, for example to indicate the type of link 
+            and/or the type of topology that the link is a part of.";  
+    }
+
+    typedef tp-id {
+        type string;
+        description 
+            "An identifier for termination points on a node. 
+            The identifier may be opaque.  
+            The identifier SHOULD be chosen such that the same TP in a 
+            real network topology will always be identified through the 
+            same identifier, even if the model is instantiated in separate 
+            datastores. An implementation MAY choose to capture semantics 
+            in the identifier, for example to indicate the type of TP 
+            and/or the type of node and topology that the TP is a part of.";  
+    }
+
+    typedef tp-ref {
+        type leafref {
+            path "/network-topology/topology/node/termination-point/tp-id";
+        }
+        description 
+            "A type for an absolute reference to a termination point.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+    typedef topology-ref {
+        type leafref {
+            path "/network-topology/topology/topology-id";
+        }
+        description 
+            "A type for an absolute reference a topology instance.";
+    }
+    
+    typedef node-ref {
+        type leafref {
+            path "/network-topology/topology/node/node-id";
+        }
+        description 
+            "A type for an absolute reference to a node instance.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+
+    typedef link-ref {
+        type leafref {
+            path "/network-topology/topology/link/link-id";
+        }
+        description 
+            "A type for an absolute reference a link instance.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+
+    typedef x {
+        type binary {
+            length 5..10|15..20|25..30;
+        }
+        description "x type description";
+        reference "x type reference";
+    }
+
+    typedef y {
+        type int32 {
+            range 5..555;
+        }
+    }
+
+    identity crypto-alg {
+        description "Base identity from which all crypto algorithms are derived.";
+    }
+
+    identity des {
+        base "crypto-alg";
+        description "DES crypto algorithm";
+    }
+
+    identity des3 {
+        base "crypto-alg";
+        description "Triple DES crypto algorithm";
+    }
+
+    grouping tp-attributes {
+        description 
+            "The data objects needed to define a termination point.
+            (This only includes a single leaf at this point, used
+            to identify the termination point.)  
+            Provided in a grouping so that in addition to the datastore,
+            the data can also be included in notifications.";
+        leaf tp-id {
+            type tp-id;
+        }
+        leaf-list tp-ref {
+            type tp-ref;
+            config false;
+            description 
+                "The leaf list identifies any termination points that the 
+                termination point is dependent on, or maps onto.  
+                Those termination points will themselves be contained 
+                in a supporting node.  
+                This dependency information can be inferred from 
+                the dependencies between links.  For this reason, 
+                this item is not separately configurable.  Hence no
+                corresponding constraint needs to be articulated.  
+                The corresponding information is simply provided by the
+                implementing system.";
+        }
+    } 
+    
+    grouping node-attributes {
+        description
+            "The data objects needed to define a node.
+            The objects are provided in a grouping so that in addition to
+            the datastore, the data can also be included in notifications
+            as needed.";
+        leaf node-id {
+            type node-id;
+            description 
+                "The identifier of a node in the topology.  
+                A node is specific to a topology to which it belongs.";   
+        }
+        list supporting-node {
+            description 
+                "This list defines vertical layering information for nodes. 
+                It allows to capture for any given node, which node (or nodes)
+                in the corresponding underlay topology it maps onto.  
+                A node can map to zero, one, or more nodes below it;
+                accordingly there can be zero, one, or more elements in the list.
+                If there are specific layering requirements, for example
+                specific to a particular type of topology that only allows
+                for certain layering relationships, the choice
+                below can be augmented with additional cases.
+                A list has been chosen rather than a leaf-list in order 
+                to provide room for augmentations, e.g. for 
+                statistics or priorization information associated with 
+                supporting nodes.";
+            key "node-ref";
+            leaf node-ref {
+                type node-ref;
+            }
+        }
+    }
+            
+    grouping link-attributes {
+        // This is a grouping, not defined inline with the link definition itself,
+        // so it can be included in a notification, if needed
+        leaf link-id {
+            type link-id;
+            description
+                "The identifier of a link in the topology.  
+                A link is specific to a topology to which it belongs.";   
+        }
+        container source { 
+            description "XYZ";
+            leaf source-node {
+                mandatory true;
+                type node-ref; 
+                description 
+                    "Source node identifier, must be in same topology.";
+            }
+            leaf source-tp {
+                type tp-ref; 
+                description 
+                    "Termination point within source node that terminates the link.";           
+            }
+        }
+        container destination { 
+            leaf dest-node {
+                mandatory true;
+                type node-ref; 
+                description 
+                    "Destination node identifier, must be in same topology.";
+            }
+            leaf dest-tp {
+                type tp-ref;
+                description 
+                    "Termination point within destination node that terminates the link.";
+            }
+        }
+        list supporting-link {
+            key "link-ref";
+            leaf link-ref {
+                type link-ref;
+            }
+        }
+    }
+    
+
+    container network-topology {
+        list topology {
+            description "
+                This is the model of an abstract topology.
+                A topology contins nodes and links.  
+                Each topology MUST be identified by
+                unique topology-id for reason that a network could contain many
+                topologies.
+            ";
+            key "topology-id";
+            leaf topology-id {
+                type topology-id; 
+                description "
+                    It is presumed that a datastore will contain many topologies. To
+                    distinguish between topologies it is vital to have UNIQUE
+                    topology identifiers.
+                ";
+            }
+            container topology-types {
+                description 
+                    "This container is used to identify the type, or types 
+                    (as a topology can support several types simultaneously), 
+                    of the topology.  
+                    Topology types are the subject of several integrity constraints 
+                    that an implementing server can validate in order to 
+                    maintain integrity of the datastore.  
+                    Topology types are indicated through separate data nodes; 
+                    the set of topology types is expected to increase over time.
+                    To add support for a new topology, an augmenting module
+                    needs to augment this container with a new empty optional 
+                    container to indicate the new topology type.  
+                    The use of a container allows to indicate a subcategorization
+                    of topology types.  
+                    The container SHALL NOT be augmented with any data nodes 
+                    that serve a purpose other than identifying a particular 
+                    topology type.  
+                ";
+                choice node-type {
+                    case type1 {
+                        container c1 {
+                            leaf id {
+                                type int8;
+                            }
+                        }
+                    }
+                    case type2 {
+                        container c2 {
+                            container cc2 {}
+                        }
+                    }
+                    case type3 {
+                        list c3 {
+                            container cc3 {
+                                leaf id {
+                                    type string;
+                                }
+                            }
+                        }
+                    }
+                }
+            }   
+            list underlay-topology {
+                key "topology-ref";
+                leaf topology-ref {
+                    type topology-ref;
+                }  
+                // a list, not a leaf-list, to allow for potential augmentation 
+                // with properties specific to the underlay topology, 
+                // such as statistics, preferences, or cost.  
+                description 
+                    "Identifies the topology, or topologies, that this topology
+                    is dependent on.";
+            }
+            
+            list node {
+                description "The list of network nodes defined for the topology.";
+                key "node-id";
+                uses node-attributes;
+                must "boolean(../underlay-topology[*]/node[./supporting-nodes/node-ref])";
+                    // This constraint is meant to ensure that a referenced node is in fact 
+                    // a node in an underlay topology.  
+                list termination-point {
+                    description
+                        "A termination point can terminate a link.  
+                        Depending on the type of topology, a termination point could, 
+                        for example, refer to a port or an interface."; 
+                    key "tp-id";
+                    uses tp-attributes;
+                }
+            }
+            
+            list link {
+                description "
+                    A Network Link connects a by Local (Source) node and
+                    a Remote (Destination) Network Nodes via a set of the 
+                    nodes' termination points. 
+                    As it is possible to have several links between the same
+                    source and destination nodes, and as a link could potentially
+                    be re-homed between termination points, to ensure that we 
+                    would always know to distinguish between links, every link 
+                    is identified by a dedicated link identifier.  
+                    Note that a link models a point-to-point link, not a multipoint
+                    link.  
+                    Layering dependencies on links in underlay topologies are
+                    not represented as the layering information of nodes and of 
+                    termination points is sufficient.  
+                ";
+                key "link-id";
+                uses link-attributes;
+                must "boolean(../underlay-topology/link[./supporting-link]";
+                    // Constraint: any supporting link must be part of an underlay topology
+                must "boolean(../node[./source/source-node])";
+                    // Constraint: A link must have as source a node of the same topology
+                must "boolean(../node[./destination/dest-node])";
+                    // Constraint: A link must have as source a destination of the same topology
+                must "boolean(../node/termination-point[./source/source-tp])";
+                    // Constraint: The source termination point must be contained in the source node
+                must "boolean(../node/termination-point[./destination/dest-tp])";
+                    // Constraint: The destination termination point must be contained 
+                    // in the destination node
+            }
+        }
+    }
+
+    notification n1 {
+        description "This example defines a notification 1.";
+        leaf event-class {
+            type string;
+        }
+        anyxml reporting-entity;
+        container severity {
+            list links {
+                container endpoints {
+                    leaf start {
+                        type x;
+                    }
+                    leaf end {
+                        type y;
+                    }
+                }
+                leaf id {
+                    type string;
+                }
+            }
+        }
+    }
+
+    notification n2 {
+        description "This example defines a notification 2.";
+        leaf event-class {
+            type string;
+        }
+        anyxml reporting-entity;
+        leaf severity {
+            type string;
+        }
+    }
+
+    augment "/network-topology" {
+        anyxml any-a;
+        anyxml any-b;
+    }
+
+    augment "/network-topology/topology" {
+        description "description of augment 2";
+        reference "reference of augment 2";
+        list list-a {}
+        list list-b {
+            leaf leaf-c {
+                type string;
+            }
+        }
+    }
+
+    augment "/network-topology/topology/topology-types" {
+        container container-c {
+            leaf id {
+                type binary;
+            }
+        }
+    }
+
+    rpc rock-the-house {
+        description "This statement is used to define a NETCONF RPC operation.";
+        reference "http://tools.ietf.org/html/rfc6020#section-7.13";
+        input {
+            leaf zip-code {
+                type string;
+            }
+        }
+        output {
+            leaf number {
+                type int32;
+            }
+        }
+    }
+
+    extension c-define {
+        description
+            "Takes as argument a name string.
+            Makes the code generator use the given name in the
+            #define.";
+        argument "name";
+    }
+
+    feature local-storage {
+        description
+            "This feature means the device supports local
+            storage (memory, flash or disk) that can be used to
+            store syslog messages.";
+    }
+
+}
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..d29a2a7
--- /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 timeout2 {
+                mandatory true;
+                type int32;
+            }
+
+            container executor2 {
+                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 executor3 {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity netty:netty-event-executor;
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/controller-network-rpcs.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/controller-network-rpcs.yang
new file mode 100644 (file)
index 0000000..b6fd3be
--- /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
+ */
+module controller-network-rpcs {
+       yang-version 1;
+       namespace "urn:opendaylight:controller:network:rpcs";
+       prefix "topos";
+       
+       import ietf-inet-types { prefix "inet"; }
+       
+       revision 2013-05-20 {
+          description "Initial demo";
+       }
+       
+       rpc activate-software-image {
+         input {
+             leaf image-name {
+                 type string;
+             }
+         }
+         output {
+             leaf status {
+                 type string;
+             }
+         }
+     }
+     
+     rpc rock-the-house {
+         input {
+             leaf zip-code {
+                 type string;
+             }
+         }
+     }
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/controller-network.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/controller-network.yang
new file mode 100644 (file)
index 0000000..372e878
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * 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 controller-network {
+       yang-version 1;
+       namespace "urn:opendaylight:controller:network";
+       prefix "topos";
+       
+       import ietf-inet-types { prefix "inet"; }
+       
+       revision 2013-05-20 {
+          description "Initial demo";
+       }
+       
+
+       
+       
+       typedef topology-id {
+               type string;
+       }
+
+       typedef node-id {
+               type string;
+       }
+
+       typedef link-id {
+               type string;
+       }
+
+       typedef tp-id {
+               type string;
+               description "identifier for termination points on a port";
+       }
+
+       typedef tp-ref {
+               type leafref {
+                       path "/network/topologies/topology/nodes/node/termination-points/termination-point/tp-id";
+               }
+       }
+       typedef topology-ref {
+               type leafref {
+                       path "/network/topologies/topology/topology-id";
+               }
+               description "This type is used for leafs that reference topology identifier instance.";
+               // currently not used
+       }
+
+       typedef node-ref {
+               type leafref {
+                       path "/network/topologies/topology/nodes/node/node-id";
+               }
+               description "This type is used for leafs that reference a node instance.";
+       }
+
+       typedef link-ref {
+               type leafref {
+                       path "/network/topologies/topology/links/link/link-id";
+               }
+               description "This type is used for leafs that reference a link instance.";
+               // currently not used
+       }
+       
+       typedef network-element-ref {
+               type leafref {
+                       path "/network/network-elements/network-element/element-id";
+               }
+       }
+
+
+       typedef element-id {
+               type string;
+       }
+       
+       container network {
+               container topologies {
+                       list topology {
+                               description "
+                                       This is the model of abstract topology which contains only Network
+                                       Nodes and Network Links. Each topology MUST be identified by
+                                       unique topology-id for reason that the store could contain many
+                                       topologies.
+                               ";
+                               key "topology-id";
+                               leaf topology-id {
+                                       type topology-id; 
+                                       description "
+                                               It is presumed that datastore will contain many topologies. To
+                                               distinguish between topologies it is vital to have UNIQUE
+                                               topology identifier.
+                                       ";
+                               }
+
+                               container types {
+                                       description "
+                                               The container for definition of topology types.
+                                               The augmenting modules should add empty optional leaf 
+                                               to this container to signalize topology type.
+                                       ";
+                               }
+
+                               container nodes {
+                                       list node {
+                                               description "The list of network nodes defined for topology.";
+
+                                               key "node-id";
+                                               leaf node-id {
+                                                       type node-id;
+                                                       description "The Topology identifier of network-node.";
+                                               }
+
+                                               leaf supporting-ne {
+                                                       type network-element-ref;
+                                               }
+                                               
+                                               container termination-points {
+                                                       list termination-point {
+                                                               key "tp-id";
+                                                               leaf tp-id {
+                                                                       type tp-id;
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+               
+                               container links {
+                                       list link {
+                                               description "
+                                                       The Network Link which is defined by Local (Source) and
+                                                       Remote (Destination) Network Nodes. Every link MUST be
+                                                       defined either by identifier and his local and remote
+                                                       Network Nodes (in real applications it is common that many
+                                                       links are originated from one node and end up in same
+                                                       remote node). To ensure that we would always know to
+                                                       distinguish between links, every link SHOULD have
+                                                       identifier.
+                                               ";
+                                               key "link-id";
+               
+                                               leaf link-id {
+                                                       type link-id;
+                                               }
+                                               container source { 
+                                                       leaf source-node {
+                                                               type node-ref;
+                                                               description "Source node identifier.";
+                                                       }
+                                                       leaf source-tp {
+                                                               type tp-ref;
+                                                       }
+                                               }
+                                               container destination { 
+                                                       leaf dest-node {
+                                                               type node-ref;
+                                                               description "Destination node identifier.";
+                                                       }
+                                                       leaf dest-tp {
+                                                               type tp-ref;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               container network-elements {
+                       config true;
+                       list network-element {
+                               key "element-id";
+                               leaf element-id {
+                                       type element-id;
+                               }
+                       }
+               }
+       }
+       
+       rpc activate-software-image {
+         input {
+             leaf image-name {
+                 type string;
+             }
+         }
+         output {
+             leaf status {
+                 type string;
+             }
+         }
+     }
+     
+     rpc rock-the-house {
+         input {
+             leaf zip-code {
+                 type string;
+             }
+         }
+     }
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/controller-openflow.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/controller-openflow.yang
new file mode 100644 (file)
index 0000000..0f6f945
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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 controller-openflow {
+
+    namespace "urn:opendaylight:controller:openflow";
+    prefix "of";
+    import controller-network {prefix cn;}
+    
+    
+    revision 2013-05-20 {
+       description "Initial demo";
+    }
+
+   
+
+
+
+    typedef datapath-id {
+        type string {
+            length 16;
+        }
+    }
+
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:types" {
+        leaf openflow {type string;}
+    }
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:links/cn:link/cn:source" {
+        when "../../../cn:types/of:openflow";
+
+        leaf logical-port {
+            type int32;
+        }
+    }
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:links/cn:link/cn:destination" {
+        when "../../../cn:types/of:openflow";
+
+        leaf logical-port {
+            type int32;
+        }
+    }
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:nodes/cn:node" {
+        when "../../../cn:types/of:openflow";
+        leaf datapath-id {
+            type datapath-id;
+        }
+    }
+    
+    augment "/cn:network/cn:network-elements/cn:network-element" {
+        leaf datapath-id {
+            type datapath-id;
+        }
+
+        container ports {
+            list port {
+                key "logical-port-id";
+                
+                leaf logical-port-id {
+                    type int32;
+                }
+
+                // Should be replaced with ref to interface
+                leaf physical-name {
+                    type string;
+                }
+            }
+        }
+        container flow-tables {
+            list flow-table {
+                key "flow-table-id";
+                leaf flow-table-id {
+                    type string;
+                }
+
+            }
+        }
+    }
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/demo-topology.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/demo-topology.yang
new file mode 100644 (file)
index 0000000..b4025ba
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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 demo-topology {
+       yang-version 1;
+    namespace "urn:model.1demo-275topology.4.5.my";
+    prefix "tp";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+               This module contains the definitions of elements that creates network 
+               topology i.e. definition of network nodes and links. This module is
+               not designed to be used solely for network representation. This module
+               SHOULD be used as base module in defining the network topology.
+       ";
+
+    revision "2013-02-08"{
+               reference " WILL BE DEFINED LATER";
+       }
+
+       container topology {
+        description "
+                       This is the model of abstract topology which contains only Network
+                       Nodes and Network Links. Each topology MUST be identified by
+                       unique topology-id for reason that the store could contain many
+                       topologies.
+               ";
+
+        leaf topology-id {
+            type string;
+            description "
+                               It is presumed that datastore will contain many topologies. To
+                               distinguish between topologies it is vital to have UNIQUE
+                               topology identifier.
+                       ";
+        }
+
+        container network-nodes {
+               list network-node {
+                   description "The list of network nodes defined for topology.";
+
+                       key "node-id";
+
+                       leaf node-id {
+                               type string;
+                               description "The Topology identifier of network-node.";
+                       }
+                
+                list network-interface {
+                    key "interface-id";
+                    
+                    leaf interface-id {
+                        type uint8;
+                    }
+                    
+                    leaf interface-address {
+                        type string;
+                    }
+                }
+                
+                   container node-attributes {
+                                       description "
+                                               Additional attributes that can Network Node contains.
+                                       ";
+
+                                       leaf geo-latitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
+
+                                       leaf geo-longitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
+                               }
+               }
+        }
+        
+        container network-links {
+               list network-link {
+                   description "
+                                       The Network Link which is defined by Local (Source) and
+                                       Remote (Destination) Network Nodes. Every link MUST be
+                                       defined either by identifier and his local and remote
+                                       Network Nodes (in real applications it is common that many
+                                       links are originated from one node and end up in same
+                                       remote node). To ensure that we would always know to
+                                       distinguish between links, every link SHOULD have
+                                       identifier.
+                               ";
+                       key "link-id";
+
+                       leaf link-id {
+                               type string;
+                               description "";
+                       }
+
+                   container source {
+                                       leaf node-id {
+                                               type string;
+                                               description "Source node identifier.";
+                                       }
+                               }
+
+                               container destination {
+                                       leaf node-id {
+                                               type string;
+                                               description "Destination node identifier.";
+                                       }
+                               }
+
+                               container link-attributes {
+                                       description "Aditional attributes that can Network Link contains.";
+                               }
+                   }
+        }
+    }
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/ietf-inet-types@2010-09-24.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/ietf-inet-types@2010-09-24.yang
new file mode 100644 (file)
index 0000000..de20feb
--- /dev/null
@@ -0,0 +1,418 @@
+ module ietf-inet-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+   prefix "inet";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types for Internet addresses and related things.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of protocol field related types ***/
+
+   typedef ip-version {
+     type enumeration {
+       enum unknown {
+         value "0";
+         description
+          "An unknown or unspecified version of the Internet protocol.";
+       }
+       enum ipv4 {
+         value "1";
+         description
+          "The IPv4 protocol as defined in RFC 791.";
+       }
+       enum ipv6 {
+         value "2";
+         description
+          "The IPv6 protocol as defined in RFC 2460.";
+       }
+     }
+     description
+      "This value represents the version of the IP protocol.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetVersion textual convention of the SMIv2.";
+     reference
+      "RFC  791: Internet Protocol
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   typedef dscp {
+     type uint8 {
+       range "0..63";
+     }
+     description
+      "The dscp type represents a Differentiated Services Code-Point
+       that may be used for marking packets in a traffic stream.
+
+       In the value set and its semantics, this type is equivalent
+       to the Dscp textual convention of the SMIv2.";
+     reference
+      "RFC 3289: Management Information Base for the Differentiated
+                 Services Architecture
+       RFC 2474: Definition of the Differentiated Services Field
+                 (DS Field) in the IPv4 and IPv6 Headers
+       RFC 2780: IANA Allocation Guidelines For Values In
+                 the Internet Protocol and Related Headers";
+   }
+
+   typedef ipv6-flow-label {
+     type uint32 {
+       range "0..1048575";
+     }
+     description
+      "The flow-label type represents flow identifier or Flow Label
+       in an IPv6 packet header that may be used to discriminate
+       traffic flows.
+
+       In the value set and its semantics, this type is equivalent
+       to the IPv6FlowLabel textual convention of the SMIv2.";
+     reference
+      "RFC 3595: Textual Conventions for IPv6 Flow Label
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+   }
+
+   typedef port-number {
+     type uint16 {
+       range "0..65535";
+     }
+     description
+      "The port-number type represents a 16-bit port number of an
+       Internet transport layer protocol such as UDP, TCP, DCCP, or
+       SCTP.  Port numbers are assigned by IANA.  A current list of
+       all assignments is available from <http://www.iana.org/>.
+
+       Note that the port number value zero is reserved by IANA.  In
+       situations where the value zero does not make sense, it can
+       be excluded by subtyping the port-number type.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetPortNumber textual convention of the SMIv2.";
+     reference
+      "RFC  768: User Datagram Protocol
+       RFC  793: Transmission Control Protocol
+       RFC 4960: Stream Control Transmission Protocol
+       RFC 4340: Datagram Congestion Control Protocol (DCCP)
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of autonomous system related types ***/
+
+   typedef as-number {
+     type uint32;
+     description
+      "The as-number type represents autonomous system numbers
+       which identify an Autonomous System (AS).  An AS is a set
+       of routers under a single technical administration, using
+       an interior gateway protocol and common metrics to route
+       packets within the AS, and using an exterior gateway
+       protocol to route packets to other ASs'.  IANA maintains
+       the AS number space and has delegated large parts to the
+       regional registries.
+
+       Autonomous system numbers were originally limited to 16
+       bits.  BGP extensions have enlarged the autonomous system
+       number space to 32 bits.  This type therefore uses an uint32
+       base type without a range restriction in order to support
+       a larger autonomous system number space.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetAutonomousSystemNumber textual convention of
+       the SMIv2.";
+     reference
+      "RFC 1930: Guidelines for creation, selection, and registration
+                 of an Autonomous System (AS)
+       RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+       RFC 4893: BGP Support for Four-octet AS Number Space
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of IP address and hostname related types ***/
+
+   typedef ip-address {
+     type union {
+       type inet:ipv4-address;
+       type inet:ipv6-address;
+     }
+     description
+      "The ip-address type represents an IP address and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-address {
+     type string {
+       pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '(%[\p{N}\p{L}]+)?';
+     }
+     description
+       "The ipv4-address type represents an IPv4 address in
+        dotted-quad notation.  The IPv4 address may include a zone
+        index, separated by a % sign.
+
+        The zone index is used to disambiguate identical address
+        values.  For link-local addresses, the zone index will
+        typically be the interface index number or the name of an
+        interface.  If the zone index is not present, the default
+        zone of the device will be used.
+
+        The canonical format for the zone index is the numerical
+        format";
+   }
+
+   typedef ipv6-address {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(%[\p{N}\p{L}]+)?';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(%.+)?';
+     }
+     description
+      "The ipv6-address type represents an IPv6 address in full,
+       mixed, shortened, and shortened-mixed notation.  The IPv6
+       address may include a zone index, separated by a % sign.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format of IPv6 addresses uses the compressed
+       format described in RFC 4291, Section 2.2, item 2 with the
+       following additional rules: the :: substitution must be
+       applied to the longest sequence of all-zero 16-bit chunks
+       in an IPv6 address.  If there is a tie, the first sequence
+       of all-zero 16-bit chunks is replaced by ::.  Single
+       all-zero 16-bit chunks are not compressed.  The canonical
+       format uses lowercase characters and leading zeros are
+       not allowed.  The canonical format for the zone index is
+       the numerical format as described in RFC 4007, Section
+       11.2.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture
+       RFC 4007: IPv6 Scoped Address Architecture
+       RFC 5952: A Recommendation for IPv6 Address Text Representation";
+   }
+
+   typedef ip-prefix {
+     type union {
+       type inet:ipv4-prefix;
+       type inet:ipv6-prefix;
+     }
+     description
+      "The ip-prefix type represents an IP prefix and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-prefix {
+     type string {
+       pattern
+          '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+        +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+        + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+     }
+     description
+      "The ipv4-prefix type represents an IPv4 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal to 32.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The canonical format of an IPv4 prefix has all bits of
+       the IPv4 address set to zero that are not part of the
+       IPv4 prefix.";
+   }
+
+   typedef ipv6-prefix {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(/.+)';
+     }
+     description
+      "The ipv6-prefix type represents an IPv6 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal 128.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The IPv6 address should have all bits that do not belong
+       to the prefix set to zero.
+
+       The canonical format of an IPv6 prefix has all bits of
+       the IPv6 address set to zero that are not part of the
+       IPv6 prefix.  Furthermore, IPv6 address is represented
+       in the compressed format described in RFC 4291, Section
+       2.2, item 2 with the following additional rules: the ::
+       substitution must be applied to the longest sequence of
+       all-zero 16-bit chunks in an IPv6 address.  If there is
+       a tie, the first sequence of all-zero 16-bit chunks is
+       replaced by ::.  Single all-zero 16-bit chunks are not
+       compressed.  The canonical format uses lowercase
+       characters and leading zeros are not allowed.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture";
+   }
+
+   /*** collection of domain name and URI types ***/
+
+   typedef domain-name {
+     type string {
+       pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+            +  '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+            +  '|\.';
+       length "1..253";
+     }
+     description
+      "The domain-name type represents a DNS domain name.  The
+       name SHOULD be fully qualified whenever possible.
+
+       Internet domain names are only loosely specified.  Section
+       3.5 of RFC 1034 recommends a syntax (modified in Section
+       2.1 of RFC 1123).  The pattern above is intended to allow
+       for current practice in domain name use, and some possible
+       future expansion.  It is designed to hold various types of
+       domain names, including names used for A or AAAA records
+       (host names) and other records, such as SRV records.  Note
+       that Internet host names have a stricter syntax (described
+       in RFC 952) than the DNS recommendations in RFCs 1034 and
+       1123, and that systems that want to store host names in
+       schema nodes using the domain-name type are recommended to
+       adhere to this stricter standard to ensure interoperability.
+
+       The encoding of DNS names in the DNS protocol is limited
+       to 255 characters.  Since the encoding consists of labels
+       prefixed by a length bytes and there is a trailing NULL
+       byte, only 253 characters can appear in the textual dotted
+       notation.
+
+       The description clause of schema nodes using the domain-name
+       type MUST describe when and how these names are resolved to
+       IP addresses.  Note that the resolution of a domain-name value
+       may require to query multiple DNS records (e.g., A for IPv4
+       and AAAA for IPv6).  The order of the resolution process and
+       which DNS record takes precedence can either be defined
+       explicitely or it may depend on the configuration of the
+       resolver.
+
+       Domain-name values use the US-ASCII encoding.  Their canonical
+       format uses lowercase US-ASCII characters.  Internationalized
+       domain names MUST be encoded in punycode as described in RFC
+       3492";
+     reference
+      "RFC  952: DoD Internet Host Table Specification
+       RFC 1034: Domain Names - Concepts and Facilities
+       RFC 1123: Requirements for Internet Hosts -- Application
+                 and Support
+       RFC 2782: A DNS RR for specifying the location of services
+                 (DNS SRV)
+       RFC 3492: Punycode: A Bootstring encoding of Unicode for
+                 Internationalized Domain Names in Applications
+                 (IDNA)
+       RFC 5891: Internationalizing Domain Names in Applications
+                 (IDNA): Protocol";
+   }
+
+   typedef host {
+     type union {
+       type inet:ip-address;
+       type inet:domain-name;
+     }
+     description
+      "The host type represents either an IP address or a DNS
+       domain name.";
+   }
+
+   typedef uri {
+     type string;
+     description
+      "The uri type represents a Uniform Resource Identifier
+       (URI) as defined by STD 66.
+
+       Objects using the uri type MUST be in US-ASCII encoding,
+       and MUST be normalized as described by RFC 3986 Sections
+       6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+       percent-encoding is removed, and all case-insensitive
+       characters are set to lowercase except for hexadecimal
+       digits, which are normalized to uppercase as described in
+       Section 6.2.2.1.
+
+       The purpose of this normalization is to help provide
+       unique URIs.  Note that this normalization is not
+       sufficient to provide uniqueness.  Two URIs that are
+       textually distinct after this normalization may still be
+       equivalent.
+
+       Objects using the uri type may restrict the schemes that
+       they permit.  For example, 'data:' and 'urn:' schemes
+       might not be appropriate.
+
+       A zero-length URI is not a valid URI.  This can be used to
+       express 'URI absent' where required.
+
+       In the value set and its semantics, this type is equivalent
+       to the Uri SMIv2 textual convention defined in RFC 5017.";
+     reference
+      "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+       RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                 Group: Uniform Resource Identifiers (URIs), URLs,
+                 and Uniform Resource Names (URNs): Clarifications
+                 and Recommendations
+       RFC 5017: MIB Textual Conventions for Uniform Resource
+                 Identifiers (URIs)";
+   }
+
+ }
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/ietf-yang-types@2010-09-24.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/wadl-gen/ietf-yang-types@2010-09-24.yang
new file mode 100644 (file)
index 0000000..51d9f8b
--- /dev/null
@@ -0,0 +1,396 @@
+ module ietf-yang-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types";
+   prefix "yang";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of counter and gauge types ***/
+
+   typedef counter32 {
+     type uint32;
+     description
+      "The counter32 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter32 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter32 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter32.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter32 {
+     type yang:counter32;
+     default "0";
+     description
+      "The zero-based-counter32 type represents a counter32
+       that has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter32 textual convention of the SMIv2.";
+     reference
+       "RFC 4502: Remote Network Monitoring Management Information
+                  Base Version 2";
+   }
+
+   typedef counter64 {
+     type uint64;
+     description
+      "The counter64 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter64 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter64 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter64.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter64 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter64 {
+     type yang:counter64;
+     default "0";
+     description
+      "The zero-based-counter64 type represents a counter64 that
+       has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter64 textual convention of the SMIv2.";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   typedef gauge32 {
+     type uint32;
+     description
+      "The gauge32 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^32-1 (4294967295 decimal), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge32 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge32 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the Gauge32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef gauge64 {
+     type uint64;
+     description
+      "The gauge64 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^64-1 (18446744073709551615), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge64 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge64 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the CounterBasedGauge64 SMIv2 textual convention defined
+       in RFC 2856";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   /*** collection of identifier related types ***/
+
+   typedef object-identifier {
+     type string {
+       pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))'
+             + '(\.(0|([1-9]\d*)))*';
+     }
+     description
+      "The object-identifier type represents administratively
+       assigned names in a registration-hierarchical-name tree.
+
+       Values of this type are denoted as a sequence of numerical
+       non-negative sub-identifier values.  Each sub-identifier
+       value MUST NOT exceed 2^32-1 (4294967295).  Sub-identifiers
+       are separated by single dots and without any intermediate
+       whitespace.
+
+       The ASN.1 standard restricts the value space of the first
+       sub-identifier to 0, 1, or 2.  Furthermore, the value space
+       of the second sub-identifier is restricted to the range
+       0 to 39 if the first sub-identifier is 0 or 1.  Finally,
+       the ASN.1 standard requires that an object identifier
+       has always at least two sub-identifier.  The pattern
+       captures these restrictions.
+
+       Although the number of sub-identifiers is not limited,
+       module designers should realize that there may be
+       implementations that stick with the SMIv2 limit of 128
+       sub-identifiers.
+
+       This type is a superset of the SMIv2 OBJECT IDENTIFIER type
+       since it is not restricted to 128 sub-identifiers.  Hence,
+       this type SHOULD NOT be used to represent the SMIv2 OBJECT
+       IDENTIFIER type, the object-identifier-128 type SHOULD be
+       used instead.";
+     reference
+      "ISO9834-1: Information technology -- Open Systems
+       Interconnection -- Procedures for the operation of OSI
+       Registration Authorities: General procedures and top
+       arcs of the ASN.1 Object Identifier tree";
+   }
+
+
+
+
+   typedef object-identifier-128 {
+     type object-identifier {
+       pattern '\d*(\.\d*){1,127}';
+     }
+     description
+      "This type represents object-identifiers restricted to 128
+       sub-identifiers.
+
+       In the value set and its semantics, this type is equivalent
+       to the OBJECT IDENTIFIER type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   /*** collection of date and time related types ***/
+
+   typedef date-and-time {
+     type string {
+       pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
+             + '(Z|[\+\-]\d{2}:\d{2})';
+     }
+     description
+      "The date-and-time type is a profile of the ISO 8601
+       standard for representation of dates and times using the
+       Gregorian calendar.  The profile is defined by the
+       date-time production in Section 5.6 of RFC 3339.
+
+       The date-and-time type is compatible with the dateTime XML
+       schema type with the following notable exceptions:
+
+       (a) The date-and-time type does not allow negative years.
+
+       (b) The date-and-time time-offset -00:00 indicates an unknown
+           time zone (see RFC 3339) while -00:00 and +00:00 and Z all
+           represent the same time zone in dateTime.
+
+       (c) The canonical format (see below) of data-and-time values
+           differs from the canonical format used by the dateTime XML
+           schema type, which requires all times to be in UTC using the
+           time-offset 'Z'.
+
+       This type is not equivalent to the DateAndTime textual
+       convention of the SMIv2 since RFC 3339 uses a different
+       separator between full-date and full-time and provides
+       higher resolution of time-secfrac.
+
+       The canonical format for date-and-time values with a known time
+       zone uses a numeric time zone offset that is calculated using
+       the device's configured known offset to UTC time.  A change of
+       the device's offset to UTC time will cause date-and-time values
+       to change accordingly.  Such changes might happen periodically
+       in case a server follows automatically daylight saving time
+       (DST) time zone offset changes.  The canonical format for
+       date-and-time values with an unknown time zone (usually referring
+       to the notion of local time) uses the time-offset -00:00.";
+     reference
+      "RFC 3339: Date and Time on the Internet: Timestamps
+       RFC 2579: Textual Conventions for SMIv2
+       XSD-TYPES: XML Schema Part 2: Datatypes Second Edition";
+   }
+
+   typedef timeticks {
+     type uint32;
+     description
+      "The timeticks type represents a non-negative integer that
+       represents the time, modulo 2^32 (4294967296 decimal), in
+       hundredths of a second between two epochs.  When a schema
+       node is defined that uses this type, the description of
+       the schema node identifies both of the reference epochs.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeTicks type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef timestamp {
+     type yang:timeticks;
+     description
+      "The timestamp type represents the value of an associated
+       timeticks schema node at which a specific occurrence happened.
+       The specific occurrence must be defined in the description
+       of any schema node defined using this type.  When the specific
+       occurrence occurred prior to the last time the associated
+       timeticks attribute was zero, then the timestamp value is
+       zero.  Note that this requires all timestamp values to be
+       reset to zero when the value of the associated timeticks
+       attribute reaches 497+ days and wraps around to zero.
+
+       The associated timeticks schema node must be specified
+       in the description of any schema node using this type.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeStamp textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of generic address types ***/
+
+   typedef phys-address {
+     type string {
+       pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
+     }
+     description
+      "Represents media- or physical-level addresses represented
+       as a sequence octets, each octet represented by two hexadecimal
+       numbers.  Octets are separated by colons.  The canonical
+       representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the PhysAddress textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   typedef mac-address {
+     type string {
+       pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
+     }
+     description
+      "The mac-address type represents an IEEE 802 MAC address.
+       The canonical representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the MacAddress textual convention of the SMIv2.";
+     reference
+      "IEEE 802: IEEE Standard for Local and Metropolitan Area
+                 Networks: Overview and Architecture
+       RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of XML specific types ***/
+
+   typedef xpath1.0 {
+     type string;
+     description
+      "This type represents an XPATH 1.0 expression.
+
+       When a schema node is defined that uses this type, the
+       description of the schema node MUST specify the XPath
+       context in which the XPath expression is evaluated.";
+     reference
+      "XPATH: XML Path Language (XPath) Version 1.0";
+   }
+
+ }
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/import-module.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/import-module.yang
new file mode 100644 (file)
index 0000000..4c29dcb
--- /dev/null
@@ -0,0 +1,12 @@
+module import-module {
+    yang-version 1;
+    namespace "yang:test:import";
+    prefix "i";
+
+    revision "2013-11-19" {
+    }
+
+
+    container imp-cont {}
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/main-module.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/main-module.yang
new file mode 100644 (file)
index 0000000..c20b20f
--- /dev/null
@@ -0,0 +1,25 @@
+module main-module {
+
+    namespace "yang:test:main";
+    prefix m;
+
+    include submodule1 {
+        revision-date 2014-04-02;
+    }
+
+    include submodule2 {
+        revision-date 2014-06-30;
+    }
+
+    include submodule3 {
+        revision-date 2014-06-30;
+    }
+
+    import import-module {
+        prefix n;
+    }
+
+    revision 2014-06-30 {
+    }
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/submodule1.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/submodule1.yang
new file mode 100644 (file)
index 0000000..02e1478
--- /dev/null
@@ -0,0 +1,17 @@
+submodule submodule1 {
+
+    belongs-to main-module {
+        prefix m;
+    }
+
+    revision 2014-04-02 {
+    }
+
+
+    typedef sub1-type {
+        type string;
+    }
+
+    container sub1-cont {}
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/submodule2.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/submodule2.yang
new file mode 100644 (file)
index 0000000..fcdf5e1
--- /dev/null
@@ -0,0 +1,21 @@
+submodule submodule2 {
+
+    belongs-to main-module {
+        prefix m;
+    }
+
+    include submodule1 {
+        revision-date 2014-04-02;
+    }
+
+    revision 2014-06-30 {
+    }
+
+
+    grouping sub2-gr {
+        leaf sub2-leaf {
+            type string;
+        }
+    }
+
+}
diff --git a/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/submodule3.yang b/code-generator/maven-sal-api-gen-plugin/src/test/resources/yang-module-info/submodule3.yang
new file mode 100644 (file)
index 0000000..2602814
--- /dev/null
@@ -0,0 +1,13 @@
+submodule submodule3 {
+
+    belongs-to main-module {
+        prefix m;
+    }
+
+    revision 2014-06-30 {
+    }
+
+
+    container sub3-cont {}
+
+}
diff --git a/code-generator/pom.xml b/code-generator/pom.xml
new file mode 100644 (file)
index 0000000..2ce6df0
--- /dev/null
@@ -0,0 +1,37 @@
+<?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>yangtools-parent</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+        <relativePath>../common/parent</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>binding-generator</artifactId>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <modules>
+        <module>binding-model-api</module>
+        <module>binding-generator-api</module>
+        <module>binding-generator-spi</module>
+        <module>binding-generator-util</module>
+        <module>binding-generator-impl</module>
+        <module>binding-java-api-generator</module>
+        <module>binding-type-provider</module>
+        <module>maven-sal-api-gen-plugin</module>
+        <module>binding-test-model</module>
+        <module>binding-data-codec</module>
+        <module>binding-parent</module>
+    </modules>
+</project>
diff --git a/code-generator/samples/maven-code-gen-sample/pom.xml b/code-generator/samples/maven-code-gen-sample/pom.xml
new file mode 100644 (file)
index 0000000..765ebe2
--- /dev/null
@@ -0,0 +1,64 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>maven-code-gen-sample</artifactId>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <version>${yang.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+                                    </codeGeneratorClass>
+                                    <outputBaseDir>
+                                        target/generated-sources/sal
+                                    </outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>false</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>maven-sal-api-gen-plugin</artifactId>
+                        <type>jar</type>
+                    </dependency>
+                </dependencies>
+            </plugin>
+        </plugins>
+       </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/java/Example.java b/code-generator/samples/maven-code-gen-sample/src/main/java/Example.java
new file mode 100644 (file)
index 0000000..b15c0e5
--- /dev/null
@@ -0,0 +1,34 @@
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.controller.network.rev2013520.ControllerNetworkData;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.controller.network.rev2013520.Network;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.controller.network.rev2013520.network.topologies.Topology;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.controller.network.rev2013520.network.topologies.topology.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.controller.openflow.rev2013520.Node1;
+
+/*
+ * 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
+ */
+
+public class Example {
+    
+
+    
+    void udpateTopology(ControllerNetworkData network) {
+        List<Topology> topologies = network.getNetwork().getTopologies().getTopology();
+        for (Topology topology : topologies) {
+            List<Node> nodes = topology.getNodes().getNode();
+            for (Node node : nodes) {
+                
+                
+                Node1 ofNode = node.getAugmentation(Node1.class);
+                ofNode.getDatapathId();
+            }
+        }
+        
+    }
+}
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/augment-monitoring@2013-07-01.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/augment-monitoring@2013-07-01.yang
new file mode 100644 (file)
index 0000000..a9c357a
--- /dev/null
@@ -0,0 +1,88 @@
+module augment-monitoring {
+    yang-version 1;
+    namespace "urn:ietf:params:xml:ns:yang:augment-monitoring";
+    prefix "amon";
+
+    import choice-monitoring { prefix nm; }
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision "2013-07-01" {
+            reference "NO REF";
+    }
+
+    augment "/nm:netconf-state/nm:datastores/nm:datastore/nm:locks/nm:lock-type" {
+        case autonomous-lock {
+            container autonomous-def {
+                leaf lock-id {
+                    type int32;
+                }
+
+                leaf lock-time {
+                    type uint32;
+                }
+            }
+        }
+
+        case anonymous-lock {
+            leaf lock-time {
+                type uint32;
+            }
+        }
+
+        leaf leaf-aug-case {
+            type string;
+        }
+    }
+
+    augment "/nm:netconf-state/nm:datastores/nm:datastore/nm:locks/nm:lock-type/nm:partial-lock" {
+        choice aug-case-by-choice {
+            case foo {
+                leaf foo {
+                    type string;
+                }
+            }
+
+            case bar {
+                leaf bar {
+                    type boolean;
+                }
+            }
+        }
+    }
+
+    augment "/nm:netconf-state/nm:datastores/nm:datastore" {
+        choice storage-format {
+            case _xml {
+                container _xml-def {
+                    leaf file-name {
+                        type string;
+                    }
+                }
+            }
+
+            case yang {
+                leaf yang-file-name {
+                    type string;
+                }
+            }
+
+            case unknown-files {
+                list files {
+                    key "file-name";
+
+                    leaf file-name {
+                        type string;
+                    }
+
+                    container file-data {
+                        leaf utf8-data {
+                            type string;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/bit_and_union_in_leaf.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/bit_and_union_in_leaf.yang
new file mode 100644 (file)
index 0000000..2a7c366
--- /dev/null
@@ -0,0 +1,55 @@
+module bit-and-union-in-leaf {
+
+    namespace "urn:bit:union:in:leaf";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-06-26 {
+        
+    }
+
+    typedef union-typedef {
+        type union {
+            type string {
+                pattern "[a-g]";
+            }
+            type int16;
+        }
+    }
+
+    typedef union-typedef2 {
+        type union {
+            type string; 
+            type int16;
+        }
+    }    
+
+    container parent-container {
+        leaf bit-leaf {
+            type bits {
+                bit first-bit;
+                bit second-bit;
+                bit third-bit;
+            }
+        }
+
+        leaf union-leaf {
+            type union {
+                type int32;
+                type string {
+                    pattern "[a-z]";
+                }
+                type string {
+                    pattern "[0-9]*"
+                }
+                type string {
+                    pattern "[a-d]*";
+                    pattern "[0-5]*";
+                }
+                type uint8;
+            }
+        }
+    }
+}
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/choice-monitoring@2013-07-01.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/choice-monitoring@2013-07-01.yang
new file mode 100644 (file)
index 0000000..2362783
--- /dev/null
@@ -0,0 +1,129 @@
+module choice-monitoring {
+  yang-version 1;
+  namespace "urn:ietf:params:xml:ns:yang:choice-monitoring";
+  prefix "ncm";
+
+  import ietf-yang-types { prefix yang; }
+  import ietf-inet-types { prefix inet; }
+
+  organization "OPEN DAYLIGHT";
+  contact "http://www.opendaylight.org/";
+
+  description
+    "Test model for testing of resolving choice, case nodes and generation types from them.";
+
+  revision 2013-07-01 {
+
+  }
+
+  typedef tls-fingerprint-type {
+    type string {
+      pattern '([0-9a-fA-F]){2}(:([0-9a-fA-F]){2})*';
+    }
+  }
+
+  typedef netconf-datastore-type {
+    type enumeration {
+      enum running;
+      enum candidate;
+      enum startup;
+    }
+  }
+
+  container netconf-state {
+    config false;
+
+    container datastores {
+      list datastore {
+        key name;
+
+        leaf name {
+          type netconf-datastore-type;
+        }
+        container locks {
+          choice lock-type {
+
+            case global-lock {
+                container global-lock {
+
+                leaf locked-by-session {
+                  type uint32;
+                  mandatory true;
+                }
+
+                leaf locked-time {
+                  type yang:date-and-time;
+                  mandatory true;
+                }
+
+                container capabilities {
+                  leaf-list capability {
+                      type inet:uri;
+                  }
+                }
+              }
+            }
+
+            case partial-lock {
+              list partial-lock {
+                  key lock-id;
+
+                  leaf lock-id {
+                    type uint32;
+                  }
+                  leaf-list select {
+                    type yang:xpath1.0;
+                    min-elements 1;
+                  }
+                  leaf-list locked-node {
+                    type string;
+                  }
+              }
+            }
+
+            case fingerprint {
+              choice algorithm-and-hash {
+                  mandatory true;
+                  case md5 {
+                    leaf md5 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+
+                  case sha1 {
+                    leaf sha1 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+                  
+                  case sha224 {
+                    leaf sha224 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+                  
+                  case sha256 {
+                    leaf sha256 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+                  
+                  case sha384 {
+                    leaf sha384 {
+                      type tls-fingerprint-type;
+                    }
+                  }                
+                  
+                  case sha512 {
+                    leaf sha512 {
+                      type tls-fingerprint-type;
+                    }
+                  }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network-ne.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network-ne.yang
new file mode 100644 (file)
index 0000000..ca8507f
--- /dev/null
@@ -0,0 +1,54 @@
+module controller-openflow-ne {
+    yang-version 1;
+    namespace "urn:opendaylight:controller:network:openflow";
+    prefix "of";
+    
+    import controller-network {
+        prefix cn;
+    }
+    import ietf-inet-types { prefix "inet"; }
+    
+    revision 2013-06-07 {
+       description "Initial demo";
+    }
+
+    augment "/cn:network/cn:network-elements/cn:network-element" {
+
+        container flow-tables2 {
+            list flow-table {
+
+                key "id";
+                leaf id {
+                    type int32;
+                }
+
+                container flows {
+                    list flow {
+                        key "name";
+                        leaf name {
+                            type string;
+                        }
+                        container match {
+                            leaf input-port {
+                                type cn:tp-ref;
+                            }
+                            leaf nl-src {
+                                type inet:ipv4-address;
+                            }
+                            leaf nl-dst {
+                                type inet:ipv4-address;
+                            }
+                        }
+                        container actions {
+                            list action {
+                                leaf type {
+                                    type string;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-network.yang
new file mode 100644 (file)
index 0000000..ce0b6b0
--- /dev/null
@@ -0,0 +1,167 @@
+module controller-network {
+    yang-version 1;
+    namespace "urn:opendaylight:controller:network";
+    prefix "topos";
+    
+    import ietf-inet-types { prefix "inet"; }
+    
+    revision 2013-05-20 {
+       description "Initial demo";
+    }
+
+    typedef topology-id {
+        type string;
+    }
+
+    typedef node-id {
+        type string;
+    }
+
+    typedef link-id {
+        type string;
+    }
+
+    typedef tp-id {
+        type string;
+        description "identifier for termination points on a port";
+    }
+
+    typedef tp-ref {
+        type leafref {
+            path "/network/topologies/topology/nodes/node/termination-points/termination-point/tp-id";
+        }
+    }
+    typedef topology-ref {
+        type leafref {
+            path "/network/topologies/topology/topology-id";
+        }
+        description "This type is used for leafs that reference topology identifier instance.";
+        // currently not used
+    }
+
+    typedef node-ref {
+        type leafref {
+            path "/network/topologies/topology/nodes/node/node-id";
+        }
+        description "This type is used for leafs that reference a node instance.";
+    }
+
+    typedef link-ref {
+        type leafref {
+            path "/network/topologies/topology/links/link/link-id";
+        }
+        description "This type is used for leafs that reference a link instance.";
+        // currently not used
+    }
+    
+    typedef network-element-ref {
+        type leafref {
+            path "/network/network-elements/network-element/element-id";
+        }
+    }
+
+    typedef element-id {
+        type string;
+    }
+    
+    container network {
+        container topologies {
+            list topology {
+                description "
+                    This is the model of abstract topology which contains only Network
+                    Nodes and Network Links. Each topology MUST be identified by
+                    unique topology-id for reason that the store could contain many
+                    topologies.
+                ";
+                key "topology-id";
+                leaf topology-id {
+                    type topology-id; 
+                    description "
+                        It is presumed that datastore will contain many topologies. To
+                        distinguish between topologies it is vital to have UNIQUE
+                        topology identifier.
+                    ";
+                }
+
+                container types {
+                    description "
+                        The container for definition of topology types.
+                        The augmenting modules should add empty optional leaf 
+                        to this container to signalize topology type.";
+                }
+
+                container nodes {
+                    list node {
+                        description "The list of network nodes defined for topology.";
+
+                        key "node-id";
+                        leaf node-id {
+                            type node-id;
+                            description "The Topology identifier of network-node.";
+                        }
+
+                        leaf supporting-ne {
+                            type network-element-ref;
+                        }
+                        
+                        container termination-points {
+                            list termination-point {
+                                key "tp-id";
+                                leaf tp-id {
+                                    type tp-id;
+                                }
+                            }
+                        }
+                    }
+                }
+        
+                container links {
+                    list link {
+                        description "
+                            The Network Link which is defined by Local (Source) and
+                            Remote (Destination) Network Nodes. Every link MUST be
+                            defined either by identifier and his local and remote
+                            Network Nodes (in real applications it is common that many
+                            links are originated from one node and end up in same
+                            remote node). To ensure that we would always know to
+                            distinguish between links, every link SHOULD have
+                            identifier.
+                        ";
+                        key "link-id";
+        
+                        leaf link-id {
+                            type link-id;
+                        }
+                        container source { 
+                            leaf source-node {
+                                type node-ref;
+                                description "Source node identifier.";
+                            }
+                            leaf source-tp {
+                                type tp-ref;
+                            }
+                        }
+                        container destination { 
+                            leaf dest-node {
+                                type node-ref;
+                                description "Destination node identifier.";
+                            }
+                            leaf dest-tp {
+                                type tp-ref;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        container network-elements {
+            config true;
+            list network-element {
+                key "element-id";
+                leaf element-id {
+                    type element-id;
+                }
+            }
+        }
+    }
+}
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-openflow-ipv6.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-openflow-ipv6.yang
new file mode 100644 (file)
index 0000000..eec1909
--- /dev/null
@@ -0,0 +1,17 @@
+module controller-openflow-ipv6 {
+       yang-version 1;
+       namespace "urn:opendaylight:controller:network:openflow:ipv6";
+       prefix "of6";
+
+       import controller-network {
+               prefix cn;
+       }
+       import ietf-inet-types { prefix "inet"; }
+       import controller-openflow-ne {prefix "of";}
+
+       revision 2013-06-07 {
+          description "Initial demo";
+       }
+}
+
+       
\ No newline at end of file
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-openflow.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/controller-openflow.yang
new file mode 100644 (file)
index 0000000..83a0459
--- /dev/null
@@ -0,0 +1,74 @@
+module controller-openflow {
+
+    namespace "urn:opendaylight:controller:openflow";
+    prefix "of";
+    import controller-network {prefix cn;}
+
+    revision 2013-05-20 {
+       description "Initial demo";
+    }
+
+    typedef datapath-id {
+        type string {
+            length 16;
+        }
+    }
+
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:types" {
+        leaf openflow {type string;}
+    }
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:links/cn:link/cn:source" {
+        when "../../../cn:types/of:openflow";
+
+        leaf logical-port {
+            type int32;
+        }
+    }
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:links/cn:link/cn:destination" {
+        when "../../../cn:types/of:openflow";
+
+        leaf logical-port {
+            type int32;
+        }
+    }
+
+    augment "/cn:network/cn:topologies/cn:topology/cn:nodes/cn:node" {
+        when "../../../cn:types/of:openflow";
+        leaf datapath-id {
+            type datapath-id;
+        }
+    }
+    
+    augment "/cn:network/cn:network-elements/cn:network-element" {
+        leaf datapath-id {
+            type datapath-id;
+        }
+
+        container ports {
+            list port {
+                key "logical-port-id";
+                
+                leaf logical-port-id {
+                    type int32;
+                }
+
+                // Should be replaced with ref to interface
+                leaf physical-name {
+                    type string;
+                }
+            }
+        }
+        container flow-tables {
+            list flow-table {
+                key "flow-table-id";
+                leaf flow-table-id {
+                    type string;
+                }
+
+            }
+        }
+    }
+}
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/demo-topology.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/demo-topology.yang
new file mode 100644 (file)
index 0000000..4fef1cd
--- /dev/null
@@ -0,0 +1,121 @@
+module demo-topology {
+       yang-version 1;
+    namespace "urn:model.1demo-275topology.4.5.my";
+    prefix "tp";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    description "
+               This module contains the definitions of elements that creates network 
+               topology i.e. definition of network nodes and links. This module is
+               not designed to be used solely for network representation. This module
+               SHOULD be used as base module in defining the network topology.
+       ";
+
+    revision "2013-02-08"{
+               reference " WILL BE DEFINED LATER";
+       }
+
+       container topology {
+        description "
+                       This is the model of abstract topology which contains only Network
+                       Nodes and Network Links. Each topology MUST be identified by
+                       unique topology-id for reason that the store could contain many
+                       topologies.
+               ";
+
+        leaf topology-id {
+            type string;
+            description "
+                               It is presumed that datastore will contain many topologies. To
+                               distinguish between topologies it is vital to have UNIQUE
+                               topology identifier.
+                       ";
+        }
+
+        container network-nodes {
+               list network-node {
+                   description "The list of network nodes defined for topology.";
+
+                       key "node-id";
+
+                       leaf node-id {
+                               type string;
+                               description "The Topology identifier of network-node.";
+                       }
+                
+                list network-interface {
+                    key "interface-id";
+                    
+                    leaf interface-id {
+                        type uint8;
+                    }
+                    
+                    leaf interface-address {
+                        type string;
+                    }
+                }
+                
+                   container node-attributes {
+                                       description "
+                                               Additional attributes that can Network Node contains.
+                                       ";
+
+                                       leaf geo-latitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
+
+                                       leaf geo-longitude {
+                                               type decimal64 {
+                                                       fraction-digits 2;
+                                               }
+                                               config true;
+                                       }
+                               }
+               }
+        }
+        
+        container network-links {
+               list network-link {
+                   description "
+                                       The Network Link which is defined by Local (Source) and
+                                       Remote (Destination) Network Nodes. Every link MUST be
+                                       defined either by identifier and his local and remote
+                                       Network Nodes (in real applications it is common that many
+                                       links are originated from one node and end up in same
+                                       remote node). To ensure that we would always know to
+                                       distinguish between links, every link SHOULD have
+                                       identifier.
+                               ";
+                       key "link-id";
+
+                       leaf link-id {
+                               type string;
+                               description "";
+                       }
+
+                   container source {
+                                       leaf node-id {
+                                               type string;
+                                               description "Source node identifier.";
+                                       }
+                               }
+
+                               container destination {
+                                       leaf node-id {
+                                               type string;
+                                               description "Destination node identifier.";
+                                       }
+                               }
+
+                               container link-attributes {
+                                       description "Aditional attributes that can Network Link contains.";
+                               }
+                   }
+        }
+    }
+}
\ No newline at end of file
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/ietf-inet-types@2010-09-24.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/ietf-inet-types@2010-09-24.yang
new file mode 100644 (file)
index 0000000..de20feb
--- /dev/null
@@ -0,0 +1,418 @@
+ module ietf-inet-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+   prefix "inet";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types for Internet addresses and related things.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of protocol field related types ***/
+
+   typedef ip-version {
+     type enumeration {
+       enum unknown {
+         value "0";
+         description
+          "An unknown or unspecified version of the Internet protocol.";
+       }
+       enum ipv4 {
+         value "1";
+         description
+          "The IPv4 protocol as defined in RFC 791.";
+       }
+       enum ipv6 {
+         value "2";
+         description
+          "The IPv6 protocol as defined in RFC 2460.";
+       }
+     }
+     description
+      "This value represents the version of the IP protocol.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetVersion textual convention of the SMIv2.";
+     reference
+      "RFC  791: Internet Protocol
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   typedef dscp {
+     type uint8 {
+       range "0..63";
+     }
+     description
+      "The dscp type represents a Differentiated Services Code-Point
+       that may be used for marking packets in a traffic stream.
+
+       In the value set and its semantics, this type is equivalent
+       to the Dscp textual convention of the SMIv2.";
+     reference
+      "RFC 3289: Management Information Base for the Differentiated
+                 Services Architecture
+       RFC 2474: Definition of the Differentiated Services Field
+                 (DS Field) in the IPv4 and IPv6 Headers
+       RFC 2780: IANA Allocation Guidelines For Values In
+                 the Internet Protocol and Related Headers";
+   }
+
+   typedef ipv6-flow-label {
+     type uint32 {
+       range "0..1048575";
+     }
+     description
+      "The flow-label type represents flow identifier or Flow Label
+       in an IPv6 packet header that may be used to discriminate
+       traffic flows.
+
+       In the value set and its semantics, this type is equivalent
+       to the IPv6FlowLabel textual convention of the SMIv2.";
+     reference
+      "RFC 3595: Textual Conventions for IPv6 Flow Label
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+   }
+
+   typedef port-number {
+     type uint16 {
+       range "0..65535";
+     }
+     description
+      "The port-number type represents a 16-bit port number of an
+       Internet transport layer protocol such as UDP, TCP, DCCP, or
+       SCTP.  Port numbers are assigned by IANA.  A current list of
+       all assignments is available from <http://www.iana.org/>.
+
+       Note that the port number value zero is reserved by IANA.  In
+       situations where the value zero does not make sense, it can
+       be excluded by subtyping the port-number type.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetPortNumber textual convention of the SMIv2.";
+     reference
+      "RFC  768: User Datagram Protocol
+       RFC  793: Transmission Control Protocol
+       RFC 4960: Stream Control Transmission Protocol
+       RFC 4340: Datagram Congestion Control Protocol (DCCP)
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of autonomous system related types ***/
+
+   typedef as-number {
+     type uint32;
+     description
+      "The as-number type represents autonomous system numbers
+       which identify an Autonomous System (AS).  An AS is a set
+       of routers under a single technical administration, using
+       an interior gateway protocol and common metrics to route
+       packets within the AS, and using an exterior gateway
+       protocol to route packets to other ASs'.  IANA maintains
+       the AS number space and has delegated large parts to the
+       regional registries.
+
+       Autonomous system numbers were originally limited to 16
+       bits.  BGP extensions have enlarged the autonomous system
+       number space to 32 bits.  This type therefore uses an uint32
+       base type without a range restriction in order to support
+       a larger autonomous system number space.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetAutonomousSystemNumber textual convention of
+       the SMIv2.";
+     reference
+      "RFC 1930: Guidelines for creation, selection, and registration
+                 of an Autonomous System (AS)
+       RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+       RFC 4893: BGP Support for Four-octet AS Number Space
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of IP address and hostname related types ***/
+
+   typedef ip-address {
+     type union {
+       type inet:ipv4-address;
+       type inet:ipv6-address;
+     }
+     description
+      "The ip-address type represents an IP address and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-address {
+     type string {
+       pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '(%[\p{N}\p{L}]+)?';
+     }
+     description
+       "The ipv4-address type represents an IPv4 address in
+        dotted-quad notation.  The IPv4 address may include a zone
+        index, separated by a % sign.
+
+        The zone index is used to disambiguate identical address
+        values.  For link-local addresses, the zone index will
+        typically be the interface index number or the name of an
+        interface.  If the zone index is not present, the default
+        zone of the device will be used.
+
+        The canonical format for the zone index is the numerical
+        format";
+   }
+
+   typedef ipv6-address {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(%[\p{N}\p{L}]+)?';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(%.+)?';
+     }
+     description
+      "The ipv6-address type represents an IPv6 address in full,
+       mixed, shortened, and shortened-mixed notation.  The IPv6
+       address may include a zone index, separated by a % sign.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format of IPv6 addresses uses the compressed
+       format described in RFC 4291, Section 2.2, item 2 with the
+       following additional rules: the :: substitution must be
+       applied to the longest sequence of all-zero 16-bit chunks
+       in an IPv6 address.  If there is a tie, the first sequence
+       of all-zero 16-bit chunks is replaced by ::.  Single
+       all-zero 16-bit chunks are not compressed.  The canonical
+       format uses lowercase characters and leading zeros are
+       not allowed.  The canonical format for the zone index is
+       the numerical format as described in RFC 4007, Section
+       11.2.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture
+       RFC 4007: IPv6 Scoped Address Architecture
+       RFC 5952: A Recommendation for IPv6 Address Text Representation";
+   }
+
+   typedef ip-prefix {
+     type union {
+       type inet:ipv4-prefix;
+       type inet:ipv6-prefix;
+     }
+     description
+      "The ip-prefix type represents an IP prefix and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-prefix {
+     type string {
+       pattern
+          '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+        +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+        + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+     }
+     description
+      "The ipv4-prefix type represents an IPv4 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal to 32.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The canonical format of an IPv4 prefix has all bits of
+       the IPv4 address set to zero that are not part of the
+       IPv4 prefix.";
+   }
+
+   typedef ipv6-prefix {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(/.+)';
+     }
+     description
+      "The ipv6-prefix type represents an IPv6 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal 128.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The IPv6 address should have all bits that do not belong
+       to the prefix set to zero.
+
+       The canonical format of an IPv6 prefix has all bits of
+       the IPv6 address set to zero that are not part of the
+       IPv6 prefix.  Furthermore, IPv6 address is represented
+       in the compressed format described in RFC 4291, Section
+       2.2, item 2 with the following additional rules: the ::
+       substitution must be applied to the longest sequence of
+       all-zero 16-bit chunks in an IPv6 address.  If there is
+       a tie, the first sequence of all-zero 16-bit chunks is
+       replaced by ::.  Single all-zero 16-bit chunks are not
+       compressed.  The canonical format uses lowercase
+       characters and leading zeros are not allowed.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture";
+   }
+
+   /*** collection of domain name and URI types ***/
+
+   typedef domain-name {
+     type string {
+       pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+            +  '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+            +  '|\.';
+       length "1..253";
+     }
+     description
+      "The domain-name type represents a DNS domain name.  The
+       name SHOULD be fully qualified whenever possible.
+
+       Internet domain names are only loosely specified.  Section
+       3.5 of RFC 1034 recommends a syntax (modified in Section
+       2.1 of RFC 1123).  The pattern above is intended to allow
+       for current practice in domain name use, and some possible
+       future expansion.  It is designed to hold various types of
+       domain names, including names used for A or AAAA records
+       (host names) and other records, such as SRV records.  Note
+       that Internet host names have a stricter syntax (described
+       in RFC 952) than the DNS recommendations in RFCs 1034 and
+       1123, and that systems that want to store host names in
+       schema nodes using the domain-name type are recommended to
+       adhere to this stricter standard to ensure interoperability.
+
+       The encoding of DNS names in the DNS protocol is limited
+       to 255 characters.  Since the encoding consists of labels
+       prefixed by a length bytes and there is a trailing NULL
+       byte, only 253 characters can appear in the textual dotted
+       notation.
+
+       The description clause of schema nodes using the domain-name
+       type MUST describe when and how these names are resolved to
+       IP addresses.  Note that the resolution of a domain-name value
+       may require to query multiple DNS records (e.g., A for IPv4
+       and AAAA for IPv6).  The order of the resolution process and
+       which DNS record takes precedence can either be defined
+       explicitely or it may depend on the configuration of the
+       resolver.
+
+       Domain-name values use the US-ASCII encoding.  Their canonical
+       format uses lowercase US-ASCII characters.  Internationalized
+       domain names MUST be encoded in punycode as described in RFC
+       3492";
+     reference
+      "RFC  952: DoD Internet Host Table Specification
+       RFC 1034: Domain Names - Concepts and Facilities
+       RFC 1123: Requirements for Internet Hosts -- Application
+                 and Support
+       RFC 2782: A DNS RR for specifying the location of services
+                 (DNS SRV)
+       RFC 3492: Punycode: A Bootstring encoding of Unicode for
+                 Internationalized Domain Names in Applications
+                 (IDNA)
+       RFC 5891: Internationalizing Domain Names in Applications
+                 (IDNA): Protocol";
+   }
+
+   typedef host {
+     type union {
+       type inet:ip-address;
+       type inet:domain-name;
+     }
+     description
+      "The host type represents either an IP address or a DNS
+       domain name.";
+   }
+
+   typedef uri {
+     type string;
+     description
+      "The uri type represents a Uniform Resource Identifier
+       (URI) as defined by STD 66.
+
+       Objects using the uri type MUST be in US-ASCII encoding,
+       and MUST be normalized as described by RFC 3986 Sections
+       6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+       percent-encoding is removed, and all case-insensitive
+       characters are set to lowercase except for hexadecimal
+       digits, which are normalized to uppercase as described in
+       Section 6.2.2.1.
+
+       The purpose of this normalization is to help provide
+       unique URIs.  Note that this normalization is not
+       sufficient to provide uniqueness.  Two URIs that are
+       textually distinct after this normalization may still be
+       equivalent.
+
+       Objects using the uri type may restrict the schemes that
+       they permit.  For example, 'data:' and 'urn:' schemes
+       might not be appropriate.
+
+       A zero-length URI is not a valid URI.  This can be used to
+       express 'URI absent' where required.
+
+       In the value set and its semantics, this type is equivalent
+       to the Uri SMIv2 textual convention defined in RFC 5017.";
+     reference
+      "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+       RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                 Group: Uniform Resource Identifiers (URIs), URLs,
+                 and Uniform Resource Names (URNs): Clarifications
+                 and Recommendations
+       RFC 5017: MIB Textual Conventions for Uniform Resource
+                 Identifiers (URIs)";
+   }
+
+ }
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/ietf-yang-types@2010-09-24.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/ietf-yang-types@2010-09-24.yang
new file mode 100644 (file)
index 0000000..51d9f8b
--- /dev/null
@@ -0,0 +1,396 @@
+ module ietf-yang-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types";
+   prefix "yang";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of counter and gauge types ***/
+
+   typedef counter32 {
+     type uint32;
+     description
+      "The counter32 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter32 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter32 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter32.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter32 {
+     type yang:counter32;
+     default "0";
+     description
+      "The zero-based-counter32 type represents a counter32
+       that has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter32 textual convention of the SMIv2.";
+     reference
+       "RFC 4502: Remote Network Monitoring Management Information
+                  Base Version 2";
+   }
+
+   typedef counter64 {
+     type uint64;
+     description
+      "The counter64 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter64 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter64 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter64.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter64 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter64 {
+     type yang:counter64;
+     default "0";
+     description
+      "The zero-based-counter64 type represents a counter64 that
+       has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter64 textual convention of the SMIv2.";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   typedef gauge32 {
+     type uint32;
+     description
+      "The gauge32 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^32-1 (4294967295 decimal), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge32 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge32 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the Gauge32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef gauge64 {
+     type uint64;
+     description
+      "The gauge64 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^64-1 (18446744073709551615), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge64 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge64 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the CounterBasedGauge64 SMIv2 textual convention defined
+       in RFC 2856";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   /*** collection of identifier related types ***/
+
+   typedef object-identifier {
+     type string {
+       pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))'
+             + '(\.(0|([1-9]\d*)))*';
+     }
+     description
+      "The object-identifier type represents administratively
+       assigned names in a registration-hierarchical-name tree.
+
+       Values of this type are denoted as a sequence of numerical
+       non-negative sub-identifier values.  Each sub-identifier
+       value MUST NOT exceed 2^32-1 (4294967295).  Sub-identifiers
+       are separated by single dots and without any intermediate
+       whitespace.
+
+       The ASN.1 standard restricts the value space of the first
+       sub-identifier to 0, 1, or 2.  Furthermore, the value space
+       of the second sub-identifier is restricted to the range
+       0 to 39 if the first sub-identifier is 0 or 1.  Finally,
+       the ASN.1 standard requires that an object identifier
+       has always at least two sub-identifier.  The pattern
+       captures these restrictions.
+
+       Although the number of sub-identifiers is not limited,
+       module designers should realize that there may be
+       implementations that stick with the SMIv2 limit of 128
+       sub-identifiers.
+
+       This type is a superset of the SMIv2 OBJECT IDENTIFIER type
+       since it is not restricted to 128 sub-identifiers.  Hence,
+       this type SHOULD NOT be used to represent the SMIv2 OBJECT
+       IDENTIFIER type, the object-identifier-128 type SHOULD be
+       used instead.";
+     reference
+      "ISO9834-1: Information technology -- Open Systems
+       Interconnection -- Procedures for the operation of OSI
+       Registration Authorities: General procedures and top
+       arcs of the ASN.1 Object Identifier tree";
+   }
+
+
+
+
+   typedef object-identifier-128 {
+     type object-identifier {
+       pattern '\d*(\.\d*){1,127}';
+     }
+     description
+      "This type represents object-identifiers restricted to 128
+       sub-identifiers.
+
+       In the value set and its semantics, this type is equivalent
+       to the OBJECT IDENTIFIER type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   /*** collection of date and time related types ***/
+
+   typedef date-and-time {
+     type string {
+       pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
+             + '(Z|[\+\-]\d{2}:\d{2})';
+     }
+     description
+      "The date-and-time type is a profile of the ISO 8601
+       standard for representation of dates and times using the
+       Gregorian calendar.  The profile is defined by the
+       date-time production in Section 5.6 of RFC 3339.
+
+       The date-and-time type is compatible with the dateTime XML
+       schema type with the following notable exceptions:
+
+       (a) The date-and-time type does not allow negative years.
+
+       (b) The date-and-time time-offset -00:00 indicates an unknown
+           time zone (see RFC 3339) while -00:00 and +00:00 and Z all
+           represent the same time zone in dateTime.
+
+       (c) The canonical format (see below) of data-and-time values
+           differs from the canonical format used by the dateTime XML
+           schema type, which requires all times to be in UTC using the
+           time-offset 'Z'.
+
+       This type is not equivalent to the DateAndTime textual
+       convention of the SMIv2 since RFC 3339 uses a different
+       separator between full-date and full-time and provides
+       higher resolution of time-secfrac.
+
+       The canonical format for date-and-time values with a known time
+       zone uses a numeric time zone offset that is calculated using
+       the device's configured known offset to UTC time.  A change of
+       the device's offset to UTC time will cause date-and-time values
+       to change accordingly.  Such changes might happen periodically
+       in case a server follows automatically daylight saving time
+       (DST) time zone offset changes.  The canonical format for
+       date-and-time values with an unknown time zone (usually referring
+       to the notion of local time) uses the time-offset -00:00.";
+     reference
+      "RFC 3339: Date and Time on the Internet: Timestamps
+       RFC 2579: Textual Conventions for SMIv2
+       XSD-TYPES: XML Schema Part 2: Datatypes Second Edition";
+   }
+
+   typedef timeticks {
+     type uint32;
+     description
+      "The timeticks type represents a non-negative integer that
+       represents the time, modulo 2^32 (4294967296 decimal), in
+       hundredths of a second between two epochs.  When a schema
+       node is defined that uses this type, the description of
+       the schema node identifies both of the reference epochs.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeTicks type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef timestamp {
+     type yang:timeticks;
+     description
+      "The timestamp type represents the value of an associated
+       timeticks schema node at which a specific occurrence happened.
+       The specific occurrence must be defined in the description
+       of any schema node defined using this type.  When the specific
+       occurrence occurred prior to the last time the associated
+       timeticks attribute was zero, then the timestamp value is
+       zero.  Note that this requires all timestamp values to be
+       reset to zero when the value of the associated timeticks
+       attribute reaches 497+ days and wraps around to zero.
+
+       The associated timeticks schema node must be specified
+       in the description of any schema node using this type.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeStamp textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of generic address types ***/
+
+   typedef phys-address {
+     type string {
+       pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
+     }
+     description
+      "Represents media- or physical-level addresses represented
+       as a sequence octets, each octet represented by two hexadecimal
+       numbers.  Octets are separated by colons.  The canonical
+       representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the PhysAddress textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   typedef mac-address {
+     type string {
+       pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
+     }
+     description
+      "The mac-address type represents an IEEE 802 MAC address.
+       The canonical representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the MacAddress textual convention of the SMIv2.";
+     reference
+      "IEEE 802: IEEE Standard for Local and Metropolitan Area
+                 Networks: Overview and Architecture
+       RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of XML specific types ***/
+
+   typedef xpath1.0 {
+     type string;
+     description
+      "This type represents an XPATH 1.0 expression.
+
+       When a schema node is defined that uses this type, the
+       description of the schema node MUST specify the XPath
+       context in which the XPath expression is evaluated.";
+     reference
+      "XPATH: XML Path Language (XPath) Version 1.0";
+   }
+
+ }
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/simple-string-demo.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/simple-string-demo.yang
new file mode 100644 (file)
index 0000000..c0f87dd
--- /dev/null
@@ -0,0 +1,22 @@
+module simple-string-demo {
+
+    namespace "urn:simple:string:demo";
+    prefix "sbd";
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-06-18 {
+        
+    }
+
+    typedef typedef-string {
+        type string {
+            length "40";
+            pattern "[0-9A-F]\.*";
+            pattern "[B-D]*";
+            pattern "[4-7]*";
+        }
+    }
+
+}
diff --git a/code-generator/samples/maven-code-gen-sample/src/main/yang/typedef_of_typedef.yang b/code-generator/samples/maven-code-gen-sample/src/main/yang/typedef_of_typedef.yang
new file mode 100644 (file)
index 0000000..b8558b3
--- /dev/null
@@ -0,0 +1,91 @@
+module typedef_typedef {
+    
+    namespace "urn:typedef:typedef";
+    prefix "sbd";
+
+    import ietf-inet-types {
+        prefix "inet";
+        revision-date 2010-09-24;
+    }    
+
+
+    organization "OPEN DAYLIGHT";
+    contact "http://www.opendaylight.org/";
+
+    revision 2013-07-09 {
+        
+    }
+
+
+    typedef typedef-from-import {
+       type inet:ipv4-address;
+    }
+
+
+   typedef byte-type {
+        type bits {
+            bit first-bit {
+                position 10;
+            }
+            bit second-bit {
+                position 20;
+            }
+         }
+    }    
+    
+    
+  typedef typedef-enum-fruit {
+    type enumeration {
+      enum "apple" {
+        value 1;
+        description "gold";
+      }
+      enum "pear" {
+        value 2;
+      }
+    }
+  }    
+    
+    typedef simple-typedef1 {
+        type uint8;
+    }
+    
+    typedef simple-typedef2 {
+        type simple-typedef1;
+    }
+    
+    typedef simple-typedef3 {
+        type simple-typedef2;
+    }
+    
+    typedef simple-typedef4 {
+        type simple-typedef3;
+    }
+    
+    typedef simple-typedef1-1 {
+        type uint16;
+    }
+
+    
+    typedef union-typedef {
+        type union {
+            type simple-typedef1;
+            type simple-typedef4;
+            type byte-type;
+            type typedef-enum-fruit;
+        }
+    }
+    
+    typedef extended-typedef-union {
+        type union-typedef;
+    }
+    
+    
+    typedef extended-typedef-simple {
+        type simple-typedef1;
+    }
+    
+    typedef extended-typedef-enum {
+        type typedef-enum-fruit;
+    }
+}
\ No newline at end of file
diff --git a/code-generator/samples/modeling-sample/pom.xml b/code-generator/samples/modeling-sample/pom.xml
new file mode 100644 (file)
index 0000000..ef68f03
--- /dev/null
@@ -0,0 +1,67 @@
+<?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">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>binding-generator</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>modeling-sample</artifactId>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+                                    </codeGeneratorClass>
+                                    <outputBaseDir>
+                                        target/generated-sources/sal
+                                    </outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>false</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>maven-sal-api-gen-plugin</artifactId>
+                        <type>jar</type>
+                    </dependency>
+                </dependencies>
+            </plugin>
+        </plugins>
+          </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/code-generator/samples/modeling-sample/src/main/yang/toaster.yang b/code-generator/samples/modeling-sample/src/main/yang/toaster.yang
new file mode 100644 (file)
index 0000000..fc9b665
--- /dev/null
@@ -0,0 +1,187 @@
+module toaster {
+
+    yang-version 1;
+
+    namespace
+      "http://netconfcentral.org/ns/toaster";
+
+    prefix toast;
+
+    organization "Netconf Central";
+
+    contact
+      "Andy Bierman <andy@netconfcentral.org>";
+
+    description
+      "YANG version of the TOASTER-MIB.";
+
+    revision "2009-11-20" {
+      description
+        "Toaster module in progress.";
+    }
+
+
+    identity toast-type {
+      description
+          "Base for all bread types supported by the toaster.
+           New bread types not listed here nay be added in the 
+           future.";
+    }
+
+    identity white-bread {
+      base toast:toast-type;
+      description "White bread.";
+    }
+
+    identity wheat-bread {
+      base toast-type;
+      description "Wheat bread.";
+    }
+
+    identity wonder-bread {
+      base toast-type;
+      description "Wonder bread.";
+    }
+
+    identity frozen-waffle {
+      base toast-type;
+      description "Frozen waffle.";
+    }
+
+    identity frozen-bagel {
+      base toast-type;
+      description "Frozen bagel.";
+    }
+
+    identity hash-brown {
+      base toast-type;
+      description "Hash browned potatos.";
+    }
+
+    typedef DisplayString {
+      type string;
+      description
+        "YANG version of the SMIv2 DisplayString TEXTUAL-CONVENTION.";
+      reference
+        "RFC 2579, section 2.";
+
+    }
+
+    container toaster {
+      presence
+        "Indicates the toaster service is available";
+      description
+        "Top-level container for all toaster database objects.";
+      leaf toasterManufacturer {
+        type DisplayString;
+        config false;
+        mandatory true;
+        description
+          "The name of the toaster's manufacturer. For instance, 
+                Microsoft Toaster.";
+      }
+
+      leaf toasterModelNumber {
+        type DisplayString;
+        config false;
+        mandatory true;
+        description
+          "The name of the toaster's model. For instance,
+               Radiant Automatic.";
+      }
+
+      leaf toasterStatus {
+        type enumeration {
+          enum "up" {
+            value 1;
+            description
+              "The toaster knob position is up.
+                      No toast is being made now.";
+          }
+          enum "down" {
+            value 2;
+            description
+              "The toaster knob position is down.
+                      Toast is being made now.";
+          }
+        }
+        config false;
+        mandatory true;
+        description
+          "This variable indicates the current state of 
+               the toaster.";
+      }
+    }  // container toaster
+
+    rpc make-toast {
+      description
+        "Make some toast.
+           The toastDone notification will be sent when 
+           the toast is finished.
+           An 'in-use' error will be returned if toast
+           is already being made.
+           A 'resource-denied' error will be returned 
+           if the toaster service is disabled.";
+      input {
+        leaf toasterDoneness {
+          type uint32 {
+            range "1 .. 10";
+          }
+          default '5';
+          description
+            "This variable controls how well-done is the 
+                   ensuing toast. It should be on a scale of 1 to 10.
+                   Toast made at 10 generally is considered unfit 
+                   for human consumption; toast made at 1 is warmed 
+                   lightly.";
+        }
+
+        leaf toasterToastType {
+          type identityref {
+            base toast:toast-type;
+          }
+          default 'wheat-bread';
+          description
+            "This variable informs the toaster of the type of 
+                   material that is being toasted. The toaster 
+                   uses this information, combined with 
+                   toasterDoneness, to compute for how 
+                   long the material must be toasted to achieve 
+                   the required doneness.";
+        }
+      }
+    }  // rpc make-toast
+
+    rpc cancel-toast {
+      description
+        "Stop making toast, if any is being made.
+           A 'resource-denied' error will be returned 
+           if the toaster service is disabled.";
+    }  // rpc cancel-toast
+
+    notification toastDone {
+      description
+        "Indicates that the toast in progress has completed.";
+      leaf toastStatus {
+        type enumeration {
+          enum "done" {
+            value 0;
+            description "The toast is done.";
+          }
+          enum "cancelled" {
+            value 1;
+            description
+              "The toast was cancelled.";
+          }
+          enum "error" {
+            value 2;
+            description
+              "The toaster service was disabled or
+                     the toaster is broken.";
+          }
+        }
+        description
+          "Indicates the final toast status";
+      }
+    }  // notification toastDone
+  }  // module toaster
diff --git a/code-generator/src/site/site.xml b/code-generator/src/site/site.xml
new file mode 100644 (file)
index 0000000..d219e60
--- /dev/null
@@ -0,0 +1,25 @@
+<?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 name="${project.name}">
+
+    <skin>
+        <groupId>org.apache.maven.skins</groupId>
+        <artifactId>maven-fluido-skin</artifactId>
+        <version>1.3.0</version>
+    </skin>
+
+    <body>
+        <menu ref="parent"/>
+        <menu ref="modules"/>
+        <menu ref="reports"/>
+    </body>
+
+</project>
+
diff --git a/model/iana/iana-afn-safi/pom.xml b/model/iana/iana-afn-safi/pom.xml
new file mode 100644 (file)
index 0000000..de82000
--- /dev/null
@@ -0,0 +1,41 @@
+<?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>
+        <artifactId>model-iana</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>iana-afn-safi</artifactId>
+    <version>2013.07.04.8-SNAPSHOT</version>
+
+    <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/model/iana/iana-afn-safi/src/main/yang/iana-afn-safi@2013-07-04.yang b/model/iana/iana-afn-safi/src/main/yang/iana-afn-safi@2013-07-04.yang
new file mode 100644 (file)
index 0000000..c076260
--- /dev/null
@@ -0,0 +1,526 @@
+module iana-afn-safi {
+  namespace "urn:ietf:params:xml:ns:yang:iana-afn-safi";
+  prefix "ianaaf";
+
+  organization
+    "IANA";
+  contact
+    "        Internet Assigned Numbers Authority
+
+     Postal: ICANN
+             4676 Admiralty Way, Suite 330
+             Marina del Rey, CA 90292
+
+     Tel:    +1 310 823 9358
+     E-Mail: iana&iana.org";
+  description
+    "This YANG module provides two typedefs containing YANG
+     definitions for the following IANA-registered enumerations:
+
+     - Address Family Numbers (AFN)
+
+     - Subsequent Address Family Identifiers (SAFI)
+
+     The latest revision of this YANG module can be obtained from the
+     IANA web site.
+
+     Copyright (c) 2012 IETF Trust and the persons identified as
+     authors of the code. All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject to
+     the license terms contained in, the Simplified BSD License set
+     forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see the
+     RFC itself for full legal notices.";
+  // RFC Ed.: replace XXXX with actual RFC number and remove this
+  // note.
+
+  // RFC Ed.: update the date below with the date of RFC publication
+  // and remove this note.
+  revision 2013-07-04 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: IANA Address Family Numbers and
+                 Subsequent Address Family Identifiers YANG Module";
+  }
+
+  typedef address-family {
+    type enumeration {
+      // value 0 is reserved by IANA
+      enum ipV4 {
+        value "1";
+        description
+          "IP version 4";
+      }
+      enum ipV6 {
+        value "2";
+        description
+          "IP version 6";
+      }
+      enum nsap {
+        value "3";
+        description
+          "NSAP";
+      }
+      enum hdlc {
+        value "4";
+        description
+          "HDLC (8-bit multidrop)";
+      }
+      enum bbn1822 {
+        value "5";
+        description
+          "BBN 1822";
+      }
+      enum all802 {
+        value "6";
+        description
+          "802 (includes all 802 media plus Ethernet 'canonical
+           format')";
+      }
+      enum e163 {
+        value "7";
+        description
+          "E.163";
+      }
+      enum e164 {
+        value "8";
+        description
+          "E.164 (SMDS, FrameRelay, ATM)";
+      }
+      enum f69 {
+        value "9";
+        description
+          "F.69 (Telex)";
+      }
+      enum x121 {
+        value "10";
+        description
+          "X.121 (X.25, Frame Relay)";
+      }
+      enum ipx {
+        value "11";
+        description
+          "IPX (Internetwork Packet Exchange)";
+      }
+      enum appletalk {
+        value "12";
+        description
+          "Appletalk";
+      }
+      enum decnetIV {
+        value "13";
+        description
+          "DECnet IV";
+      }
+      enum banyanVines {
+        value "14";
+        description
+          "Banyan Vines";
+      }
+      enum e164withNsap {
+        value "15";
+        description
+          "E.164 with NSAP format subaddress";
+        reference
+          "ATM Forum UNI 3.1";
+      }
+      enum dns {
+        value "16";
+        description
+          "DNS (Domain Name System)";
+      }
+      enum distinguishedName {
+        value "17";
+        description
+          "Distinguished Name (per X.500)";
+      }
+      enum asNumber {
+        value "18";
+        description
+          "Autonomous System Number";
+      }
+      enum xtpOverIpv4 {
+        value "19";
+        description
+          "XTP over IP version 4";
+      }
+      enum xtpOverIpv6 {
+        value "20";
+        description
+          "XTP over IP version 6";
+      }
+      enum xtpNativeModeXTP {
+        value "21";
+        description
+          "XTP native mode XTP";
+      }
+      enum fibreChannelWWPN {
+        value "22";
+        description
+          "Fibre Channel World-Wide Port Name";
+      }
+      enum fibreChannelWWNN {
+        value "23";
+        description
+          "Fibre Channel World-Wide Node Name";
+      }
+      enum gwid {
+        value "24";
+        description
+          "Gateway Identifier";
+      }
+      // FIXME: This one is actually called "afi" in the MIB, but
+      // that must be a mistake.
+      enum l2vpn {
+        value "25";
+        description
+          "AFI for L2VPN information";
+        reference
+          "RFC 4761: Virtual Private LAN Service (VPLS): Using BGP
+           for Auto-Discovery and Signaling
+
+           RFC 6074: Provisioning, Auto-Discovery, and Signaling in
+           Layer 2 Virtual Private Networks (L2VPNs)";
+      }
+      enum mplsTpSectionEndpointIdentifier {
+        value "26";
+        description
+          "MPLS-TP Section Endpoint Identifier";
+        reference
+          "draft-ietf-mpls-gach-adv";
+      }
+      enum mplsTpLspEndpointIdentifier {
+        value "27";
+        description
+          "MPLS-TP LSP Endpoint Identifier";
+        reference
+          "draft-ietf-mpls-gach-adv";
+      }
+      enum mplsTpPseudowireEndpointIdentifier {
+        value "28";
+        description
+          "MPLS-TP Pseudowire Endpoint Identifier";
+        reference
+          "draft-ietf-mpls-gach-adv";
+      }
+      enum eigrpCommonServiceFamily {
+        value "16384";
+        description
+          "EIGRP Common Service Family";
+      }
+      enum eigrpIpv4ServiceFamily {
+        value "16385";
+        description
+          "EIGRP IPv4 Service Family";
+      }
+      enum eigrpIpv6ServiceFamily {
+        value "16386";
+        description
+          "EIGRP IPv6 Service Family";
+      }
+      enum lispCanonicalAddressFormat {
+        value "16387";
+        description
+          "LISP Canonical Address Format (LCAF)";
+      }
+      enum bgpLs {
+        value "16388";
+        description
+          "BGP-LS";
+        reference
+          "draft-ietf-idr-ls-distribution";
+      }
+      enum 48BitMac {
+        value "16389";
+        description
+          "48-bit MAC";
+        reference
+          "draft-eastlake-rfc5342bis";
+      }
+      enum 64BitMac {
+        value "16390";
+        description
+          "64-bit MAC";
+        reference
+          "draft-eastlake-rfc5342bis";
+      }
+      // value 65535 is reserved by IANA
+    }
+    description
+      "This typedef is a YANG enumeration of IANA-registered address
+       family numbers (AFN).";
+    reference
+      "IANA Address Family Numbers registry.
+       <http://www.iana.org/assignments/address-family-numbers>";
+  }
+
+  typedef subsequent-address-family {
+    type enumeration {
+      // value 0 is reserved by IANA
+      enum nlriUnicast {
+        value "1";
+        description
+          "Network Layer Reachability Information used for unicast
+           forwarding";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum nlriMulticast {
+        value "2";
+        description
+          "Network Layer Reachability Information used for multicast
+           forwarding";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      // value 3 is reserved by IANA
+      enum nlriMpls {
+        value "4";
+        description
+          "Network Layer Reachability Information (NLRI) with MPLS
+           Labels";
+        reference
+          "RFC 3107: Carrying Label Information in BGP-4";
+      }
+      enum mcastVpn {
+        value "5";
+        description
+          "MCAST-VPN";
+        reference
+          "RFC 6514: BGP Encodings and Procedures for Multicast in
+           MPLS/BGP IP VPNs";
+      }
+      enum nlriDynamicMsPw {
+        value "6";
+        status "obsolete";
+        description
+          "Network Layer Reachability Information used for Dynamic
+           Placement of Multi-Segment Pseudowires (TEMPORARY -
+           Expires 2008-08-23)";
+        reference
+          "draft-ietf-pwe3-dynamic-ms-pw: Dynamic Placement of Multi
+           Segment Pseudowires";
+      }
+      enum encapsulation {
+        value "7";
+        description
+          "Encapsulation SAFI";
+        reference
+          "RFC 5512: The BGP Encapsulation Subsequent Address Family
+           Identifier (SAFI) and the BGP Tunnel Encapsulation
+           Attribute";
+      }
+      enum tunnel {
+        value "64";
+        status "obsolete";
+        description
+          "Tunnel SAFI";
+        reference
+          "draft-nalawade-kapoor-tunnel-safi: BGP Tunnel SAFI";
+      }
+      enum vpls {
+        value "65";
+        description
+          "Virtual Private LAN Service (VPLS)";
+        reference
+          "RFC 4761: Virtual Private LAN Service (VPLS): Using BGP
+           for Auto-Discovery and Signaling
+
+           RFC 6074: Provisioning, Auto-Discovery, and Signaling in
+           Layer 2 Virtual Private Networks (L2VPNs)";
+      }
+      enum bgpMdt {
+        value "66";
+        description
+          "BGP MDT SAFI";
+        reference
+          "RFC 6037: Cisco Systems' Solution for Multicast in
+           BGP/MPLS IP VPNs";
+      }
+      enum bgp4over6 {
+        value "67";
+        description
+          "BGP 4over6 SAFI";
+        reference
+          "RFC 5747: 4over6 Transit Solution Using IP Encapsulation
+           and MP-BGP Extensions";
+      }
+      enum bgp6over4 {
+        value "68";
+        description
+          "BGP 6over4 SAFI";
+      }
+      enum l1VpnAutoDiscovery {
+        value "69";
+        description
+          "Layer-1 VPN auto-discovery information";
+        reference
+          "RFC 5195: BGP-Based Auto-Discovery for Layer-1 VPNs";
+      }
+      enum mplsVpn {
+        value "128";
+        description
+          "MPLS-labeled VPN address";
+        reference
+          "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs)";
+      }
+      enum multicastBgpMplsVpn {
+        value "129";
+        description
+          "Multicast for BGP/MPLS IP Virtual Private Networks
+           (VPNs)";
+        reference
+          "RFC 6513: Multicast in MPLS/BGP IP VPNs
+
+           RFC 6514: BGP Encodings and Procedures for Multicast in
+           MPLS/BGP IP VPNs";
+      }
+      // values 130-131 are reserved by IANA
+      enum routeTargetConstraints {
+        value "132";
+        description
+          "Route Target constraints";
+        reference
+          "RFC 4684: Constrained Route Distribution for Border
+           Gateway Protocol/MultiProtocol Label Switching (BGP/MPLS)
+           Internet Protocol (IP) Virtual Private Networks (VPNs)";
+      }
+      enum ipv4DissFlow {
+        value "133";
+        description
+          "IPv4 dissemination of flow specification rules";
+        reference
+          "RFC 5575: Dissemination of Flow Specification Rules";
+      }
+      enum vpnv4DissFlow {
+        value "134";
+        description
+          "VPNv4 dissemination of flow specification rules";
+        reference
+          "RFC 5575: Dissemination of Flow Specification Rules";
+      }
+      // values 135-139 are reserved by IANA
+      enum vpnAutoDiscovery {
+        value "140";
+        status "obsolete";
+        description
+          "VPN auto-discovery";
+        reference
+          "draft-ietf-l3vpn-bgpvpn-auto: Using BGP as an
+           Auto-Discovery Mechanism for VR-based Layer-3 VPNs";
+      }
+      // values 141-240 are reserved by IANA
+      enum private241 {
+        value "241";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private242 {
+        value "242";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private243 {
+        value "243";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private244 {
+        value "244";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private245 {
+        value "245";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private246 {
+        value "246";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private247 {
+        value "247";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private248 {
+        value "248";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private249 {
+        value "249";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private250 {
+        value "250";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private251 {
+        value "251";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private252 {
+        value "252";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private253 {
+        value "253";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      enum private254 {
+        value "254";
+        description
+          "Reserved for Private Use";
+        reference
+          "RFC 4760: Multiprotocol Extensions for BGP-4";
+      }
+      // value 255 is reserved by IANA
+    }
+    description
+      "This typedef is a YANG enumeration of IANA-registered
+       subsequent address family identifiers (SAFI).";
+    reference
+      "IANA SAFI Values registry.
+       <http://www.iana.org/assignments/safi-namespace>";
+  }
+}
diff --git a/model/iana/iana-if-type-2014-05-08/pom.xml b/model/iana/iana-if-type-2014-05-08/pom.xml
new file mode 100644 (file)
index 0000000..3815db3
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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>
+        <artifactId>model-iana</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>iana-if-type-2014-05-08</artifactId>
+    <version>2014.05.08.8-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-interfaces</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/model/iana/iana-if-type-2014-05-08/src/main/yang/iana-if-type@2014-05-08.yang b/model/iana/iana-if-type-2014-05-08/src/main/yang/iana-if-type@2014-05-08.yang
new file mode 100644 (file)
index 0000000..5dd8219
--- /dev/null
@@ -0,0 +1,1547 @@
+module iana-if-type {
+  namespace "urn:ietf:params:xml:ns:yang:iana-if-type";
+  prefix ianaift;
+
+  import ietf-interfaces {
+    prefix if;
+  }
+
+  organization "IANA";
+  contact
+    "        Internet Assigned Numbers Authority
+
+     Postal: ICANN
+             4676 Admiralty Way, Suite 330
+             Marina del Rey, CA 90292
+
+     Tel:    +1 310 823 9358
+     <mailto:iana@iana.org>";
+  description
+    "This YANG module defines YANG identities for IANA-registered
+     interface types.
+
+     This YANG module is maintained by IANA and reflects the
+     'ifType definitions' registry.
+
+     The latest revision of this YANG module can be obtained from
+     the IANA web site.
+
+     Requests for new values should be made to IANA via
+     email (iana@iana.org).
+
+     Copyright (c) 2014 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     The initial version of this YANG module is part of RFC 7224;
+     see the RFC itself for full legal notices.";
+    reference
+      "IANA 'ifType definitions' registry.
+       <http://www.iana.org/assignments/smi-numbers>";
+
+  revision 2014-05-08 {
+    description
+      "Initial revision.";
+    reference
+      "RFC 7224: IANA Interface Type YANG Module";
+  }
+
+  identity iana-interface-type {
+    base if:interface-type;
+    description
+      "This identity is used as a base for all interface types
+       defined in the 'ifType definitions' registry.";
+  }
+
+
+
+
+
+
+  identity other {
+    base iana-interface-type;
+  }
+  identity regular1822 {
+    base iana-interface-type;
+  }
+  identity hdh1822 {
+    base iana-interface-type;
+  }
+  identity ddnX25 {
+    base iana-interface-type;
+  }
+  identity rfc877x25 {
+    base iana-interface-type;
+    reference
+      "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer";
+  }
+  identity ethernetCsmacd {
+    base iana-interface-type;
+    description
+      "For all Ethernet-like interfaces, regardless of speed,
+       as per RFC 3635.";
+    reference
+      "RFC 3635 - Definitions of Managed Objects for the
+                  Ethernet-like Interface Types";
+  }
+  identity iso88023Csmacd {
+    base iana-interface-type;
+    status deprecated;
+    description
+      "Deprecated via RFC 3635.
+       Use ethernetCsmacd(6) instead.";
+    reference
+      "RFC 3635 - Definitions of Managed Objects for the
+                  Ethernet-like Interface Types";
+  }
+  identity iso88024TokenBus {
+    base iana-interface-type;
+  }
+  identity iso88025TokenRing {
+    base iana-interface-type;
+  }
+  identity iso88026Man {
+    base iana-interface-type;
+  }
+  identity starLan {
+    base iana-interface-type;
+    status deprecated;
+    description
+      "Deprecated via RFC 3635.
+       Use ethernetCsmacd(6) instead.";
+    reference
+      "RFC 3635 - Definitions of Managed Objects for the
+                  Ethernet-like Interface Types";
+  }
+  identity proteon10Mbit {
+    base iana-interface-type;
+  }
+  identity proteon80Mbit {
+    base iana-interface-type;
+  }
+  identity hyperchannel {
+    base iana-interface-type;
+  }
+  identity fddi {
+    base iana-interface-type;
+    reference
+      "RFC 1512 - FDDI Management Information Base";
+  }
+  identity lapb {
+    base iana-interface-type;
+    reference
+      "RFC 1381 - SNMP MIB Extension for X.25 LAPB";
+  }
+  identity sdlc {
+    base iana-interface-type;
+  }
+  identity ds1 {
+    base iana-interface-type;
+    description
+      "DS1-MIB.";
+    reference
+      "RFC 4805 - Definitions of Managed Objects for the
+                  DS1, J1, E1, DS2, and E2 Interface Types";
+  }
+  identity e1 {
+    base iana-interface-type;
+    status obsolete;
+    description
+      "Obsolete; see DS1-MIB.";
+    reference
+      "RFC 4805 - Definitions of Managed Objects for the
+                  DS1, J1, E1, DS2, and E2 Interface Types";
+  }
+
+
+  identity basicISDN {
+    base iana-interface-type;
+    description
+      "No longer used.  See also RFC 2127.";
+  }
+  identity primaryISDN {
+    base iana-interface-type;
+    description
+      "No longer used.  See also RFC 2127.";
+  }
+  identity propPointToPointSerial {
+    base iana-interface-type;
+    description
+      "Proprietary serial.";
+  }
+  identity ppp {
+    base iana-interface-type;
+  }
+  identity softwareLoopback {
+    base iana-interface-type;
+  }
+  identity eon {
+    base iana-interface-type;
+    description
+      "CLNP over IP.";
+  }
+  identity ethernet3Mbit {
+    base iana-interface-type;
+  }
+  identity nsip {
+    base iana-interface-type;
+    description
+      "XNS over IP.";
+  }
+  identity slip {
+    base iana-interface-type;
+    description
+      "Generic SLIP.";
+  }
+  identity ultra {
+    base iana-interface-type;
+    description
+      "Ultra Technologies.";
+  }
+  identity ds3 {
+    base iana-interface-type;
+    description
+      "DS3-MIB.";
+    reference
+      "RFC 3896 - Definitions of Managed Objects for the
+                  DS3/E3 Interface Type";
+  }
+  identity sip {
+    base iana-interface-type;
+    description
+      "SMDS, coffee.";
+    reference
+      "RFC 1694 - Definitions of Managed Objects for SMDS
+                  Interfaces using SMIv2";
+  }
+  identity frameRelay {
+    base iana-interface-type;
+    description
+      "DTE only.";
+    reference
+      "RFC 2115 - Management Information Base for Frame Relay
+                  DTEs Using SMIv2";
+  }
+  identity rs232 {
+    base iana-interface-type;
+    reference
+      "RFC 1659 - Definitions of Managed Objects for RS-232-like
+                  Hardware Devices using SMIv2";
+  }
+  identity para {
+    base iana-interface-type;
+    description
+      "Parallel-port.";
+    reference
+      "RFC 1660 - Definitions of Managed Objects for
+                  Parallel-printer-like Hardware Devices using
+                  SMIv2";
+  }
+  identity arcnet {
+    base iana-interface-type;
+    description
+      "ARCnet.";
+  }
+  identity arcnetPlus {
+    base iana-interface-type;
+    description
+      "ARCnet Plus.";
+  }
+
+
+
+  identity atm {
+    base iana-interface-type;
+    description
+      "ATM cells.";
+  }
+  identity miox25 {
+    base iana-interface-type;
+    reference
+      "RFC 1461 - SNMP MIB extension for Multiprotocol
+                  Interconnect over X.25";
+  }
+  identity sonet {
+    base iana-interface-type;
+    description
+      "SONET or SDH.";
+  }
+  identity x25ple {
+    base iana-interface-type;
+    reference
+      "RFC 2127 - ISDN Management Information Base using SMIv2";
+  }
+  identity iso88022llc {
+    base iana-interface-type;
+  }
+  identity localTalk {
+    base iana-interface-type;
+  }
+  identity smdsDxi {
+    base iana-interface-type;
+  }
+  identity frameRelayService {
+    base iana-interface-type;
+    description
+      "FRNETSERV-MIB.";
+    reference
+      "RFC 2954 - Definitions of Managed Objects for Frame
+                  Relay Service";
+  }
+  identity v35 {
+    base iana-interface-type;
+  }
+  identity hssi {
+    base iana-interface-type;
+  }
+  identity hippi {
+    base iana-interface-type;
+  }
+
+  identity modem {
+    base iana-interface-type;
+    description
+      "Generic modem.";
+  }
+  identity aal5 {
+    base iana-interface-type;
+    description
+      "AAL5 over ATM.";
+  }
+  identity sonetPath {
+    base iana-interface-type;
+  }
+  identity sonetVT {
+    base iana-interface-type;
+  }
+  identity smdsIcip {
+    base iana-interface-type;
+    description
+      "SMDS InterCarrier Interface.";
+  }
+  identity propVirtual {
+    base iana-interface-type;
+    description
+      "Proprietary virtual/internal.";
+    reference
+      "RFC 2863 - The Interfaces Group MIB";
+  }
+  identity propMultiplexor {
+    base iana-interface-type;
+    description
+      "Proprietary multiplexing.";
+    reference
+      "RFC 2863 - The Interfaces Group MIB";
+  }
+  identity ieee80212 {
+    base iana-interface-type;
+    description
+      "100BaseVG.";
+  }
+  identity fibreChannel {
+    base iana-interface-type;
+    description
+      "Fibre Channel.";
+  }
+
+
+
+  identity hippiInterface {
+    base iana-interface-type;
+    description
+      "HIPPI interfaces.";
+  }
+  identity frameRelayInterconnect {
+    base iana-interface-type;
+    status obsolete;
+    description
+      "Obsolete; use either
+       frameRelay(32) or frameRelayService(44).";
+  }
+  identity aflane8023 {
+    base iana-interface-type;
+    description
+      "ATM Emulated LAN for 802.3.";
+  }
+  identity aflane8025 {
+    base iana-interface-type;
+    description
+      "ATM Emulated LAN for 802.5.";
+  }
+  identity cctEmul {
+    base iana-interface-type;
+    description
+      "ATM Emulated circuit.";
+  }
+  identity fastEther {
+    base iana-interface-type;
+    status deprecated;
+    description
+      "Obsoleted via RFC 3635.
+       ethernetCsmacd(6) should be used instead.";
+    reference
+      "RFC 3635 - Definitions of Managed Objects for the
+                  Ethernet-like Interface Types";
+  }
+  identity isdn {
+    base iana-interface-type;
+    description
+      "ISDN and X.25.";
+    reference
+      "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN
+                  in the Packet Mode";
+  }
+
+
+
+  identity v11 {
+    base iana-interface-type;
+    description
+      "CCITT V.11/X.21.";
+  }
+  identity v36 {
+    base iana-interface-type;
+    description
+      "CCITT V.36.";
+  }
+  identity g703at64k {
+    base iana-interface-type;
+    description
+      "CCITT G703 at 64Kbps.";
+  }
+  identity g703at2mb {
+    base iana-interface-type;
+    status obsolete;
+    description
+      "Obsolete; see DS1-MIB.";
+  }
+  identity qllc {
+    base iana-interface-type;
+    description
+      "SNA QLLC.";
+  }
+  identity fastEtherFX {
+    base iana-interface-type;
+    status deprecated;
+    description
+      "Obsoleted via RFC 3635.
+       ethernetCsmacd(6) should be used instead.";
+    reference
+      "RFC 3635 - Definitions of Managed Objects for the
+                  Ethernet-like Interface Types";
+  }
+  identity channel {
+    base iana-interface-type;
+    description
+      "Channel.";
+  }
+  identity ieee80211 {
+    base iana-interface-type;
+    description
+      "Radio spread spectrum.";
+  }
+  identity ibm370parChan {
+    base iana-interface-type;
+    description
+      "IBM System 360/370 OEMI Channel.";
+  }
+  identity escon {
+    base iana-interface-type;
+    description
+      "IBM Enterprise Systems Connection.";
+  }
+  identity dlsw {
+    base iana-interface-type;
+    description
+      "Data Link Switching.";
+  }
+  identity isdns {
+    base iana-interface-type;
+    description
+      "ISDN S/T interface.";
+  }
+  identity isdnu {
+    base iana-interface-type;
+    description
+      "ISDN U interface.";
+  }
+  identity lapd {
+    base iana-interface-type;
+    description
+      "Link Access Protocol D.";
+  }
+  identity ipSwitch {
+    base iana-interface-type;
+    description
+      "IP Switching Objects.";
+  }
+  identity rsrb {
+    base iana-interface-type;
+    description
+      "Remote Source Route Bridging.";
+  }
+  identity atmLogical {
+    base iana-interface-type;
+    description
+      "ATM Logical Port.";
+    reference
+      "RFC 3606 - Definitions of Supplemental Managed Objects
+                  for ATM Interface";
+  }
+  identity ds0 {
+    base iana-interface-type;
+    description
+      "Digital Signal Level 0.";
+    reference
+      "RFC 2494 - Definitions of Managed Objects for the DS0
+                  and DS0 Bundle Interface Type";
+  }
+  identity ds0Bundle {
+    base iana-interface-type;
+    description
+      "Group of ds0s on the same ds1.";
+    reference
+      "RFC 2494 - Definitions of Managed Objects for the DS0
+                  and DS0 Bundle Interface Type";
+  }
+  identity bsc {
+    base iana-interface-type;
+    description
+      "Bisynchronous Protocol.";
+  }
+  identity async {
+    base iana-interface-type;
+    description
+      "Asynchronous Protocol.";
+  }
+  identity cnr {
+    base iana-interface-type;
+    description
+      "Combat Net Radio.";
+  }
+  identity iso88025Dtr {
+    base iana-interface-type;
+    description
+      "ISO 802.5r DTR.";
+  }
+  identity eplrs {
+    base iana-interface-type;
+    description
+      "Ext Pos Loc Report Sys.";
+  }
+  identity arap {
+    base iana-interface-type;
+    description
+      "Appletalk Remote Access Protocol.";
+  }
+  identity propCnls {
+    base iana-interface-type;
+    description
+      "Proprietary Connectionless Protocol.";
+  }
+  identity hostPad {
+    base iana-interface-type;
+    description
+      "CCITT-ITU X.29 PAD Protocol.";
+  }
+  identity termPad {
+    base iana-interface-type;
+    description
+      "CCITT-ITU X.3 PAD Facility.";
+  }
+  identity frameRelayMPI {
+    base iana-interface-type;
+    description
+      "Multiproto Interconnect over FR.";
+  }
+  identity x213 {
+    base iana-interface-type;
+    description
+      "CCITT-ITU X213.";
+  }
+  identity adsl {
+    base iana-interface-type;
+    description
+      "Asymmetric Digital Subscriber Loop.";
+  }
+  identity radsl {
+    base iana-interface-type;
+    description
+      "Rate-Adapt. Digital Subscriber Loop.";
+  }
+  identity sdsl {
+    base iana-interface-type;
+    description
+      "Symmetric Digital Subscriber Loop.";
+  }
+  identity vdsl {
+    base iana-interface-type;
+    description
+      "Very H-Speed Digital Subscrib. Loop.";
+  }
+  identity iso88025CRFPInt {
+    base iana-interface-type;
+    description
+      "ISO 802.5 CRFP.";
+  }
+  identity myrinet {
+    base iana-interface-type;
+    description
+      "Myricom Myrinet.";
+  }
+  identity voiceEM {
+    base iana-interface-type;
+    description
+      "Voice recEive and transMit.";
+  }
+  identity voiceFXO {
+    base iana-interface-type;
+    description
+      "Voice Foreign Exchange Office.";
+  }
+  identity voiceFXS {
+    base iana-interface-type;
+    description
+      "Voice Foreign Exchange Station.";
+  }
+  identity voiceEncap {
+    base iana-interface-type;
+    description
+      "Voice encapsulation.";
+  }
+  identity voiceOverIp {
+    base iana-interface-type;
+    description
+      "Voice over IP encapsulation.";
+  }
+  identity atmDxi {
+    base iana-interface-type;
+    description
+      "ATM DXI.";
+  }
+  identity atmFuni {
+    base iana-interface-type;
+    description
+      "ATM FUNI.";
+  }
+  identity atmIma {
+    base iana-interface-type;
+    description
+      "ATM IMA.";
+  }
+  identity pppMultilinkBundle {
+    base iana-interface-type;
+    description
+      "PPP Multilink Bundle.";
+  }
+  identity ipOverCdlc {
+    base iana-interface-type;
+    description
+      "IBM ipOverCdlc.";
+  }
+  identity ipOverClaw {
+    base iana-interface-type;
+    description
+      "IBM Common Link Access to Workstn.";
+  }
+  identity stackToStack {
+    base iana-interface-type;
+    description
+      "IBM stackToStack.";
+  }
+  identity virtualIpAddress {
+    base iana-interface-type;
+    description
+      "IBM VIPA.";
+  }
+  identity mpc {
+    base iana-interface-type;
+    description
+      "IBM multi-protocol channel support.";
+  }
+  identity ipOverAtm {
+    base iana-interface-type;
+    description
+      "IBM ipOverAtm.";
+    reference
+      "RFC 2320 - Definitions of Managed Objects for Classical IP
+                  and ARP Over ATM Using SMIv2 (IPOA-MIB)";
+  }
+  identity iso88025Fiber {
+    base iana-interface-type;
+    description
+      "ISO 802.5j Fiber Token Ring.";
+  }
+  identity tdlc {
+    base iana-interface-type;
+    description
+      "IBM twinaxial data link control.";
+  }
+  identity gigabitEthernet {
+    base iana-interface-type;
+    status deprecated;
+
+
+    description
+      "Obsoleted via RFC 3635.
+       ethernetCsmacd(6) should be used instead.";
+    reference
+      "RFC 3635 - Definitions of Managed Objects for the
+                  Ethernet-like Interface Types";
+  }
+  identity hdlc {
+    base iana-interface-type;
+    description
+      "HDLC.";
+  }
+  identity lapf {
+    base iana-interface-type;
+    description
+      "LAP F.";
+  }
+  identity v37 {
+    base iana-interface-type;
+    description
+      "V.37.";
+  }
+  identity x25mlp {
+    base iana-interface-type;
+    description
+      "Multi-Link Protocol.";
+  }
+  identity x25huntGroup {
+    base iana-interface-type;
+    description
+      "X25 Hunt Group.";
+  }
+  identity transpHdlc {
+    base iana-interface-type;
+    description
+      "Transp HDLC.";
+  }
+  identity interleave {
+    base iana-interface-type;
+    description
+      "Interleave channel.";
+  }
+  identity fast {
+    base iana-interface-type;
+    description
+      "Fast channel.";
+  }
+
+  identity ip {
+    base iana-interface-type;
+    description
+      "IP (for APPN HPR in IP networks).";
+  }
+  identity docsCableMaclayer {
+    base iana-interface-type;
+    description
+      "CATV Mac Layer.";
+  }
+  identity docsCableDownstream {
+    base iana-interface-type;
+    description
+      "CATV Downstream interface.";
+  }
+  identity docsCableUpstream {
+    base iana-interface-type;
+    description
+      "CATV Upstream interface.";
+  }
+  identity a12MppSwitch {
+    base iana-interface-type;
+    description
+      "Avalon Parallel Processor.";
+  }
+  identity tunnel {
+    base iana-interface-type;
+    description
+      "Encapsulation interface.";
+  }
+  identity coffee {
+    base iana-interface-type;
+    description
+      "Coffee pot.";
+    reference
+      "RFC 2325 - Coffee MIB";
+  }
+  identity ces {
+    base iana-interface-type;
+    description
+      "Circuit Emulation Service.";
+  }
+  identity atmSubInterface {
+    base iana-interface-type;
+    description
+      "ATM Sub Interface.";
+  }
+
+  identity l2vlan {
+    base iana-interface-type;
+    description
+      "Layer 2 Virtual LAN using 802.1Q.";
+  }
+  identity l3ipvlan {
+    base iana-interface-type;
+    description
+      "Layer 3 Virtual LAN using IP.";
+  }
+  identity l3ipxvlan {
+    base iana-interface-type;
+    description
+      "Layer 3 Virtual LAN using IPX.";
+  }
+  identity digitalPowerline {
+    base iana-interface-type;
+    description
+      "IP over Power Lines.";
+  }
+  identity mediaMailOverIp {
+    base iana-interface-type;
+    description
+      "Multimedia Mail over IP.";
+  }
+  identity dtm {
+    base iana-interface-type;
+    description
+      "Dynamic synchronous Transfer Mode.";
+  }
+  identity dcn {
+    base iana-interface-type;
+    description
+      "Data Communications Network.";
+  }
+  identity ipForward {
+    base iana-interface-type;
+    description
+      "IP Forwarding Interface.";
+  }
+  identity msdsl {
+    base iana-interface-type;
+    description
+      "Multi-rate Symmetric DSL.";
+  }
+  identity ieee1394 {
+    base iana-interface-type;
+
+    description
+      "IEEE1394 High Performance Serial Bus.";
+  }
+  identity if-gsn {
+    base iana-interface-type;
+    description
+      "HIPPI-6400.";
+  }
+  identity dvbRccMacLayer {
+    base iana-interface-type;
+    description
+      "DVB-RCC MAC Layer.";
+  }
+  identity dvbRccDownstream {
+    base iana-interface-type;
+    description
+      "DVB-RCC Downstream Channel.";
+  }
+  identity dvbRccUpstream {
+    base iana-interface-type;
+    description
+      "DVB-RCC Upstream Channel.";
+  }
+  identity atmVirtual {
+    base iana-interface-type;
+    description
+      "ATM Virtual Interface.";
+  }
+  identity mplsTunnel {
+    base iana-interface-type;
+    description
+      "MPLS Tunnel Virtual Interface.";
+  }
+  identity srp {
+    base iana-interface-type;
+    description
+      "Spatial Reuse Protocol.";
+  }
+  identity voiceOverAtm {
+    base iana-interface-type;
+    description
+      "Voice over ATM.";
+  }
+  identity voiceOverFrameRelay {
+    base iana-interface-type;
+    description
+      "Voice Over Frame Relay.";
+  }
+  identity idsl {
+    base iana-interface-type;
+    description
+      "Digital Subscriber Loop over ISDN.";
+  }
+  identity compositeLink {
+    base iana-interface-type;
+    description
+      "Avici Composite Link Interface.";
+  }
+  identity ss7SigLink {
+    base iana-interface-type;
+    description
+      "SS7 Signaling Link.";
+  }
+  identity propWirelessP2P {
+    base iana-interface-type;
+    description
+      "Prop. P2P wireless interface.";
+  }
+  identity frForward {
+    base iana-interface-type;
+    description
+      "Frame Forward Interface.";
+  }
+  identity rfc1483 {
+    base iana-interface-type;
+    description
+      "Multiprotocol over ATM AAL5.";
+    reference
+      "RFC 1483 - Multiprotocol Encapsulation over ATM
+                  Adaptation Layer 5";
+  }
+  identity usb {
+    base iana-interface-type;
+    description
+      "USB Interface.";
+  }
+  identity ieee8023adLag {
+    base iana-interface-type;
+    description
+      "IEEE 802.3ad Link Aggregate.";
+  }
+  identity bgppolicyaccounting {
+    base iana-interface-type;
+    description
+      "BGP Policy Accounting.";
+  }
+  identity frf16MfrBundle {
+    base iana-interface-type;
+    description
+      "FRF.16 Multilink Frame Relay.";
+  }
+  identity h323Gatekeeper {
+    base iana-interface-type;
+    description
+      "H323 Gatekeeper.";
+  }
+  identity h323Proxy {
+    base iana-interface-type;
+    description
+      "H323 Voice and Video Proxy.";
+  }
+  identity mpls {
+    base iana-interface-type;
+    description
+      "MPLS.";
+  }
+  identity mfSigLink {
+    base iana-interface-type;
+    description
+      "Multi-frequency signaling link.";
+  }
+  identity hdsl2 {
+    base iana-interface-type;
+    description
+      "High Bit-Rate DSL - 2nd generation.";
+  }
+  identity shdsl {
+    base iana-interface-type;
+    description
+      "Multirate HDSL2.";
+  }
+  identity ds1FDL {
+    base iana-interface-type;
+    description
+      "Facility Data Link (4Kbps) on a DS1.";
+  }
+  identity pos {
+    base iana-interface-type;
+    description
+      "Packet over SONET/SDH Interface.";
+  }
+
+
+
+  identity dvbAsiIn {
+    base iana-interface-type;
+    description
+      "DVB-ASI Input.";
+  }
+  identity dvbAsiOut {
+    base iana-interface-type;
+    description
+      "DVB-ASI Output.";
+  }
+  identity plc {
+    base iana-interface-type;
+    description
+      "Power Line Communications.";
+  }
+  identity nfas {
+    base iana-interface-type;
+    description
+      "Non-Facility Associated Signaling.";
+  }
+  identity tr008 {
+    base iana-interface-type;
+    description
+      "TR008.";
+  }
+  identity gr303RDT {
+    base iana-interface-type;
+    description
+      "Remote Digital Terminal.";
+  }
+  identity gr303IDT {
+    base iana-interface-type;
+    description
+      "Integrated Digital Terminal.";
+  }
+  identity isup {
+    base iana-interface-type;
+    description
+      "ISUP.";
+  }
+  identity propDocsWirelessMaclayer {
+    base iana-interface-type;
+    description
+      "Cisco proprietary Maclayer.";
+  }
+
+
+
+  identity propDocsWirelessDownstream {
+    base iana-interface-type;
+    description
+      "Cisco proprietary Downstream.";
+  }
+  identity propDocsWirelessUpstream {
+    base iana-interface-type;
+    description
+      "Cisco proprietary Upstream.";
+  }
+  identity hiperlan2 {
+    base iana-interface-type;
+    description
+      "HIPERLAN Type 2 Radio Interface.";
+  }
+  identity propBWAp2Mp {
+    base iana-interface-type;
+    description
+      "PropBroadbandWirelessAccesspt2Multipt (use of this value
+       for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f
+       is deprecated, and ieee80216WMAN(237) should be used
+       instead).";
+  }
+  identity sonetOverheadChannel {
+    base iana-interface-type;
+    description
+      "SONET Overhead Channel.";
+  }
+  identity digitalWrapperOverheadChannel {
+    base iana-interface-type;
+    description
+      "Digital Wrapper.";
+  }
+  identity aal2 {
+    base iana-interface-type;
+    description
+      "ATM adaptation layer 2.";
+  }
+  identity radioMAC {
+    base iana-interface-type;
+    description
+      "MAC layer over radio links.";
+  }
+  identity atmRadio {
+    base iana-interface-type;
+    description
+      "ATM over radio links.";
+  }
+  identity imt {
+    base iana-interface-type;
+    description
+      "Inter-Machine Trunks.";
+  }
+  identity mvl {
+    base iana-interface-type;
+    description
+      "Multiple Virtual Lines DSL.";
+  }
+  identity reachDSL {
+    base iana-interface-type;
+    description
+      "Long Reach DSL.";
+  }
+  identity frDlciEndPt {
+    base iana-interface-type;
+    description
+      "Frame Relay DLCI End Point.";
+  }
+  identity atmVciEndPt {
+    base iana-interface-type;
+    description
+      "ATM VCI End Point.";
+  }
+  identity opticalChannel {
+    base iana-interface-type;
+    description
+      "Optical Channel.";
+  }
+  identity opticalTransport {
+    base iana-interface-type;
+    description
+      "Optical Transport.";
+  }
+  identity propAtm {
+    base iana-interface-type;
+    description
+      "Proprietary ATM.";
+  }
+  identity voiceOverCable {
+    base iana-interface-type;
+    description
+      "Voice Over Cable Interface.";
+  }
+
+
+
+  identity infiniband {
+    base iana-interface-type;
+    description
+      "Infiniband.";
+  }
+  identity teLink {
+    base iana-interface-type;
+    description
+      "TE Link.";
+  }
+  identity q2931 {
+    base iana-interface-type;
+    description
+      "Q.2931.";
+  }
+  identity virtualTg {
+    base iana-interface-type;
+    description
+      "Virtual Trunk Group.";
+  }
+  identity sipTg {
+    base iana-interface-type;
+    description
+      "SIP Trunk Group.";
+  }
+  identity sipSig {
+    base iana-interface-type;
+    description
+      "SIP Signaling.";
+  }
+  identity docsCableUpstreamChannel {
+    base iana-interface-type;
+    description
+      "CATV Upstream Channel.";
+  }
+  identity econet {
+    base iana-interface-type;
+    description
+      "Acorn Econet.";
+  }
+  identity pon155 {
+    base iana-interface-type;
+    description
+      "FSAN 155Mb Symetrical PON interface.";
+  }
+
+
+
+  identity pon622 {
+    base iana-interface-type;
+    description
+      "FSAN 622Mb Symetrical PON interface.";
+  }
+  identity bridge {
+    base iana-interface-type;
+    description
+      "Transparent bridge interface.";
+  }
+  identity linegroup {
+    base iana-interface-type;
+    description
+      "Interface common to multiple lines.";
+  }
+  identity voiceEMFGD {
+    base iana-interface-type;
+    description
+      "Voice E&M Feature Group D.";
+  }
+  identity voiceFGDEANA {
+    base iana-interface-type;
+    description
+      "Voice FGD Exchange Access North American.";
+  }
+  identity voiceDID {
+    base iana-interface-type;
+    description
+      "Voice Direct Inward Dialing.";
+  }
+  identity mpegTransport {
+    base iana-interface-type;
+    description
+      "MPEG transport interface.";
+  }
+  identity sixToFour {
+    base iana-interface-type;
+    status deprecated;
+    description
+      "6to4 interface (DEPRECATED).";
+    reference
+      "RFC 4087 - IP Tunnel MIB";
+  }
+  identity gtp {
+    base iana-interface-type;
+    description
+      "GTP (GPRS Tunneling Protocol).";
+  }
+  identity pdnEtherLoop1 {
+    base iana-interface-type;
+    description
+      "Paradyne EtherLoop 1.";
+  }
+  identity pdnEtherLoop2 {
+    base iana-interface-type;
+    description
+      "Paradyne EtherLoop 2.";
+  }
+  identity opticalChannelGroup {
+    base iana-interface-type;
+    description
+      "Optical Channel Group.";
+  }
+  identity homepna {
+    base iana-interface-type;
+    description
+      "HomePNA ITU-T G.989.";
+  }
+  identity gfp {
+    base iana-interface-type;
+    description
+      "Generic Framing Procedure (GFP).";
+  }
+  identity ciscoISLvlan {
+    base iana-interface-type;
+    description
+      "Layer 2 Virtual LAN using Cisco ISL.";
+  }
+  identity actelisMetaLOOP {
+    base iana-interface-type;
+    description
+      "Acteleis proprietary MetaLOOP High Speed Link.";
+  }
+  identity fcipLink {
+    base iana-interface-type;
+    description
+      "FCIP Link.";
+  }
+  identity rpr {
+    base iana-interface-type;
+    description
+      "Resilient Packet Ring Interface Type.";
+  }
+
+
+
+  identity qam {
+    base iana-interface-type;
+    description
+      "RF Qam Interface.";
+  }
+  identity lmp {
+    base iana-interface-type;
+    description
+      "Link Management Protocol.";
+    reference
+      "RFC 4327 - Link Management Protocol (LMP) Management
+                  Information Base (MIB)";
+  }
+  identity cblVectaStar {
+    base iana-interface-type;
+    description
+      "Cambridge Broadband Networks Limited VectaStar.";
+  }
+  identity docsCableMCmtsDownstream {
+    base iana-interface-type;
+    description
+      "CATV Modular CMTS Downstream Interface.";
+  }
+  identity adsl2 {
+    base iana-interface-type;
+    status deprecated;
+    description
+      "Asymmetric Digital Subscriber Loop Version 2
+       (DEPRECATED/OBSOLETED - please use adsl2plus(238)
+       instead).";
+    reference
+      "RFC 4706 - Definitions of Managed Objects for Asymmetric
+                  Digital Subscriber Line 2 (ADSL2)";
+  }
+  identity macSecControlledIF {
+    base iana-interface-type;
+    description
+      "MACSecControlled.";
+  }
+  identity macSecUncontrolledIF {
+    base iana-interface-type;
+    description
+      "MACSecUncontrolled.";
+  }
+  identity aviciOpticalEther {
+    base iana-interface-type;
+    description
+      "Avici Optical Ethernet Aggregate.";
+  }
+  identity atmbond {
+    base iana-interface-type;
+    description
+      "atmbond.";
+  }
+  identity voiceFGDOS {
+    base iana-interface-type;
+    description
+      "Voice FGD Operator Services.";
+  }
+  identity mocaVersion1 {
+    base iana-interface-type;
+    description
+      "MultiMedia over Coax Alliance (MoCA) Interface
+       as documented in information provided privately to IANA.";
+  }
+  identity ieee80216WMAN {
+    base iana-interface-type;
+    description
+      "IEEE 802.16 WMAN interface.";
+  }
+  identity adsl2plus {
+    base iana-interface-type;
+    description
+      "Asymmetric Digital Subscriber Loop Version 2 -
+       Version 2 Plus and all variants.";
+  }
+  identity dvbRcsMacLayer {
+    base iana-interface-type;
+    description
+      "DVB-RCS MAC Layer.";
+    reference
+      "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+  }
+  identity dvbTdm {
+    base iana-interface-type;
+    description
+      "DVB Satellite TDM.";
+    reference
+      "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+  }
+  identity dvbRcsTdma {
+    base iana-interface-type;
+    description
+      "DVB-RCS TDMA.";
+    reference
+      "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+  }
+  identity x86Laps {
+    base iana-interface-type;
+    description
+      "LAPS based on ITU-T X.86/Y.1323.";
+  }
+  identity wwanPP {
+    base iana-interface-type;
+    description
+      "3GPP WWAN.";
+  }
+  identity wwanPP2 {
+    base iana-interface-type;
+    description
+      "3GPP2 WWAN.";
+  }
+  identity voiceEBS {
+    base iana-interface-type;
+    description
+      "Voice P-phone EBS physical interface.";
+  }
+  identity ifPwType {
+    base iana-interface-type;
+    description
+      "Pseudowire interface type.";
+    reference
+      "RFC 5601 - Pseudowire (PW) Management Information Base (MIB)";
+  }
+  identity ilan {
+    base iana-interface-type;
+    description
+      "Internal LAN on a bridge per IEEE 802.1ap.";
+  }
+  identity pip {
+    base iana-interface-type;
+    description
+      "Provider Instance Port on a bridge per IEEE 802.1ah PBB.";
+  }
+  identity aluELP {
+    base iana-interface-type;
+    description
+      "Alcatel-Lucent Ethernet Link Protection.";
+  }
+  identity gpon {
+    base iana-interface-type;
+    description
+      "Gigabit-capable passive optical networks (G-PON) as per
+       ITU-T G.948.";
+  }
+  identity vdsl2 {
+    base iana-interface-type;
+    description
+      "Very high speed digital subscriber line Version 2
+       (as per ITU-T Recommendation G.993.2).";
+    reference
+      "RFC 5650 - Definitions of Managed Objects for Very High
+                  Speed Digital Subscriber Line 2 (VDSL2)";
+  }
+  identity capwapDot11Profile {
+    base iana-interface-type;
+    description
+      "WLAN Profile Interface.";
+    reference
+      "RFC 5834 - Control and Provisioning of Wireless Access
+                  Points (CAPWAP) Protocol Binding MIB for
+                  IEEE 802.11";
+  }
+  identity capwapDot11Bss {
+    base iana-interface-type;
+    description
+      "WLAN BSS Interface.";
+    reference
+      "RFC 5834 - Control and Provisioning of Wireless Access
+                  Points (CAPWAP) Protocol Binding MIB for
+                  IEEE 802.11";
+  }
+  identity capwapWtpVirtualRadio {
+    base iana-interface-type;
+    description
+      "WTP Virtual Radio Interface.";
+    reference
+      "RFC 5833 - Control and Provisioning of Wireless Access
+                  Points (CAPWAP) Protocol Base MIB";
+  }
+  identity bits {
+    base iana-interface-type;
+    description
+      "bitsport.";
+  }
+  identity docsCableUpstreamRfPort {
+    base iana-interface-type;
+    description
+      "DOCSIS CATV Upstream RF Port.";
+  }
+
+
+  identity cableDownstreamRfPort {
+    base iana-interface-type;
+    description
+      "CATV downstream RF Port.";
+  }
+  identity vmwareVirtualNic {
+    base iana-interface-type;
+    description
+      "VMware Virtual Network Interface.";
+  }
+  identity ieee802154 {
+    base iana-interface-type;
+    description
+      "IEEE 802.15.4 WPAN interface.";
+    reference
+      "IEEE 802.15.4-2006";
+  }
+  identity otnOdu {
+    base iana-interface-type;
+    description
+      "OTN Optical Data Unit.";
+  }
+  identity otnOtu {
+    base iana-interface-type;
+    description
+      "OTN Optical channel Transport Unit.";
+  }
+  identity ifVfiType {
+    base iana-interface-type;
+    description
+      "VPLS Forwarding Instance Interface Type.";
+  }
+  identity g9981 {
+    base iana-interface-type;
+    description
+      "G.998.1 bonded interface.";
+  }
+  identity g9982 {
+    base iana-interface-type;
+    description
+      "G.998.2 bonded interface.";
+  }
+  identity g9983 {
+    base iana-interface-type;
+    description
+      "G.998.3 bonded interface.";
+  }
+
+  identity aluEpon {
+    base iana-interface-type;
+    description
+      "Ethernet Passive Optical Networks (E-PON).";
+  }
+  identity aluEponOnu {
+    base iana-interface-type;
+    description
+      "EPON Optical Network Unit.";
+  }
+  identity aluEponPhysicalUni {
+    base iana-interface-type;
+    description
+      "EPON physical User to Network interface.";
+  }
+  identity aluEponLogicalLink {
+    base iana-interface-type;
+    description
+      "The emulation of a point-to-point link over the EPON
+       layer.";
+  }
+  identity aluGponOnu {
+    base iana-interface-type;
+    description
+      "GPON Optical Network Unit.";
+    reference
+      "ITU-T G.984.2";
+  }
+  identity aluGponPhysicalUni {
+    base iana-interface-type;
+    description
+      "GPON physical User to Network interface.";
+    reference
+      "ITU-T G.984.2";
+  }
+  identity vmwareNicTeam {
+    base iana-interface-type;
+    description
+      "VMware NIC Team.";
+  }
+}
diff --git a/model/iana/iana-if-type/pom.xml b/model/iana/iana-if-type/pom.xml
new file mode 100644 (file)
index 0000000..fb011b8
--- /dev/null
@@ -0,0 +1,41 @@
+<?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>
+        <artifactId>model-iana</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>iana-if-type</artifactId>
+    <version>2013.07.04.8-SNAPSHOT</version>
+
+    <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/model/iana/iana-if-type/src/main/yang/iana-if-type@2013-07-04.yang b/model/iana/iana-if-type/src/main/yang/iana-if-type@2013-07-04.yang
new file mode 100644 (file)
index 0000000..c75974d
--- /dev/null
@@ -0,0 +1,1517 @@
+module iana-if-type {
+  namespace "urn:ietf:params:xml:ns:yang:iana-if-type";
+  prefix ianaift;
+
+  organization "IANA";
+  contact
+    "        Internet Assigned Numbers Authority
+
+     Postal: ICANN
+             4676 Admiralty Way, Suite 330
+             Marina del Rey, CA 90292
+
+     Tel:    +1 310 823 9358
+     E-Mail: iana&iana.org";
+  description
+    "This YANG module defines the iana-if-type typedef, which
+     contains YANG definitions for IANA-registered interface types.
+
+     This YANG module is maintained by IANA, and reflects the
+     'ifType definitions' registry.
+
+     The latest revision of this YANG module can be obtained from
+     the IANA web site.
+
+     Copyright (c) 2011 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see
+     the RFC itself for full legal notices.";
+  // RFC Ed.: replace XXXX with actual RFC number and remove this
+  // note.
+
+  // RFC Ed.: update the date below with the date of RFC publication
+  // and remove this note.
+  revision 2013-07-04 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: IANA Interface Type YANG Module";
+  }
+
+  typedef iana-if-type {
+    type enumeration {
+      enum "other" {
+        value 1;
+        description
+          "None of the following";
+      }
+      enum "regular1822" {
+        value 2;
+      }
+      enum "hdh1822" {
+        value 3;
+      }
+      enum "ddnX25" {
+        value 4;
+      }
+      enum "rfc877x25" {
+        value 5;
+        reference
+          "RFC 1382 - SNMP MIB Extension for the X.25 Packet Layer";
+      }
+      enum "ethernetCsmacd" {
+        value 6;
+        description
+          "For all ethernet-like interfaces, regardless of speed,
+           as per RFC3635.";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "iso88023Csmacd" {
+        value 7;
+        status deprecated;
+        description
+          "Deprecated via RFC3635.
+           Use ethernetCsmacd(6) instead.";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "iso88024TokenBus" {
+        value 8;
+      }
+      enum "iso88025TokenRing" {
+        value 9;
+      }
+      enum "iso88026Man" {
+        value 10;
+      }
+      enum "starLan" {
+        value 11;
+        status deprecated;
+        description
+          "Deprecated via RFC3635.
+           Use ethernetCsmacd(6) instead.";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "proteon10Mbit" {
+        value 12;
+      }
+      enum "proteon80Mbit" {
+        value 13;
+      }
+      enum "hyperchannel" {
+        value 14;
+      }
+      enum "fddi" {
+        value 15;
+        reference
+          "RFC 1512 - FDDI Management Information Base";
+      }
+      enum "lapb" {
+        value 16;
+        reference
+          "RFC 1381 - SNMP MIB Extension for X.25 LAPB";
+      }
+      enum "sdlc" {
+        value 17;
+      }
+      enum "ds1" {
+        value 18;
+        description
+          "DS1-MIB";
+        reference
+          "RFC 4805 - Definitions of Managed Objects for the
+                      DS1, J1, E1, DS2, and E2 Interface Types";
+      }
+      enum "e1" {
+        value 19;
+        status obsolete;
+        description
+          "Obsolete see DS1-MIB";
+        reference
+          "RFC 4805 - Definitions of Managed Objects for the
+                      DS1, J1, E1, DS2, and E2 Interface Types";
+      }
+      enum "basicISDN" {
+        value 20;
+        description
+          "see also RFC2127";
+      }
+      enum "primaryISDN" {
+        value 21;
+      }
+      enum "propPointToPointSerial" {
+        value 22;
+        description
+          "proprietary serial";
+      }
+      enum "ppp" {
+        value 23;
+      }
+      enum "softwareLoopback" {
+        value 24;
+      }
+      enum "eon" {
+        value 25;
+        description
+          "CLNP over IP";
+      }
+      enum "ethernet3Mbit" {
+        value 26;
+      }
+      enum "nsip" {
+        value 27;
+        description
+          "XNS over IP";
+      }
+      enum "slip" {
+        value 28;
+        description
+          "generic SLIP";
+      }
+      enum "ultra" {
+        value 29;
+        description
+          "ULTRA technologies";
+      }
+      enum "ds3" {
+        value 30;
+        description
+          "DS3-MIB";
+        reference
+          "RFC 3896 - Definitions of Managed Objects for the
+                      DS3/E3 Interface Type";
+      }
+      enum "sip" {
+        value 31;
+        description
+          "SMDS, coffee";
+        reference
+          "RFC 1694 - Definitions of Managed Objects for SMDS
+                      Interfaces using SMIv2";
+      }
+      enum "frameRelay" {
+        value 32;
+        description
+          "DTE only.";
+        reference
+          "RFC 2115 - Management Information Base for Frame Relay
+                      DTEs Using SMIv2";
+      }
+      enum "rs232" {
+        value 33;
+        reference
+          "RFC 1659 - Definitions of Managed Objects for RS-232-like
+                      Hardware Devices using SMIv2";
+      }
+      enum "para" {
+        value 34;
+        description
+          "parallel-port";
+        reference
+          "RFC 1660 - Definitions of Managed Objects for
+                      Parallel-printer-like Hardware Devices using
+                      SMIv2";
+      }
+      enum "arcnet" {
+        value 35;
+        description
+          "arcnet";
+      }
+      enum "arcnetPlus" {
+        value 36;
+        description
+          "arcnet plus";
+      }
+      enum "atm" {
+        value 37;
+        description
+          "ATM cells";
+      }
+      enum "miox25" {
+        value 38;
+        reference
+          "RFC 1461 - SNMP MIB extension for Multiprotocol
+                      Interconnect over X.25";
+      }
+      enum "sonet" {
+        value 39;
+        description
+          "SONET or SDH";
+      }
+      enum "x25ple" {
+        value 40;
+        reference
+          "RFC 2127 - ISDN Management Information Base using SMIv2";
+      }
+      enum "iso88022llc" {
+        value 41;
+      }
+      enum "localTalk" {
+        value 42;
+      }
+      enum "smdsDxi" {
+        value 43;
+      }
+      enum "frameRelayService" {
+        value 44;
+        description
+          "FRNETSERV-MIB";
+        reference
+          "RFC 2954 - Definitions of Managed Objects for Frame
+                      Relay Service";
+      }
+      enum "v35" {
+        value 45;
+      }
+      enum "hssi" {
+        value 46;
+      }
+      enum "hippi" {
+        value 47;
+      }
+      enum "modem" {
+        value 48;
+        description
+          "Generic modem";
+      }
+      enum "aal5" {
+        value 49;
+        description
+          "AAL5 over ATM";
+      }
+      enum "sonetPath" {
+        value 50;
+      }
+      enum "sonetVT" {
+        value 51;
+      }
+      enum "smdsIcip" {
+        value 52;
+        description
+          "SMDS InterCarrier Interface";
+      }
+      enum "propVirtual" {
+        value 53;
+        description
+          "proprietary virtual/internal";
+        reference
+          "RFC 2863 - The Interfaces Group MIB";
+      }
+      enum "propMultiplexor" {
+        value 54;
+        description
+          "proprietary multiplexing";
+        reference
+          "RFC 2863 - The Interfaces Group MIB";
+      }
+      enum "ieee80212" {
+        value 55;
+        description
+          "100BaseVG";
+      }
+      enum "fibreChannel" {
+        value 56;
+        description
+          "Fibre Channel";
+      }
+      enum "hippiInterface" {
+        value 57;
+        description
+          "HIPPI interfaces";
+      }
+      enum "frameRelayInterconnect" {
+        value 58;
+        status obsolete;
+        description
+          "Obsolete use either
+           frameRelay(32) or frameRelayService(44).";
+      }
+      enum "aflane8023" {
+        value 59;
+        description
+          "ATM Emulated LAN for 802.3";
+      }
+      enum "aflane8025" {
+        value 60;
+        description
+          "ATM Emulated LAN for 802.5";
+      }
+      enum "cctEmul" {
+        value 61;
+        description
+         "ATM Emulated circuit";
+      }
+      enum "fastEther" {
+        value 62;
+        status deprecated;
+        description
+          "Obsoleted via RFC3635.
+          ethernetCsmacd(6) should be used instead";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "isdn" {
+        value 63;
+        description
+          "ISDN and X.25";
+        reference
+          "RFC 1356 - Multiprotocol Interconnect on X.25 and ISDN
+                      in the Packet Mode";
+      }
+      enum "v11" {
+        value 64;
+        description
+         "CCITT V.11/X.21";
+      }
+      enum "v36" {
+        value 65;
+        description
+          "CCITT V.36";
+      }
+      enum "g703at64k" {
+        value 66;
+        description
+          "CCITT G703 at 64Kbps";
+      }
+      enum "g703at2mb" {
+        value 67;
+        status obsolete;
+        description
+          "Obsolete see DS1-MIB";
+      }
+      enum "qllc" {
+        value 68;
+        description
+          "SNA QLLC";
+      }
+      enum "fastEtherFX" {
+        value 69;
+        status deprecated;
+        description
+          "Obsoleted via RFC3635
+          ethernetCsmacd(6) should be used instead";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "channel" {
+        value 70;
+        description
+          "channel";
+      }
+      enum "ieee80211" {
+        value 71;
+        description
+          "radio spread spectrum";
+      }
+      enum "ibm370parChan" {
+        value 72;
+        description
+          "IBM System 360/370 OEMI Channel";
+      }
+      enum "escon" {
+        value 73;
+        description
+          "IBM Enterprise Systems Connection";
+      }
+      enum "dlsw" {
+        value 74;
+        description
+          "Data Link Switching";
+      }
+      enum "isdns" {
+        value 75;
+        description
+          "ISDN S/T interface";
+      }
+      enum "isdnu" {
+        value 76;
+        description
+          "ISDN U interface";
+      }
+      enum "lapd" {
+        value 77;
+        description
+          "Link Access Protocol D";
+      }
+      enum "ipSwitch" {
+        value 78;
+        description
+          "IP Switching Objects";
+      }
+      enum "rsrb" {
+        value 79;
+        description
+          "Remote Source Route Bridging";
+      }
+      enum "atmLogical" {
+        value 80;
+        description
+          "ATM Logical Port";
+        reference
+          "RFC 3606 - Definitions of Supplemental Managed Objects
+                      for ATM Interface";
+      }
+      enum "ds0" {
+        value 81;
+        description
+          "Digital Signal Level 0";
+        reference
+          "RFC 2494 - Definitions of Managed Objects for the DS0
+                      and DS0 Bundle Interface Type";
+      }
+      enum "ds0Bundle" {
+        value 82;
+        description
+          "group of ds0s on the same ds1";
+        reference
+          "RFC 2494 - Definitions of Managed Objects for the DS0
+                      and DS0 Bundle Interface Type";
+      }
+      enum "bsc" {
+        value 83;
+        description
+          "Bisynchronous Protocol";
+      }
+      enum "async" {
+        value 84;
+        description
+          "Asynchronous Protocol";
+      }
+      enum "cnr" {
+        value 85;
+        description
+          "Combat Net Radio";
+      }
+      enum "iso88025Dtr" {
+        value 86;
+        description
+          "ISO 802.5r DTR";
+      }
+      enum "eplrs" {
+        value 87;
+        description
+          "Ext Pos Loc Report Sys";
+      }
+      enum "arap" {
+        value 88;
+        description
+          "Appletalk Remote Access Protocol";
+      }
+      enum "propCnls" {
+        value 89;
+        description
+          "Proprietary Connectionless Protocol";
+      }
+      enum "hostPad" {
+        value 90;
+        description
+          "CCITT-ITU X.29 PAD Protocol";
+      }
+      enum "termPad" {
+        value 91;
+        description
+          "CCITT-ITU X.3 PAD Facility";
+      }
+      enum "frameRelayMPI" {
+        value 92;
+        description
+          "Multiproto Interconnect over FR";
+      }
+      enum "x213" {
+        value 93;
+        description
+          "CCITT-ITU X213";
+      }
+      enum "adsl" {
+        value 94;
+        description
+          "Asymmetric Digital Subscriber Loop";
+      }
+      enum "radsl" {
+        value 95;
+        description
+          "Rate-Adapt. Digital Subscriber Loop";
+      }
+      enum "sdsl" {
+        value 96;
+        description
+          "Symmetric Digital Subscriber Loop";
+      }
+      enum "vdsl" {
+        value 97;
+        description
+          "Very H-Speed Digital Subscrib. Loop";
+      }
+      enum "iso88025CRFPInt" {
+        value 98;
+        description
+          "ISO 802.5 CRFP";
+      }
+      enum "myrinet" {
+        value 99;
+        description
+          "Myricom Myrinet";
+      }
+      enum "voiceEM" {
+        value 100;
+        description
+          "voice recEive and transMit";
+      }
+      enum "voiceFXO" {
+        value 101;
+        description
+          "voice Foreign Exchange Office";
+      }
+      enum "voiceFXS" {
+        value 102;
+        description
+          "voice Foreign Exchange Station";
+      }
+      enum "voiceEncap" {
+        value 103;
+        description
+          "voice encapsulation";
+      }
+      enum "voiceOverIp" {
+        value 104;
+        description
+          "voice over IP encapsulation";
+      }
+      enum "atmDxi" {
+        value 105;
+        description
+          "ATM DXI";
+      }
+      enum "atmFuni" {
+        value 106;
+        description
+          "ATM FUNI";
+      }
+      enum "atmIma" {
+        value 107;
+        description
+          "ATM IMA";
+      }
+      enum "pppMultilinkBundle" {
+        value 108;
+        description
+          "PPP Multilink Bundle";
+      }
+      enum "ipOverCdlc" {
+        value 109;
+        description
+          "IBM ipOverCdlc";
+      }
+      enum "ipOverClaw" {
+        value 110;
+        description
+          "IBM Common Link Access to Workstn";
+      }
+      enum "stackToStack" {
+        value 111;
+        description
+          "IBM stackToStack";
+      }
+      enum "virtualIpAddress" {
+        value 112;
+        description
+          "IBM VIPA";
+      }
+      enum "mpc" {
+        value 113;
+        description
+          "IBM multi-protocol channel support";
+      }
+      enum "ipOverAtm" {
+        value 114;
+        description
+          "IBM ipOverAtm";
+        reference
+          "RFC 2320 - Definitions of Managed Objects for Classical IP
+                      and ARP Over ATM Using SMIv2 (IPOA-MIB)";
+      }
+      enum "iso88025Fiber" {
+        value 115;
+        description
+          "ISO 802.5j Fiber Token Ring";
+      }
+      enum "tdlc" {
+        value 116;
+        description
+          "IBM twinaxial data link control";
+      }
+      enum "gigabitEthernet" {
+        value 117;
+        status deprecated;
+        description
+          "Obsoleted via RFC3635
+           ethernetCsmacd(6) should be used instead";
+        reference
+          "RFC 3635 - Definitions of Managed Objects for the
+                      Ethernet-like Interface Types.";
+      }
+      enum "hdlc" {
+        value 118;
+        description
+          "HDLC";
+      }
+      enum "lapf" {
+        value 119;
+        description
+          "LAP F";
+      }
+      enum "v37" {
+        value 120;
+        description
+          "V.37";
+      }
+      enum "x25mlp" {
+        value 121;
+        description
+          "Multi-Link Protocol";
+      }
+      enum "x25huntGroup" {
+        value 122;
+        description
+          "X25 Hunt Group";
+      }
+      enum "transpHdlc" {
+        value 123;
+        description
+          "Transp HDLC";
+      }
+      enum "interleave" {
+        value 124;
+        description
+          "Interleave channel";
+      }
+      enum "fast" {
+        value 125;
+        description
+          "Fast channel";
+      }
+      enum "ip" {
+        value 126;
+        description
+          "IP (for APPN HPR in IP networks)";
+      }
+      enum "docsCableMaclayer" {
+        value 127;
+        description
+          "CATV Mac Layer";
+      }
+      enum "docsCableDownstream" {
+        value 128;
+        description
+          "CATV Downstream interface";
+      }
+      enum "docsCableUpstream" {
+        value 129;
+        description
+          "CATV Upstream interface";
+      }
+      enum "a12MppSwitch" {
+        value 130;
+        description
+          "Avalon Parallel Processor";
+      }
+      enum "tunnel" {
+        value 131;
+        description
+          "Encapsulation interface";
+      }
+      enum "coffee" {
+        value 132;
+        description
+          "coffee pot";
+        reference
+          "RFC 2325 - Coffee MIB";
+      }
+      enum "ces" {
+        value 133;
+        description
+          "Circuit Emulation Service";
+      }
+      enum "atmSubInterface" {
+        value 134;
+        description
+          "ATM Sub Interface";
+      }
+      enum "l2vlan" {
+        value 135;
+        description
+          "Layer 2 Virtual LAN using 802.1Q";
+      }
+      enum "l3ipvlan" {
+        value 136;
+        description
+          "Layer 3 Virtual LAN using IP";
+      }
+      enum "l3ipxvlan" {
+        value 137;
+        description
+          "Layer 3 Virtual LAN using IPX";
+      }
+      enum "digitalPowerline" {
+        value 138;
+        description
+          "IP over Power Lines";
+      }
+      enum "mediaMailOverIp" {
+        value 139;
+        description
+          "Multimedia Mail over IP";
+      }
+      enum "dtm" {
+        value 140;
+        description
+          "Dynamic syncronous Transfer Mode";
+      }
+      enum "dcn" {
+        value 141;
+        description
+          "Data Communications Network";
+      }
+      enum "ipForward" {
+        value 142;
+        description
+          "IP Forwarding Interface";
+      }
+      enum "msdsl" {
+        value 143;
+        description
+          "Multi-rate Symmetric DSL";
+      }
+      enum "ieee1394" {
+        value 144;
+        description
+          "IEEE1394 High Performance Serial Bus";
+      }
+      enum "if-gsn" {
+        value 145;
+        description
+          "HIPPI-6400";
+      }
+      enum "dvbRccMacLayer" {
+        value 146;
+        description
+          "DVB-RCC MAC Layer";
+      }
+      enum "dvbRccDownstream" {
+        value 147;
+        description
+          "DVB-RCC Downstream Channel";
+      }
+      enum "dvbRccUpstream" {
+        value 148;
+        description
+          "DVB-RCC Upstream Channel";
+      }
+      enum "atmVirtual" {
+        value 149;
+        description
+          "ATM Virtual Interface";
+      }
+      enum "mplsTunnel" {
+        value 150;
+        description
+          "MPLS Tunnel Virtual Interface";
+      }
+      enum "srp" {
+        value 151;
+        description
+          "Spatial Reuse Protocol";
+      }
+      enum "voiceOverAtm" {
+        value 152;
+        description
+          "Voice Over ATM";
+      }
+      enum "voiceOverFrameRelay" {
+        value 153;
+        description
+          "Voice Over Frame Relay";
+      }
+      enum "idsl" {
+        value 154;
+        description
+          "Digital Subscriber Loop over ISDN";
+      }
+      enum "compositeLink" {
+        value 155;
+        description
+          "Avici Composite Link Interface";
+      }
+      enum "ss7SigLink" {
+        value 156;
+        description
+          "SS7 Signaling Link";
+      }
+      enum "propWirelessP2P" {
+        value 157;
+        description
+          "Prop. P2P wireless interface";
+      }
+      enum "frForward" {
+        value 158;
+        description
+          "Frame Forward Interface";
+      }
+      enum "rfc1483" {
+        value 159;
+        description
+          "Multiprotocol over ATM AAL5";
+        reference
+          "RFC 1483 - Multiprotocol Encapsulation over ATM
+                      Adaptation Layer 5";
+      }
+      enum "usb" {
+        value 160;
+        description
+          "USB Interface";
+      }
+      enum "ieee8023adLag" {
+        value 161;
+        description
+          "IEEE 802.3ad Link Aggregate";
+      }
+      enum "bgppolicyaccounting" {
+        value 162;
+        description
+          "BGP Policy Accounting";
+      }
+      enum "frf16MfrBundle" {
+        value 163;
+        description
+          "FRF .16 Multilink Frame Relay";
+      }
+      enum "h323Gatekeeper" {
+        value 164;
+        description
+          "H323 Gatekeeper";
+      }
+      enum "h323Proxy" {
+        value 165;
+        description
+          "H323 Voice and Video Proxy";
+      }
+      enum "mpls" {
+        value 166;
+        description
+          "MPLS";
+      }
+      enum "mfSigLink" {
+        value 167;
+        description
+          "Multi-frequency signaling link";
+      }
+      enum "hdsl2" {
+        value 168;
+        description
+          "High Bit-Rate DSL - 2nd generation";
+      }
+      enum "shdsl" {
+        value 169;
+        description
+          "Multirate HDSL2";
+      }
+      enum "ds1FDL" {
+        value 170;
+        description
+          "Facility Data Link 4Kbps on a DS1";
+      }
+      enum "pos" {
+        value 171;
+        description
+          "Packet over SONET/SDH Interface";
+      }
+      enum "dvbAsiIn" {
+        value 172;
+        description
+          "DVB-ASI Input";
+      }
+      enum "dvbAsiOut" {
+        value 173;
+        description
+          "DVB-ASI Output";
+      }
+      enum "plc" {
+        value 174;
+        description
+          "Power Line Communtications";
+      }
+      enum "nfas" {
+        value 175;
+        description
+          "Non Facility Associated Signaling";
+      }
+      enum "tr008" {
+        value 176;
+        description
+          "TR008";
+      }
+      enum "gr303RDT" {
+        value 177;
+        description
+          "Remote Digital Terminal";
+      }
+      enum "gr303IDT" {
+        value 178;
+        description
+          "Integrated Digital Terminal";
+      }
+      enum "isup" {
+        value 179;
+        description
+          "ISUP";
+      }
+      enum "propDocsWirelessMaclayer" {
+        value 180;
+        description
+          "Cisco proprietary Maclayer";
+      }
+      enum "propDocsWirelessDownstream" {
+        value 181;
+        description
+          "Cisco proprietary Downstream";
+      }
+      enum "propDocsWirelessUpstream" {
+        value 182;
+        description
+          "Cisco proprietary Upstream";
+      }
+      enum "hiperlan2" {
+        value 183;
+        description
+          "HIPERLAN Type 2 Radio Interface";
+      }
+      enum "propBWAp2Mp" {
+        value 184;
+        description
+          "PropBroadbandWirelessAccesspt2multipt use of this value
+           for IEEE 802.16 WMAN interfaces as per IEEE Std 802.16f
+           is deprecated and ieee80216WMAN(237) should be used
+           instead.";
+      }
+      enum "sonetOverheadChannel" {
+        value 185;
+        description
+          "SONET Overhead Channel";
+      }
+      enum "digitalWrapperOverheadChannel" {
+        value 186;
+        description
+          "Digital Wrapper";
+      }
+      enum "aal2" {
+        value 187;
+        description
+          "ATM adaptation layer 2";
+      }
+      enum "radioMAC" {
+        value 188;
+        description
+          "MAC layer over radio links";
+      }
+      enum "atmRadio" {
+        value 189;
+        description
+          "ATM over radio links";
+      }
+      enum "imt" {
+        value 190;
+        description
+          "Inter Machine Trunks";
+      }
+      enum "mvl" {
+        value 191;
+        description
+          "Multiple Virtual Lines DSL";
+      }
+      enum "reachDSL" {
+        value 192;
+        description
+          "Long Reach DSL";
+      }
+      enum "frDlciEndPt" {
+        value 193;
+        description
+          "Frame Relay DLCI End Point";
+      }
+      enum "atmVciEndPt" {
+        value 194;
+        description
+          "ATM VCI End Point";
+      }
+      enum "opticalChannel" {
+        value 195;
+        description
+          "Optical Channel";
+      }
+      enum "opticalTransport" {
+        value 196;
+        description
+          "Optical Transport";
+      }
+      enum "propAtm" {
+        value 197;
+        description
+          "Proprietary ATM";
+      }
+      enum "voiceOverCable" {
+        value 198;
+        description
+          "Voice Over Cable Interface";
+      }
+      enum "infiniband" {
+        value 199;
+        description
+          "Infiniband";
+      }
+      enum "teLink" {
+        value 200;
+        description
+          "TE Link";
+      }
+      enum "q2931" {
+        value 201;
+        description
+          "Q.2931";
+      }
+      enum "virtualTg" {
+        value 202;
+        description
+          "Virtual Trunk Group";
+      }
+      enum "sipTg" {
+        value 203;
+        description
+          "SIP Trunk Group";
+      }
+      enum "sipSig" {
+        value 204;
+        description
+          "SIP Signaling";
+      }
+      enum "docsCableUpstreamChannel" {
+        value 205;
+        description
+          "CATV Upstream Channel";
+      }
+      enum "econet" {
+        value 206;
+        description
+          "Acorn Econet";
+      }
+      enum "pon155" {
+        value 207;
+        description
+          "FSAN 155Mb Symetrical PON interface";
+      }
+      enum "pon622" {
+        value 208;
+        description
+          "FSAN622Mb Symetrical PON interface";
+      }
+      enum "bridge" {
+        value 209;
+        description
+          "Transparent bridge interface";
+      }
+      enum "linegroup" {
+        value 210;
+        description
+          "Interface common to multiple lines";
+      }
+      enum "voiceEMFGD" {
+        value 211;
+        description
+          "voice E&M Feature Group D";
+      }
+      enum "voiceFGDEANA" {
+        value 212;
+        description
+          "voice FGD Exchange Access North American";
+      }
+      enum "voiceDID" {
+        value 213;
+        description
+          "voice Direct Inward Dialing";
+      }
+      enum "mpegTransport" {
+        value 214;
+        description
+          "MPEG transport interface";
+      }
+      enum "sixToFour" {
+        value 215;
+        status deprecated;
+        description
+          "6to4 interface (DEPRECATED)";
+        reference
+          "RFC 4087 - IP Tunnel MIB";
+      }
+      enum "gtp" {
+        value 216;
+        description
+          "GTP (GPRS Tunneling Protocol)";
+      }
+      enum "pdnEtherLoop1" {
+        value 217;
+        description
+          "Paradyne EtherLoop 1";
+      }
+      enum "pdnEtherLoop2" {
+        value 218;
+        description
+          "Paradyne EtherLoop 2";
+      }
+      enum "opticalChannelGroup" {
+        value 219;
+        description
+          "Optical Channel Group";
+      }
+      enum "homepna" {
+        value 220;
+        description
+          "HomePNA ITU-T G.989";
+      }
+      enum "gfp" {
+        value 221;
+        description
+          "Generic Framing Procedure (GFP)";
+      }
+      enum "ciscoISLvlan" {
+        value 222;
+        description
+          "Layer 2 Virtual LAN using Cisco ISL";
+      }
+      enum "actelisMetaLOOP" {
+        value 223;
+        description
+          "Acteleis proprietary MetaLOOP High Speed Link";
+      }
+      enum "fcipLink" {
+        value 224;
+        description
+          "FCIP Link";
+      }
+      enum "rpr" {
+        value 225;
+        description
+          "Resilient Packet Ring Interface Type";
+      }
+      enum "qam" {
+        value 226;
+        description
+          "RF Qam Interface";
+      }
+      enum "lmp" {
+        value 227;
+        description
+          "Link Management Protocol";
+        reference
+          "RFC 4327 - Link Management Protocol (LMP) Management
+                      Information Base (MIB)";
+      }
+      enum "cblVectaStar" {
+        value 228;
+        description
+          "Cambridge Broadband Networks Limited VectaStar";
+      }
+      enum "docsCableMCmtsDownstream" {
+        value 229;
+        description
+          "CATV Modular CMTS Downstream Interface";
+      }
+      enum "adsl2" {
+        value 230;
+        status deprecated;
+        description
+          "Asymmetric Digital Subscriber Loop Version 2
+           (DEPRECATED/OBSOLETED - please use adsl2plus(238)
+           instead)";
+        reference
+          "RFC 4706 - Definitions of Managed Objects for Asymmetric
+                      Digital Subscriber Line 2 (ADSL2)";
+      }
+      enum "macSecControlledIF" {
+        value 231;
+        description
+          "MACSecControlled";
+      }
+      enum "macSecUncontrolledIF" {
+        value 232;
+        description
+          "MACSecUncontrolled";
+      }
+      enum "aviciOpticalEther" {
+        value 233;
+        description
+         "Avici Optical Ethernet Aggregate";
+      }
+      enum "atmbond" {
+        value 234;
+        description
+          "atmbond";
+      }
+      enum "voiceFGDOS" {
+        value 235;
+        description
+          "voice FGD Operator Services";
+      }
+      enum "mocaVersion1" {
+        value 236;
+        description
+          "MultiMedia over Coax Alliance (MoCA) Interface
+           as documented in information provided privately to IANA";
+      }
+      enum "ieee80216WMAN" {
+        value 237;
+        description
+          "IEEE 802.16 WMAN interface";
+      }
+      enum "adsl2plus" {
+        value 238;
+        description
+          "Asymmetric Digital Subscriber Loop Version 2,
+           Version 2 Plus and all variants";
+      }
+      enum "dvbRcsMacLayer" {
+        value 239;
+        description
+          "DVB-RCS MAC Layer";
+        reference
+          "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+      }
+      enum "dvbTdm" {
+        value 240;
+        description
+          "DVB Satellite TDM";
+        reference
+          "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+      }
+      enum "dvbRcsTdma" {
+        value 241;
+        description
+          "DVB-RCS TDMA";
+        reference
+          "RFC 5728 - The SatLabs Group DVB-RCS MIB";
+      }
+      enum "x86Laps" {
+        value 242;
+        description
+          "LAPS based on ITU-T X.86/Y.1323";
+      }
+      enum "wwanPP" {
+        value 243;
+        description
+          "3GPP WWAN";
+      }
+      enum "wwanPP2" {
+        value 244;
+        description
+          "3GPP2 WWAN";
+      }
+      enum "voiceEBS" {
+        value 245;
+        description
+          "voice P-phone EBS physical interface";
+      }
+      enum "ifPwType" {
+        value 246;
+        description
+          "Pseudowire interface type";
+        reference
+          "RFC 5601 - Pseudowire (PW) Management Information Base";
+      }
+      enum "ilan" {
+        value 247;
+        description
+          "Internal LAN on a bridge per IEEE 802.1ap";
+      }
+      enum "pip" {
+        value 248;
+        description
+          "Provider Instance Port on a bridge per IEEE 802.1ah PBB";
+      }
+      enum "aluELP" {
+        value 249;
+        description
+          "Alcatel-Lucent Ethernet Link Protection";
+      }
+      enum "gpon" {
+        value 250;
+        description
+          "Gigabit-capable passive optical networks (G-PON) as per
+           ITU-T G.948";
+      }
+      enum "vdsl2" {
+        value 251;
+        description
+          "Very high speed digital subscriber line Version 2
+           (as per ITU-T Recommendation G.993.2)";
+        reference
+          "RFC 5650 - Definitions of Managed Objects for Very High
+                      Speed Digital Subscriber Line 2 (VDSL2)";
+      }
+      enum "capwapDot11Profile" {
+        value 252;
+        description
+          "WLAN Profile Interface";
+        reference
+          "RFC 5834 - Control and Provisioning of Wireless Access
+                      Points (CAPWAP) Protocol Binding MIB for
+                      IEEE 802.11";
+      }
+      enum "capwapDot11Bss" {
+        value 253;
+        description
+          "WLAN BSS Interface";
+        reference
+          "RFC 5834 - Control and Provisioning of Wireless Access
+                      Points (CAPWAP) Protocol Binding MIB for
+                      IEEE 802.11";
+      }
+      enum "capwapWtpVirtualRadio" {
+        value 254;
+        description
+          "WTP Virtual Radio Interface";
+        reference
+          "RFC 5833 - Control and Provisioning of Wireless Access
+                      Points (CAPWAP) Protocol Base MIB";
+      }
+      enum "bits" {
+        value 255;
+        description
+          "bitsport";
+      }
+      enum "docsCableUpstreamRfPort" {
+        value 256;
+        description
+          "DOCSIS CATV Upstream RF Port";
+      }
+      enum "cableDownstreamRfPort" {
+        value 257;
+        description
+          "CATV downstream RF port";
+      }
+      enum "vmwareVirtualNic" {
+        value 258;
+        description
+          "VMware Virtual Network Interface";
+      }
+      enum "ieee802154" {
+        value 259;
+        description
+          "IEEE 802.15.4 WPAN interface";
+        reference
+          "IEEE 802.15.4-2006";
+      }
+      enum "otnOdu" {
+        value 260;
+        description
+          "OTN Optical Data Unit";
+      }
+      enum "otnOtu" {
+        value 261;
+        description
+          "OTN Optical channel Transport Unit";
+      }
+      enum "ifVfiType" {
+        value 262;
+        description
+          "VPLS Forwarding Instance Interface Type";
+      }
+      enum "g9981" {
+        value 263;
+        description
+          "G.998.1 bonded interface";
+      }
+      enum "g9982" {
+        value 264;
+        description
+          "G.998.2 bonded interface";
+      }
+      enum "g9983" {
+        value 265;
+        description
+          "G.998.3 bonded interface";
+      }
+      enum "aluEpon" {
+        value 266;
+        description
+          "Ethernet Passive Optical Networks (E-PON)";
+      }
+      enum "aluEponOnu" {
+        value 267;
+        description
+          "EPON Optical Network Unit";
+      }
+      enum "aluEponPhysicalUni" {
+        value 268;
+        description
+          "EPON physical User to Network interface";
+      }
+      enum "aluEponLogicalLink" {
+        value 269;
+        description
+          "The emulation of a point-to-point link over the EPON
+           layer";
+      }
+      enum "aluGponOnu" {
+        value 270;
+        description
+          "GPON Optical Network Unit";
+        reference
+          "ITU-T G.984.2";
+      }
+      enum "aluGponPhysicalUni" {
+        value 271;
+        description
+          "GPON physical User to Network interface";
+        reference
+          "ITU-T G.984.2";
+      }
+      enum "vmwareNicTeam" {
+        value 272;
+        description
+          "VMware NIC Team";
+      }
+      // value 273 reserved by IANA
+    }
+    description
+      "This data type is used as the syntax of the 'type'
+       leaf in the 'interface' list in the YANG module
+       ietf-interface.
+
+       The definition of this typedef with the
+       addition of newly assigned values is published
+       periodically by the IANA, in either the Assigned
+       Numbers RFC, or some derivative of it specific to
+       Internet Network Management number assignments.  (The
+       latest arrangements can be obtained by contacting the
+       IANA.)
+
+       Requests for new values should be made to IANA via
+       email (iana&iana.org).";
+    reference
+      "IANA ifType definitions registry.
+       <http://www.iana.org/assignments/smi-numbers>";
+  }
+}
diff --git a/model/iana/pom.xml b/model/iana/pom.xml
new file mode 100644 (file)
index 0000000..843c084
--- /dev/null
@@ -0,0 +1,32 @@
+<?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>
+        <artifactId>model-parent</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>model-iana</artifactId>
+    <packaging>pom</packaging>
+    <modules>
+        <module>iana-afn-safi</module>
+        <module>iana-if-type</module>
+        <module>iana-if-type-2014-05-08</module>
+        <!-- 
+        <module>ietf-topology-l3-unicast-igp</module>
+        <module>ietf-topology-isis</module>
+        <module>ietf-topology-ospf</module>
+         -->
+    </modules>
+</project>
diff --git a/model/iana/src/main/yang/.gitignore b/model/iana/src/main/yang/.gitignore
new file mode 100644 (file)
index 0000000..e50f3cf
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# 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
+#
+
diff --git a/model/ietf/ietf-inet-types/pom.xml b/model/ietf/ietf-inet-types/pom.xml
new file mode 100644 (file)
index 0000000..cad8508
--- /dev/null
@@ -0,0 +1,51 @@
+<?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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-inet-types</artifactId>
+    <version>2010.09.24.8-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <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/model/ietf/ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/HostBuilder.java b/model/ietf/ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/HostBuilder.java
new file mode 100644 (file)
index 0000000..96f32fc
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ **/
+public final class HostBuilder {
+    private static final Pattern IPV4_PATTERN = Pattern.compile("(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(%[\\p{N}\\p{L}]+)?");
+    private static final Pattern IPV6_PATTERN1 = Pattern.compile("((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(%[\\p{N}\\p{L}]+)?");
+    private static final Pattern IPV6_PATTERN2 = Pattern.compile("(([^:]+:){6}(([^:]+:[^:]+)|(.*\\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(%.+)?");
+    private static final Pattern DOMAIN_PATTERN = Pattern.compile("((([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.)*([a-zA-Z0-9_]([a-zA-Z0-9\\-_]){0,61})?[a-zA-Z0-9]\\.?)|\\.");
+
+    private HostBuilder() {
+
+    }
+
+    public static Host getDefaultInstance(final String defaultValue) {
+        final Matcher ipv4Matcher = IPV4_PATTERN.matcher(defaultValue);
+        final Matcher ipv6Matcher1 = IPV6_PATTERN1.matcher(defaultValue);
+        final Matcher ipv6Matcher2 = IPV6_PATTERN2.matcher(defaultValue);
+        final Matcher domainMatcher = DOMAIN_PATTERN.matcher(defaultValue);
+
+        List<String> matchers = new ArrayList<>(3);
+        if (ipv6Matcher1.matches() || ipv6Matcher2.matches()) {
+            matchers.add(Ipv6Address.class.getSimpleName());
+        }
+
+        // Ipv4 and Domain Name patterns are not exclusive
+        // Address 127.0.0.1 matches both patterns
+        // This way Ipv4 address is preferred to domain name
+        if (ipv4Matcher.matches()) {
+            matchers.add(Ipv4Address.class.getSimpleName());
+        } else if (domainMatcher.matches()) {
+            matchers.add(DomainName.class.getSimpleName());
+        }
+
+        if (matchers.size() > 1) {
+            throw new IllegalArgumentException("Cannot create Host from " + defaultValue + ". Value is ambigious for "
+                    + matchers);
+        }
+
+        if (ipv4Matcher.matches()) {
+            Ipv4Address ipv4 = new Ipv4Address(defaultValue);
+            IpAddress ipAddress = new IpAddress(ipv4);
+            return new Host(ipAddress);
+        }
+        if (ipv6Matcher1.matches() || ipv6Matcher2.matches()) {
+            Ipv6Address ipv6 = new Ipv6Address(defaultValue);
+            IpAddress ipAddress = new IpAddress(ipv6);
+            return new Host(ipAddress);
+        }
+        if (domainMatcher.matches()) {
+            DomainName domainName = new DomainName(defaultValue);
+            return new Host(domainName);
+        }
+        throw new IllegalArgumentException("Cannot create Host from " + defaultValue);
+    }
+
+}
diff --git a/model/ietf/ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/IpAddressBuilder.java b/model/ietf/ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/IpAddressBuilder.java
new file mode 100644 (file)
index 0000000..26bfa2d
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ **/
+public final class IpAddressBuilder {
+    private static final Pattern IPV4_PATTERN =
+            Pattern.compile("(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(%[\\p{N}\\p{L}]+)?");
+    private static final Pattern IPV6_PATTERN1 =
+            Pattern.compile("((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(%[\\p{N}\\p{L}]+)?");
+    private static final Pattern IPV6_PATTERN2 =
+            Pattern.compile("(([^:]+:){6}(([^:]+:[^:]+)|(.*\\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(%.+)?");
+
+    private IpAddressBuilder() {
+
+    }
+
+    public static IpAddress getDefaultInstance(final String defaultValue) {
+        final Matcher ipv4Matcher = IPV4_PATTERN.matcher(defaultValue);
+
+        if (ipv4Matcher.matches()) {
+            if (IPV6_PATTERN1.matcher(defaultValue).matches() && IPV6_PATTERN2.matcher(defaultValue).matches()) {
+                throw new IllegalArgumentException(
+                        String.format("Cannot create IpAddress from \"%s\", matches both %s and %s",
+                                defaultValue, Ipv4Address.class.getSimpleName(), Ipv6Address.class.getSimpleName()));
+
+            }
+            return new IpAddress(new Ipv4Address(defaultValue));
+        } else if (IPV6_PATTERN1.matcher(defaultValue).matches() && IPV6_PATTERN2.matcher(defaultValue).matches()) {
+            return new IpAddress(new Ipv6Address(defaultValue));
+        } else {
+            throw new IllegalArgumentException("Cannot create IpAddress from " + defaultValue);
+        }
+    }
+
+}
diff --git a/model/ietf/ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/IpPrefixBuilder.java b/model/ietf/ietf-inet-types/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/IpPrefixBuilder.java
new file mode 100644 (file)
index 0000000..4d15116
--- /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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ **/
+public final class IpPrefixBuilder {
+    private static final Pattern IPV4_PATTERN = Pattern.compile("(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])/(([0-9])|([1-2][0-9])|(3[0-2]))");
+    private static final Pattern IPV6_PATTERN1 = Pattern.compile("((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))");
+    private static final Pattern IPV6_PATTERN2 = Pattern.compile("(([^:]+:){6}(([^:]+:[^:]+)|(.*\\..*)))|((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)(/.+)");
+
+    private IpPrefixBuilder() {
+
+    }
+
+    public static IpPrefix getDefaultInstance(final String defaultValue) {
+        final Matcher ipv4Matcher = IPV4_PATTERN.matcher(defaultValue);
+
+        if (ipv4Matcher.matches()) {
+            if (IPV6_PATTERN1.matcher(defaultValue).matches() && IPV6_PATTERN2.matcher(defaultValue).matches()) {
+                throw new IllegalArgumentException(
+                        String.format("Cannot create IpPrefix from \"%s\", matches both %s and %s",
+                                defaultValue, Ipv4Address.class.getSimpleName(), Ipv6Address.class.getSimpleName()));
+
+            }
+            return new IpPrefix(new Ipv4Prefix(defaultValue));
+        } else if (IPV6_PATTERN1.matcher(defaultValue).matches() && IPV6_PATTERN2.matcher(defaultValue).matches()) {
+            return new IpPrefix(new Ipv6Prefix(defaultValue));
+        } else {
+            throw new IllegalArgumentException("Cannot create IpPrefix from " + defaultValue);
+        }
+    }
+
+}
diff --git a/model/ietf/ietf-inet-types/src/main/yang/ietf-inet-types.yang b/model/ietf/ietf-inet-types/src/main/yang/ietf-inet-types.yang
new file mode 100644 (file)
index 0000000..de20feb
--- /dev/null
@@ -0,0 +1,418 @@
+ module ietf-inet-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+   prefix "inet";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types for Internet addresses and related things.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of protocol field related types ***/
+
+   typedef ip-version {
+     type enumeration {
+       enum unknown {
+         value "0";
+         description
+          "An unknown or unspecified version of the Internet protocol.";
+       }
+       enum ipv4 {
+         value "1";
+         description
+          "The IPv4 protocol as defined in RFC 791.";
+       }
+       enum ipv6 {
+         value "2";
+         description
+          "The IPv6 protocol as defined in RFC 2460.";
+       }
+     }
+     description
+      "This value represents the version of the IP protocol.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetVersion textual convention of the SMIv2.";
+     reference
+      "RFC  791: Internet Protocol
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   typedef dscp {
+     type uint8 {
+       range "0..63";
+     }
+     description
+      "The dscp type represents a Differentiated Services Code-Point
+       that may be used for marking packets in a traffic stream.
+
+       In the value set and its semantics, this type is equivalent
+       to the Dscp textual convention of the SMIv2.";
+     reference
+      "RFC 3289: Management Information Base for the Differentiated
+                 Services Architecture
+       RFC 2474: Definition of the Differentiated Services Field
+                 (DS Field) in the IPv4 and IPv6 Headers
+       RFC 2780: IANA Allocation Guidelines For Values In
+                 the Internet Protocol and Related Headers";
+   }
+
+   typedef ipv6-flow-label {
+     type uint32 {
+       range "0..1048575";
+     }
+     description
+      "The flow-label type represents flow identifier or Flow Label
+       in an IPv6 packet header that may be used to discriminate
+       traffic flows.
+
+       In the value set and its semantics, this type is equivalent
+       to the IPv6FlowLabel textual convention of the SMIv2.";
+     reference
+      "RFC 3595: Textual Conventions for IPv6 Flow Label
+       RFC 2460: Internet Protocol, Version 6 (IPv6) Specification";
+   }
+
+   typedef port-number {
+     type uint16 {
+       range "0..65535";
+     }
+     description
+      "The port-number type represents a 16-bit port number of an
+       Internet transport layer protocol such as UDP, TCP, DCCP, or
+       SCTP.  Port numbers are assigned by IANA.  A current list of
+       all assignments is available from <http://www.iana.org/>.
+
+       Note that the port number value zero is reserved by IANA.  In
+       situations where the value zero does not make sense, it can
+       be excluded by subtyping the port-number type.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetPortNumber textual convention of the SMIv2.";
+     reference
+      "RFC  768: User Datagram Protocol
+       RFC  793: Transmission Control Protocol
+       RFC 4960: Stream Control Transmission Protocol
+       RFC 4340: Datagram Congestion Control Protocol (DCCP)
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of autonomous system related types ***/
+
+   typedef as-number {
+     type uint32;
+     description
+      "The as-number type represents autonomous system numbers
+       which identify an Autonomous System (AS).  An AS is a set
+       of routers under a single technical administration, using
+       an interior gateway protocol and common metrics to route
+       packets within the AS, and using an exterior gateway
+       protocol to route packets to other ASs'.  IANA maintains
+       the AS number space and has delegated large parts to the
+       regional registries.
+
+       Autonomous system numbers were originally limited to 16
+       bits.  BGP extensions have enlarged the autonomous system
+       number space to 32 bits.  This type therefore uses an uint32
+       base type without a range restriction in order to support
+       a larger autonomous system number space.
+
+       In the value set and its semantics, this type is equivalent
+       to the InetAutonomousSystemNumber textual convention of
+       the SMIv2.";
+     reference
+      "RFC 1930: Guidelines for creation, selection, and registration
+                 of an Autonomous System (AS)
+       RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+       RFC 4893: BGP Support for Four-octet AS Number Space
+       RFC 4001: Textual Conventions for Internet Network Addresses";
+   }
+
+   /*** collection of IP address and hostname related types ***/
+
+   typedef ip-address {
+     type union {
+       type inet:ipv4-address;
+       type inet:ipv6-address;
+     }
+     description
+      "The ip-address type represents an IP address and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-address {
+     type string {
+       pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '(%[\p{N}\p{L}]+)?';
+     }
+     description
+       "The ipv4-address type represents an IPv4 address in
+        dotted-quad notation.  The IPv4 address may include a zone
+        index, separated by a % sign.
+
+        The zone index is used to disambiguate identical address
+        values.  For link-local addresses, the zone index will
+        typically be the interface index number or the name of an
+        interface.  If the zone index is not present, the default
+        zone of the device will be used.
+
+        The canonical format for the zone index is the numerical
+        format";
+   }
+
+   typedef ipv6-address {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(%[\p{N}\p{L}]+)?';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(%.+)?';
+     }
+     description
+      "The ipv6-address type represents an IPv6 address in full,
+       mixed, shortened, and shortened-mixed notation.  The IPv6
+       address may include a zone index, separated by a % sign.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format of IPv6 addresses uses the compressed
+       format described in RFC 4291, Section 2.2, item 2 with the
+       following additional rules: the :: substitution must be
+       applied to the longest sequence of all-zero 16-bit chunks
+       in an IPv6 address.  If there is a tie, the first sequence
+       of all-zero 16-bit chunks is replaced by ::.  Single
+       all-zero 16-bit chunks are not compressed.  The canonical
+       format uses lowercase characters and leading zeros are
+       not allowed.  The canonical format for the zone index is
+       the numerical format as described in RFC 4007, Section
+       11.2.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture
+       RFC 4007: IPv6 Scoped Address Architecture
+       RFC 5952: A Recommendation for IPv6 Address Text Representation";
+   }
+
+   typedef ip-prefix {
+     type union {
+       type inet:ipv4-prefix;
+       type inet:ipv6-prefix;
+     }
+     description
+      "The ip-prefix type represents an IP prefix and is IP
+       version neutral.  The format of the textual representations
+       implies the IP version.";
+   }
+
+   typedef ipv4-prefix {
+     type string {
+       pattern
+          '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+        +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+        + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+     }
+     description
+      "The ipv4-prefix type represents an IPv4 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal to 32.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The canonical format of an IPv4 prefix has all bits of
+       the IPv4 address set to zero that are not part of the
+       IPv4 prefix.";
+   }
+
+   typedef ipv6-prefix {
+     type string {
+       pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+             + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+             + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+             + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+             + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+       pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+             + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+             + '(/.+)';
+     }
+     description
+      "The ipv6-prefix type represents an IPv6 address prefix.
+       The prefix length is given by the number following the
+       slash character and must be less than or equal 128.
+
+       A prefix length value of n corresponds to an IP address
+       mask that has n contiguous 1-bits from the most
+       significant bit (MSB) and all other bits set to 0.
+
+       The IPv6 address should have all bits that do not belong
+       to the prefix set to zero.
+
+       The canonical format of an IPv6 prefix has all bits of
+       the IPv6 address set to zero that are not part of the
+       IPv6 prefix.  Furthermore, IPv6 address is represented
+       in the compressed format described in RFC 4291, Section
+       2.2, item 2 with the following additional rules: the ::
+       substitution must be applied to the longest sequence of
+       all-zero 16-bit chunks in an IPv6 address.  If there is
+       a tie, the first sequence of all-zero 16-bit chunks is
+       replaced by ::.  Single all-zero 16-bit chunks are not
+       compressed.  The canonical format uses lowercase
+       characters and leading zeros are not allowed.";
+     reference
+      "RFC 4291: IP Version 6 Addressing Architecture";
+   }
+
+   /*** collection of domain name and URI types ***/
+
+   typedef domain-name {
+     type string {
+       pattern '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+            +  '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+            +  '|\.';
+       length "1..253";
+     }
+     description
+      "The domain-name type represents a DNS domain name.  The
+       name SHOULD be fully qualified whenever possible.
+
+       Internet domain names are only loosely specified.  Section
+       3.5 of RFC 1034 recommends a syntax (modified in Section
+       2.1 of RFC 1123).  The pattern above is intended to allow
+       for current practice in domain name use, and some possible
+       future expansion.  It is designed to hold various types of
+       domain names, including names used for A or AAAA records
+       (host names) and other records, such as SRV records.  Note
+       that Internet host names have a stricter syntax (described
+       in RFC 952) than the DNS recommendations in RFCs 1034 and
+       1123, and that systems that want to store host names in
+       schema nodes using the domain-name type are recommended to
+       adhere to this stricter standard to ensure interoperability.
+
+       The encoding of DNS names in the DNS protocol is limited
+       to 255 characters.  Since the encoding consists of labels
+       prefixed by a length bytes and there is a trailing NULL
+       byte, only 253 characters can appear in the textual dotted
+       notation.
+
+       The description clause of schema nodes using the domain-name
+       type MUST describe when and how these names are resolved to
+       IP addresses.  Note that the resolution of a domain-name value
+       may require to query multiple DNS records (e.g., A for IPv4
+       and AAAA for IPv6).  The order of the resolution process and
+       which DNS record takes precedence can either be defined
+       explicitely or it may depend on the configuration of the
+       resolver.
+
+       Domain-name values use the US-ASCII encoding.  Their canonical
+       format uses lowercase US-ASCII characters.  Internationalized
+       domain names MUST be encoded in punycode as described in RFC
+       3492";
+     reference
+      "RFC  952: DoD Internet Host Table Specification
+       RFC 1034: Domain Names - Concepts and Facilities
+       RFC 1123: Requirements for Internet Hosts -- Application
+                 and Support
+       RFC 2782: A DNS RR for specifying the location of services
+                 (DNS SRV)
+       RFC 3492: Punycode: A Bootstring encoding of Unicode for
+                 Internationalized Domain Names in Applications
+                 (IDNA)
+       RFC 5891: Internationalizing Domain Names in Applications
+                 (IDNA): Protocol";
+   }
+
+   typedef host {
+     type union {
+       type inet:ip-address;
+       type inet:domain-name;
+     }
+     description
+      "The host type represents either an IP address or a DNS
+       domain name.";
+   }
+
+   typedef uri {
+     type string;
+     description
+      "The uri type represents a Uniform Resource Identifier
+       (URI) as defined by STD 66.
+
+       Objects using the uri type MUST be in US-ASCII encoding,
+       and MUST be normalized as described by RFC 3986 Sections
+       6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+       percent-encoding is removed, and all case-insensitive
+       characters are set to lowercase except for hexadecimal
+       digits, which are normalized to uppercase as described in
+       Section 6.2.2.1.
+
+       The purpose of this normalization is to help provide
+       unique URIs.  Note that this normalization is not
+       sufficient to provide uniqueness.  Two URIs that are
+       textually distinct after this normalization may still be
+       equivalent.
+
+       Objects using the uri type may restrict the schemes that
+       they permit.  For example, 'data:' and 'urn:' schemes
+       might not be appropriate.
+
+       A zero-length URI is not a valid URI.  This can be used to
+       express 'URI absent' where required.
+
+       In the value set and its semantics, this type is equivalent
+       to the Uri SMIv2 textual convention defined in RFC 5017.";
+     reference
+      "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+       RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                 Group: Uniform Resource Identifiers (URIs), URLs,
+                 and Uniform Resource Names (URNs): Clarifications
+                 and Recommendations
+       RFC 5017: MIB Textual Conventions for Uniform Resource
+                 Identifiers (URIs)";
+   }
+
+ }
diff --git a/model/ietf/ietf-inet-types/src/test/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/HostBuilderTest.java b/model/ietf/ietf-inet-types/src/test/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/inet/types/rev100924/HostBuilderTest.java
new file mode 100644 (file)
index 0000000..d2259d0
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class HostBuilderTest {
+
+    @Test
+    public void testGetDefaultInstanceIpv4() throws Exception {
+        final Host host = HostBuilder.getDefaultInstance("127.0.0.1");
+        assertEquals(new Host(new IpAddress(new Ipv4Address("127.0.0.1"))), host);
+    }
+
+    @Test
+    public void testGetDefaultInstanceIpv6() throws Exception {
+        testIpv6("1234:5678:9abc:def1:2345:6789:abcd:ef12");
+    }
+
+    private void testIpv6(final String ivp6string) {
+        final Host host = HostBuilder.getDefaultInstance(ivp6string);
+        assertEquals(new Host(new IpAddress(new Ipv6Address(ivp6string))), host);
+    }
+
+    @Test
+    public void testGetDefaultInstanceDomain() throws Exception {
+        final Host host = HostBuilder.getDefaultInstance("localhost");
+        assertEquals(new Host(new DomainName("localhost")), host);
+    }
+}
\ No newline at end of file
diff --git a/model/ietf/ietf-interfaces/pom.xml b/model/ietf/ietf-interfaces/pom.xml
new file mode 100644 (file)
index 0000000..ac56197
--- /dev/null
@@ -0,0 +1,54 @@
+<?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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-interfaces</artifactId>
+    <version>2014.05.08.8-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-yang-types-20130715</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/model/ietf/ietf-interfaces/src/main/yang/ietf-interfaces.yang b/model/ietf/ietf-interfaces/src/main/yang/ietf-interfaces.yang
new file mode 100644 (file)
index 0000000..3689c89
--- /dev/null
@@ -0,0 +1,726 @@
+module ietf-interfaces {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-interfaces";
+  prefix if;
+
+  import ietf-yang-types {
+    prefix yang;
+    revision-date "2013-07-15";
+  }
+
+  organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+  contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: Thomas Nadeau
+               <mailto:tnadeau@lucidvision.com>
+
+     WG Chair: Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>
+
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+
+  description
+    "This module contains a collection of YANG definitions for
+     managing network interfaces.
+
+     Copyright (c) 2014 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 7223; see
+     the RFC itself for full legal notices.";
+
+  revision 2014-05-08 {
+    description
+      "Initial revision.";
+    reference
+      "RFC 7223: A YANG Data Model for Interface Management";
+  }
+
+  /*
+   * Typedefs
+   */
+
+  typedef interface-ref {
+    type leafref {
+      path "/if:interfaces/if:interface/if:name";
+    }
+    description
+      "This type is used by data models that need to reference
+       configured interfaces.";
+  }
+
+  typedef interface-state-ref {
+    type leafref {
+      path "/if:interfaces-state/if:interface/if:name";
+    }
+    description
+      "This type is used by data models that need to reference
+       the operationally present interfaces.";
+  }
+
+  /*
+   * Identities
+   */
+
+  identity interface-type {
+    description
+      "Base identity from which specific interface types are
+       derived.";
+  }
+
+  /*
+   * Features
+   */
+
+  feature arbitrary-names {
+    description
+      "This feature indicates that the device allows user-controlled
+       interfaces to be named arbitrarily.";
+  }
+  feature pre-provisioning {
+    description
+      "This feature indicates that the device supports
+       pre-provisioning of interface configuration, i.e., it is
+       possible to configure an interface whose physical interface
+       hardware is not present on the device.";
+  }
+
+  feature if-mib {
+    description
+      "This feature indicates that the device implements
+       the IF-MIB.";
+    reference
+      "RFC 2863: The Interfaces Group MIB";
+  }
+
+  /*
+   * Configuration data nodes
+   */
+
+  container interfaces {
+    description
+      "Interface configuration parameters.";
+
+    list interface {
+      key "name";
+
+      description
+        "The list of configured interfaces on the device.
+
+         The operational state of an interface is available in the
+         /interfaces-state/interface list.  If the configuration of a
+         system-controlled interface cannot be used by the system
+         (e.g., the interface hardware present does not match the
+         interface type), then the configuration is not applied to
+         the system-controlled interface shown in the
+         /interfaces-state/interface list.  If the configuration
+         of a user-controlled interface cannot be used by the system,
+         the configured interface is not instantiated in the
+         /interfaces-state/interface list.";
+
+     leaf name {
+        type string;
+        description
+          "The name of the interface.
+
+           A device MAY restrict the allowed values for this leaf,
+           possibly depending on the type of the interface.
+           For system-controlled interfaces, this leaf is the
+           device-specific name of the interface.  The 'config false'
+           list /interfaces-state/interface contains the currently
+           existing interfaces on the device.
+
+           If a client tries to create configuration for a
+           system-controlled interface that is not present in the
+           /interfaces-state/interface list, the server MAY reject
+           the request if the implementation does not support
+           pre-provisioning of interfaces or if the name refers to
+           an interface that can never exist in the system.  A
+           NETCONF server MUST reply with an rpc-error with the
+           error-tag 'invalid-value' in this case.
+
+           If the device supports pre-provisioning of interface
+           configuration, the 'pre-provisioning' feature is
+           advertised.
+
+           If the device allows arbitrarily named user-controlled
+           interfaces, the 'arbitrary-names' feature is advertised.
+
+           When a configured user-controlled interface is created by
+           the system, it is instantiated with the same name in the
+           /interface-state/interface list.";
+      }
+
+      leaf description {
+        type string;
+        description
+          "A textual description of the interface.
+
+           A server implementation MAY map this leaf to the ifAlias
+           MIB object.  Such an implementation needs to use some
+           mechanism to handle the differences in size and characters
+           allowed between this leaf and ifAlias.  The definition of
+           such a mechanism is outside the scope of this document.
+
+           Since ifAlias is defined to be stored in non-volatile
+           storage, the MIB implementation MUST map ifAlias to the
+           value of 'description' in the persistently stored
+           datastore.
+
+           Specifically, if the device supports ':startup', when
+           ifAlias is read the device MUST return the value of
+           'description' in the 'startup' datastore, and when it is
+           written, it MUST be written to the 'running' and 'startup'
+           datastores.  Note that it is up to the implementation to
+
+           decide whether to modify this single leaf in 'startup' or
+           perform an implicit copy-config from 'running' to
+           'startup'.
+
+           If the device does not support ':startup', ifAlias MUST
+           be mapped to the 'description' leaf in the 'running'
+           datastore.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifAlias";
+      }
+
+      leaf type {
+        type identityref {
+          base interface-type;
+        }
+        mandatory true;
+        description
+          "The type of the interface.
+
+           When an interface entry is created, a server MAY
+           initialize the type leaf with a valid value, e.g., if it
+           is possible to derive the type from the name of the
+           interface.
+
+           If a client tries to set the type of an interface to a
+           value that can never be used by the system, e.g., if the
+           type is not supported or if the type does not match the
+           name of the interface, the server MUST reject the request.
+           A NETCONF server MUST reply with an rpc-error with the
+           error-tag 'invalid-value' in this case.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifType";
+      }
+
+      leaf enabled {
+        type boolean;
+        default "true";
+        description
+          "This leaf contains the configured, desired state of the
+           interface.
+
+           Systems that implement the IF-MIB use the value of this
+           leaf in the 'running' datastore to set
+           IF-MIB.ifAdminStatus to 'up' or 'down' after an ifEntry
+           has been initialized, as described in RFC 2863.
+
+
+
+           Changes in this leaf in the 'running' datastore are
+           reflected in ifAdminStatus, but if ifAdminStatus is
+           changed over SNMP, this leaf is not affected.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+      }
+
+      leaf link-up-down-trap-enable {
+        if-feature if-mib;
+        type enumeration {
+          enum enabled {
+            value 1;
+          }
+          enum disabled {
+            value 2;
+          }
+        }
+        description
+          "Controls whether linkUp/linkDown SNMP notifications
+           should be generated for this interface.
+
+           If this node is not configured, the value 'enabled' is
+           operationally used by the server for interfaces that do
+           not operate on top of any other interface (i.e., there are
+           no 'lower-layer-if' entries), and 'disabled' otherwise.";
+        reference
+          "RFC 2863: The Interfaces Group MIB -
+                     ifLinkUpDownTrapEnable";
+      }
+    }
+  }
+
+  /*
+   * Operational state data nodes
+   */
+
+  container interfaces-state {
+    config false;
+    description
+      "Data nodes for the operational state of interfaces.";
+
+    list interface {
+      key "name";
+
+
+
+
+
+      description
+        "The list of interfaces on the device.
+
+         System-controlled interfaces created by the system are
+         always present in this list, whether they are configured or
+         not.";
+
+      leaf name {
+        type string;
+        description
+          "The name of the interface.
+
+           A server implementation MAY map this leaf to the ifName
+           MIB object.  Such an implementation needs to use some
+           mechanism to handle the differences in size and characters
+           allowed between this leaf and ifName.  The definition of
+           such a mechanism is outside the scope of this document.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifName";
+      }
+
+      leaf type {
+        type identityref {
+          base interface-type;
+        }
+        mandatory true;
+        description
+          "The type of the interface.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifType";
+      }
+
+      leaf admin-status {
+        if-feature if-mib;
+        type enumeration {
+          enum up {
+            value 1;
+            description
+              "Ready to pass packets.";
+          }
+          enum down {
+            value 2;
+            description
+              "Not ready to pass packets and not in some test mode.";
+          }
+
+
+
+          enum testing {
+            value 3;
+            description
+              "In some test mode.";
+          }
+        }
+        mandatory true;
+        description
+          "The desired state of the interface.
+
+           This leaf has the same read semantics as ifAdminStatus.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifAdminStatus";
+      }
+
+      leaf oper-status {
+        type enumeration {
+          enum up {
+            value 1;
+            description
+              "Ready to pass packets.";
+          }
+          enum down {
+            value 2;
+            description
+              "The interface does not pass any packets.";
+          }
+          enum testing {
+            value 3;
+            description
+              "In some test mode.  No operational packets can
+               be passed.";
+          }
+          enum unknown {
+            value 4;
+            description
+              "Status cannot be determined for some reason.";
+          }
+          enum dormant {
+            value 5;
+            description
+              "Waiting for some external event.";
+          }
+          enum not-present {
+            value 6;
+            description
+              "Some component (typically hardware) is missing.";
+          }
+          enum lower-layer-down {
+            value 7;
+            description
+              "Down due to state of lower-layer interface(s).";
+          }
+        }
+        mandatory true;
+        description
+          "The current operational state of the interface.
+
+           This leaf has the same semantics as ifOperStatus.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifOperStatus";
+      }
+
+      leaf last-change {
+        type yang:date-and-time;
+        description
+          "The time the interface entered its current operational
+           state.  If the current state was entered prior to the
+           last re-initialization of the local network management
+           subsystem, then this node is not present.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifLastChange";
+      }
+
+      leaf if-index {
+        if-feature if-mib;
+        type int32 {
+          range "1..2147483647";
+        }
+        mandatory true;
+        description
+          "The ifIndex value for the ifEntry represented by this
+           interface.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifIndex";
+      }
+
+      leaf phys-address {
+        type yang:phys-address;
+        description
+          "The interface's address at its protocol sub-layer.  For
+           example, for an 802.x interface, this object normally
+           contains a Media Access Control (MAC) address.  The
+           interface's media-specific modules must define the bit
+
+
+           and byte ordering and the format of the value of this
+           object.  For interfaces that do not have such an address
+           (e.g., a serial line), this node is not present.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifPhysAddress";
+      }
+
+      leaf-list higher-layer-if {
+        type interface-state-ref;
+        description
+          "A list of references to interfaces layered on top of this
+           interface.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifStackTable";
+      }
+
+      leaf-list lower-layer-if {
+        type interface-state-ref;
+        description
+          "A list of references to interfaces layered underneath this
+           interface.";
+        reference
+          "RFC 2863: The Interfaces Group MIB - ifStackTable";
+      }
+
+      leaf speed {
+        type yang:gauge64;
+        units "bits/second";
+        description
+            "An estimate of the interface's current bandwidth in bits
+             per second.  For interfaces that do not vary in
+             bandwidth or for those where no accurate estimation can
+             be made, this node should contain the nominal bandwidth.
+             For interfaces that have no concept of bandwidth, this
+             node is not present.";
+        reference
+          "RFC 2863: The Interfaces Group MIB -
+                     ifSpeed, ifHighSpeed";
+      }
+
+
+
+
+
+
+
+
+
+      container statistics {
+        description
+          "A collection of interface-related statistics objects.";
+
+        leaf discontinuity-time {
+          type yang:date-and-time;
+          mandatory true;
+          description
+            "The time on the most recent occasion at which any one or
+             more of this interface's counters suffered a
+             discontinuity.  If no such discontinuities have occurred
+             since the last re-initialization of the local management
+             subsystem, then this node contains the time the local
+             management subsystem re-initialized itself.";
+        }
+
+        leaf in-octets {
+          type yang:counter64;
+          description
+            "The total number of octets received on the interface,
+             including framing characters.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCInOctets";
+        }
+
+        leaf in-unicast-pkts {
+          type yang:counter64;
+          description
+            "The number of packets, delivered by this sub-layer to a
+             higher (sub-)layer, that were not addressed to a
+             multicast or broadcast address at this sub-layer.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCInUcastPkts";
+        }
+
+
+
+
+        leaf in-broadcast-pkts {
+          type yang:counter64;
+          description
+            "The number of packets, delivered by this sub-layer to a
+             higher (sub-)layer, that were addressed to a broadcast
+             address at this sub-layer.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCInBroadcastPkts";
+        }
+
+        leaf in-multicast-pkts {
+          type yang:counter64;
+          description
+            "The number of packets, delivered by this sub-layer to a
+             higher (sub-)layer, that were addressed to a multicast
+             address at this sub-layer.  For a MAC-layer protocol,
+             this includes both Group and Functional addresses.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCInMulticastPkts";
+        }
+
+        leaf in-discards {
+          type yang:counter32;
+          description
+            "The number of inbound packets that were chosen to be
+             discarded even though no errors had been detected to
+             prevent their being deliverable to a higher-layer
+             protocol.  One possible reason for discarding such a
+             packet could be to free up buffer space.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+
+
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifInDiscards";
+        }
+
+        leaf in-errors {
+          type yang:counter32;
+          description
+            "For packet-oriented interfaces, the number of inbound
+             packets that contained errors preventing them from being
+             deliverable to a higher-layer protocol.  For character-
+             oriented or fixed-length interfaces, the number of
+             inbound transmission units that contained errors
+             preventing them from being deliverable to a higher-layer
+             protocol.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifInErrors";
+        }
+
+        leaf in-unknown-protos {
+          type yang:counter32;
+          description
+            "For packet-oriented interfaces, the number of packets
+             received via the interface that were discarded because
+             of an unknown or unsupported protocol.  For
+             character-oriented or fixed-length interfaces that
+             support protocol multiplexing, the number of
+             transmission units received via the interface that were
+             discarded because of an unknown or unsupported protocol.
+             For any interface that does not support protocol
+             multiplexing, this counter is not present.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifInUnknownProtos";
+        }
+
+
+
+
+
+        leaf out-octets {
+          type yang:counter64;
+          description
+            "The total number of octets transmitted out of the
+             interface, including framing characters.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCOutOctets";
+        }
+
+        leaf out-unicast-pkts {
+          type yang:counter64;
+          description
+            "The total number of packets that higher-level protocols
+             requested be transmitted, and that were not addressed
+             to a multicast or broadcast address at this sub-layer,
+             including those that were discarded or not sent.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifHCOutUcastPkts";
+        }
+
+        leaf out-broadcast-pkts {
+          type yang:counter64;
+          description
+            "The total number of packets that higher-level protocols
+             requested be transmitted, and that were addressed to a
+             broadcast address at this sub-layer, including those
+             that were discarded or not sent.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCOutBroadcastPkts";
+        }
+
+
+        leaf out-multicast-pkts {
+          type yang:counter64;
+          description
+            "The total number of packets that higher-level protocols
+             requested be transmitted, and that were addressed to a
+             multicast address at this sub-layer, including those
+             that were discarded or not sent.  For a MAC-layer
+             protocol, this includes both Group and Functional
+             addresses.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB -
+                       ifHCOutMulticastPkts";
+        }
+
+        leaf out-discards {
+          type yang:counter32;
+          description
+            "The number of outbound packets that were chosen to be
+             discarded even though no errors had been detected to
+             prevent their being transmitted.  One possible reason
+             for discarding such a packet could be to free up buffer
+             space.
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifOutDiscards";
+        }
+
+        leaf out-errors {
+          type yang:counter32;
+          description
+            "For packet-oriented interfaces, the number of outbound
+             packets that could not be transmitted because of errors.
+             For character-oriented or fixed-length interfaces, the
+             number of outbound transmission units that could not be
+             transmitted because of errors.
+
+
+
+
+             Discontinuities in the value of this counter can occur
+             at re-initialization of the management system, and at
+             other times as indicated by the value of
+             'discontinuity-time'.";
+          reference
+            "RFC 2863: The Interfaces Group MIB - ifOutErrors";
+        }
+      }
+    }
+  }
+}
diff --git a/model/ietf/ietf-restconf/pom.xml b/model/ietf/ietf-restconf/pom.xml
new file mode 100644 (file)
index 0000000..f25ffe7
--- /dev/null
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (c) 2014 Brocade Communications 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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-restconf</artifactId>
+    <version>2013.10.19.8-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+        </dependency>
+        <!--  TODO: We need a better way to handle versioning... -->
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-yang-types-20130715</artifactId>
+        </dependency>
+        
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/model/ietf/ietf-restconf/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/DatastoreIdentifierBuilder.java b/model/ietf/ietf-restconf/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/DatastoreIdentifierBuilder.java
new file mode 100644 (file)
index 0000000..42defe5
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2014 Brocade Communications 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019.DatastoreIdentifier.Enumeration;
+
+
+/**
+ **/
+public class DatastoreIdentifierBuilder {
+
+    public static DatastoreIdentifier getDefaultInstance(final String defaultValue) {
+        return new DatastoreIdentifier(Enumeration.valueOf(defaultValue));
+    }
+
+}
diff --git a/model/ietf/ietf-restconf/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/restconf/restconf/modules/ModuleRevisionBuilder.java b/model/ietf/ietf-restconf/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/restconf/restconf/modules/ModuleRevisionBuilder.java
new file mode 100644 (file)
index 0000000..dfd0aeb
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2015 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019.restconf.restconf.modules;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019.restconf.restconf.modules.Module.Revision;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create
+ * new instances of unions from a string representation. In some cases it is
+ * very difficult to automate it since there can be unions such as (uint32 -
+ * uint16), or (string - uint32).
+ *
+ * The reason behind putting it under src/main/java is: This class is generated
+ * in form of a stub and needs to be finished by the user. This class is
+ * generated only once to prevent loss of user code.
+ *
+ */
+public class ModuleRevisionBuilder {
+
+    public static Revision getDefaultInstance(java.lang.String defaultValue) {
+        return RevisionBuilder.getDefaultInstance(defaultValue);
+    }
+
+}
diff --git a/model/ietf/ietf-restconf/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/restconf/restconf/modules/RevisionBuilder.java b/model/ietf/ietf-restconf/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/restconf/restconf/modules/RevisionBuilder.java
new file mode 100644 (file)
index 0000000..d09646a
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 Brocade Communications 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019.restconf.restconf.modules;
+
+import java.util.regex.Pattern;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019.RevisionIdentifier;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019.restconf.restconf.modules.Module.Revision;
+
+/**
+**/
+public class RevisionBuilder {
+
+    /**
+     * Defines the pattern for revisions. NOTE: This pattern will likely be
+     * updated in future versions of the ietf and should be adjusted accordingly
+     */
+    private static final Pattern REVISION_PATTERN = Pattern.compile("\\d{4}-\\d{2}-\\d{2}");
+
+    public static Revision getDefaultInstance(String defaultValue) {
+
+        if (defaultValue != null) {
+            if (REVISION_PATTERN.matcher(defaultValue).matches()) {
+                RevisionIdentifier id = new RevisionIdentifier(defaultValue);
+                return new Revision(id);
+            }
+            if (defaultValue.isEmpty()) {
+                return new Revision(defaultValue);
+            }
+        }
+
+        throw new IllegalArgumentException("Cannot create Revision from " + defaultValue
+                + ". Default value does not match pattern " + REVISION_PATTERN.pattern()
+                + " or empty string.");
+    }
+
+}
diff --git a/model/ietf/ietf-restconf/src/main/yang/ietf-restconf@2013-10-19.yang b/model/ietf/ietf-restconf/src/main/yang/ietf-restconf@2013-10-19.yang
new file mode 100644 (file)
index 0000000..83bb378
--- /dev/null
@@ -0,0 +1,689 @@
+module ietf-restconf {
+  namespace "urn:ietf:params:xml:ns:yang:ietf-restconf";
+  prefix "restconf";
+
+  import ietf-yang-types { prefix yang; revision-date 2013-07-15; }
+  import ietf-inet-types { prefix inet; }
+
+  organization
+    "IETF NETCONF (Network Configuration) Working Group";
+
+  contact
+    "Editor:   Andy Bierman
+               <mailto:andy@yumaworks.com>
+
+     Editor:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>
+
+     Editor:   Kent Watsen
+               <mailto:kwatsen@juniper.net>
+
+     Editor:   Rex Fernando
+               <mailto:rex@cisco.com>";
+
+  description
+    "This module contains conceptual YANG specifications
+     for the YANG Patch and error content that is used in
+     RESTCONF protocol messages. A conceptual container
+     representing the RESTCONF API nodes (media type 
+     application/yang.api).
+
+     Note that the YANG definitions within this module do not
+     represent configuration data of any kind.
+     The YANG grouping statements provide a normative syntax
+     for XML and JSON message encoding purposes.
+
+     Copyright (c) 2013 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see
+     the RFC itself for full legal notices.";
+
+  // RFC Ed.: replace XXXX with actual RFC number and remove this
+  // note.
+
+  // RFC Ed.: remove this note
+  // Note: extracted from draft-bierman-netconf-restconf-02.txt
+
+  // RFC Ed.: update the date below with the date of RFC publication
+  // and remove this note.
+  revision 2013-10-19 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: RESTCONF Protocol.";
+  }
+
+  typedef data-resource-identifier {
+    type string {
+      length "1 .. max";
+    }
+    description
+      "Contains a Data Resource Identifier formatted string
+       to identify a specific data node. The data node that
+       uses this data type SHOULD define the document root
+       for data resource identifiers.  The default document
+       root is the target datastore conceptual root node.
+       Data resource identifiers are defined relative to
+       this document root.";
+    reference
+      "RFC XXXX: [sec. 5.3.1.1 ABNF For Data Resource Identifiers]";
+  }
+
+  // this typedef is TBD; not currently used
+  typedef datastore-identifier {
+    type union {
+      type enumeration {
+        enum candidate {
+          description
+            "Identifies the NETCONF shared candidate datastore.";
+          reference
+            "RFC 6241, section 8.3";
+        }
+        enum running {
+          description
+            "Identifies the NETCONF running datastore.";
+          reference
+            "RFC 6241, section 5.1";
+        }
+        enum startup {
+          description
+            "Identifies the NETCONF startup datastore.";
+          reference
+            "RFC 6241, section 8.7";
+        }
+      }
+      type string;
+    }
+    description
+      "Contains a string to identify a specific datastore.
+       The enumerated datastore identifier values are
+       reserved for standard datastore names.";
+  }
+
+  typedef revision-identifier {
+    type string {
+      pattern '\d{4}-\d{2}-\d{2}';
+    }
+    description
+      "Represents a specific date in YYYY-MM-DD format.
+       TBD: make pattern more precise to exclude leading zeros.";
+  }
+
+  grouping yang-patch {
+
+    description
+      "A grouping that contains a YANG container
+       representing the syntax and semantics of a
+       YANG Patch edit request message.";
+
+    container yang-patch {
+      description
+        "Represents a conceptual sequence of datastore edits,
+         called a patch. Each patch is given a client-assigned
+         patch identifier. Each edit MUST be applied
+         in ascending order, and all edits MUST be applied.
+         If any errors occur, then the target datastore MUST NOT
+         be changed by the patch operation.
+  
+         A patch MUST be validated by the server to be a 
+         well-formed message before any of the patch edits
+         are validated or attempted.
+  
+         YANG datastore validation (defined in RFC 6020, section
+         8.3.3) is performed after all edits have been
+         individually validated.
+  
+         It is possible for a datastore constraint violation to occur
+         due to any node in the datastore, including nodes not
+         included in the edit list. Any validation errors MUST
+         be reported in the reply message.";
+  
+      reference
+        "RFC 6020, section 8.3.";
+  
+      leaf patch-id {
+        type string;
+        description
+          "An arbitrary string provided by the client to identify
+           the entire patch.  This value SHOULD be present in any
+           audit logging records generated by the server for the
+           patch. Error messages returned by the server pertaining
+           to this patch will be identified by this patch-id value.";
+      }
+
+      leaf comment {
+        type string {
+          length "0 .. 1024";
+        }
+        description
+          "An arbitrary string provided by the client to describe
+           the entire patch.  This value SHOULD be present in any
+           audit logging records generated by the server for the
+           patch.";
+      }
+  
+      list edit {
+        key edit-id;
+        ordered-by user;
+
+        description
+          "Represents one edit within the YANG Patch
+           request message.";
+
+        leaf edit-id {
+          type string;
+          description
+            "Arbitrary string index for the edit.
+             Error messages returned by the server pertaining
+             to a specific edit will be identified by this
+             value.";
+        }
+  
+        leaf operation {
+          type enumeration {
+            enum create {
+              description
+                "The target data node is created using the
+                 supplied value, only if it does not already
+                 exist.";
+            }
+            enum delete {
+              description
+                "Delete the target node, only if the data resource
+                 currently exists, otherwise return an error.";
+            }
+            enum insert {
+              description
+                "Insert the supplied value into a user-ordered
+                 list or leaf-list entry. The target node must
+                 represent a new data resource.";
+            }
+            enum merge {
+              description
+                "The supplied value is merged with the target data
+                 node.";
+            }
+            enum move {
+              description
+                "Move the target node. Reorder a user-ordered
+                 list or leaf-list. The target node must represent
+                 an existing data resource.";
+            }
+            enum replace {
+              description
+                "The supplied value is used to replace the target
+                 data node.";
+            }
+            enum remove {
+              description
+                "Delete the target node if it currently exists.";
+            }
+          }
+          mandatory true;
+          description
+            "The datastore operation requested for the associated
+             edit entry";
+        }
+  
+        leaf target {
+          type data-resource-identifier;
+          mandatory true;
+          description
+            "Identifies the target data resource for the edit
+             operation.";
+        }
+  
+        leaf point {
+          when "(../operation = 'insert' or " +
+            "../operation = 'move') and " +
+            "(../where = 'before' or ../where = 'after')" {
+            description
+              "Point leaf only applies for insert or move
+               operations, before or after an existing entry.";
+          }
+          type data-resource-identifier;
+          description
+            "The absolute URL path for the data node that is being
+             used as the insertion point or move point for the
+             target of this edit entry.";
+        }
+  
+        leaf where {
+          when "../operation = 'insert' or ../operation = 'move'" {
+            description
+              "Where leaf only applies for insert or move
+               operations.";
+          }
+          type enumeration {
+            enum before {
+              description
+                "Insert or move a data node before the data resource
+                 identified by the 'point' parameter.";
+            }
+            enum after {
+              description
+                "Insert or move a data node after the data resource
+                 identified by the 'point' parameter.";
+            }
+            enum first {
+              description
+                "Insert or move a data node so it becomes ordered
+                 as the first entry.";
+            }
+            enum last {
+              description
+                "Insert or move a data node so it becomes ordered
+                 as the last entry.";
+            }
+  
+          }
+          default last;
+          description
+            "Identifies where a data resource will be inserted or
+             moved. YANG only allows these operations for
+             list and leaf-list data nodes that are ordered-by
+             user.";
+        }
+  
+        anyxml value {
+          when "(../operation = 'create' or " +
+            "../operation = 'merge' " +
+            "or ../operation = 'replace' or " +
+            "../operation = 'insert')" {
+            description
+              "Value node only used for create, merge,
+               replace, and insert operations";
+          }
+          description
+            "Value used for this edit operation.";
+        }
+      }
+    }
+
+  } // grouping yang-patch
+
+
+  grouping yang-patch-status {
+
+    description
+      "A grouping that contains a YANG container
+       representing the syntax and semantics of
+       YANG Patch status response message.";
+    
+    container yang-patch-status {
+      description
+        "A container representing the response message
+         sent by the server after a YANG Patch edit
+         request message has been processed.";
+
+      leaf patch-id {
+        type string;
+        description
+          "The patch-id value used in the request";
+      }
+
+      choice global-status {
+        description
+          "Report global errors or complete success.
+           If there is no case selected then errors
+           are reported in the edit-status container.";
+
+        case global-errors {
+          uses errors;
+          description
+            "This container will be present if global
+             errors unrelated to a specific edit occurred.";
+        }
+        leaf ok {
+          type empty;
+          description
+            "This leaf will be present if the request succeeded
+             and there are no errors reported in the edit-status
+             container.";
+        }
+      }
+
+      container edit-status {
+        description
+          "This container will be present if there are
+           edit-specific status responses to report.";
+      
+        list edit {
+          key edit-id;
+
+          description
+            "Represents a list of status responses,
+             corresponding to edits in the YANG Patch
+             request message.  If an edit entry was
+             skipped or not reached by the server,
+             then this list will not contain a corresponding
+             entry for that edit.";
+
+          leaf edit-id {
+            type string;
+             description
+               "Response status is for the edit list entry
+                with this edit-id value.";
+          }
+          choice edit-status-choice {
+            description
+              "A choice between different types of status
+               responses for each edit entry.";
+            leaf ok {
+              type empty;
+              description
+                "This edit entry was invoked without any
+                 errors detected by the server associated
+                 with this edit.";
+            }
+            leaf location {
+              type inet:uri;
+              description
+                "Contains the Location header value that would be
+                 returned if this edit causes a new resource to be
+                 created. If the edit identified by the same edit-id
+                 value was successfully invoked and a new resource
+                 was created, then this field will be returned
+                 instead of 'ok'.";
+            }
+            case errors {
+              uses errors;
+              description
+                "The server detected errors associated with the
+                  edit identified by the same edit-id value.";
+            }
+          }
+        }
+      }
+    }
+  }  // grouping yang-patch-status
+
+
+  grouping errors {
+
+    description
+      "A grouping that contains a YANG container
+       representing the syntax and semantics of a
+       YANG Patch errors report within a response message.";
+
+    container errors {
+      config false;  // needed so list error does not need a key
+      description
+        "Represents an error report returned by the server if
+         a request results in an error.";
+  
+      list error {
+        description
+          "An entry containing information about one
+           specific error that occurred while processing
+           a RESTCONF request.";
+        reference "RFC 6241, Section 4.3";
+  
+        leaf error-type { 
+          type enumeration {
+            enum transport {
+              description "The transport layer";
+            }
+            enum rpc {
+              description "The rpc or notification layer";
+            }
+            enum protocol {
+              description "The protocol operation layer";
+            }
+            enum application {
+              description "The server application layer";
+            }
+          }
+          mandatory true;
+          description
+            "The protocol layer where the error occurred.";
+        }
+  
+        leaf error-tag {
+          type string;
+          mandatory true;
+          description
+            "The enumerated error tag.";
+        }
+  
+        leaf error-app-tag { 
+          type string;
+          description
+            "The application-specific error tag.";
+        }
+  
+        leaf error-path { 
+          type data-resource-identifier;
+          description
+            "The target data resource identifier associated
+             with the error, if any.";
+        }
+  
+        leaf error-message { 
+          type string;
+          description
+            "A message describing the error.";
+        }
+  
+        container error-info { 
+           description
+             "A container allowing additional information
+              to be included in the error report.";
+           // arbitrary anyxml content here
+        }
+      }
+    }
+  } // grouping errors
+
+
+  grouping restconf {
+
+    description
+      "A grouping that contains a YANG container
+       representing the syntax and semantics of
+       the RESTCONF API resource.";
+
+    container restconf {
+      description
+        "Conceptual container representing the
+         application/yang.api resource type.";
+  
+      container config {
+        description
+          "Container representing the application/yang.datastore
+           resource type. Represents the conceptual root of the
+           unified configuration datastore containing YANG data
+           nodes. The child nodes of this container are
+           configuration data resources (application/yang.data)
+           defined as top-level YANG data nodes from the modules
+           advertised by the server in /restconf/modules.";
+      }
+
+      container operational {
+        description
+          "Container representing the application/yang.datastore
+           resource type. Represents the conceptual root of the
+           operational data supported by the server.  The child
+           nodes of this container are operational data resources 
+           (application/yang.data) defined as top-level
+           YANG data nodes from the modules advertised by
+           the server in /restconf/modules.";
+      }
+
+      container modules {
+        description
+          "Contains a list of module description entries.
+           These modules are currently loaded into the server.";
+  
+        list module {
+          key "name revision";
+          description
+            "Each entry represents one module currently
+             supported by the server.";
+
+          leaf name {
+            type yang:yang-identifier;
+            description "The YANG module name.";
+          }
+          leaf revision {
+            type union {
+              type revision-identifier;
+              type string { length 0; }
+            }
+            description
+              "The YANG module revision date. An empty string is
+               used if no revision statement is present in the
+               YANG module.";
+          }
+          leaf namespace {
+            type inet:uri;
+            mandatory true;
+            description
+              "The XML namespace identifier for this module.";
+          }
+          leaf-list feature {
+            type yang:yang-identifier;
+            description
+              "List of YANG feature names from this module that are
+               supported by the server.";
+          }
+          leaf-list deviation {
+            type yang:yang-identifier;
+            description
+              "List of YANG deviation module names used by this
+               server to modify the conformance of the module
+               associated with this entry.";
+          }
+        }
+      }
+
+      container operations {
+        description
+          "Container for all operation resources
+           (application/yang.operation),
+
+           Each resource is represented as an empty leaf with the
+           name of the RPC operation from the YANG rpc statement.
+  
+           E.g.;
+  
+              POST /restconf/operations/show-log-errors
+  
+              leaf show-log-errors {
+                type empty;
+              }
+          ";
+      }
+
+      container streams {
+        description
+          "Container representing the notification event streams
+           supported by the server.";
+         reference
+           "RFC 5277, Section 3.4, <streams> element.";
+
+        list stream {
+          key name;
+          description
+            "Each entry describes an event stream supported by
+             the server.";
+
+          leaf name {
+            type string;
+            description "The stream name";
+            reference "RFC 5277, Section 3.4, <name> element.";
+          }
+
+          leaf description {
+            type string;
+            description "Description of stream content";
+            reference
+              "RFC 5277, Section 3.4, <description> element.";
+          }
+
+          leaf replay-support {
+            type boolean;
+            description
+              "Indicates if replay buffer supported for this stream";
+            reference
+              "RFC 5277, Section 3.4, <replaySupport> element.";
+          }
+
+          leaf replay-log-creation-time {
+            type yang:date-and-time;
+            description
+              "Indicates the time the replay log for this stream
+               was created.";
+            reference
+              "RFC 5277, Section 3.4, <replayLogCreationTime>
+               element.";
+          }
+
+          leaf events {
+            type empty;
+            description
+              "Represents the entry point for establishing
+               notification delivery via server sent events.";
+          }
+        }
+      }
+
+      leaf version {
+        type enumeration {
+          enum "1.0" {
+            description 
+              "Version 1.0 of the RESTCONF protocol.";
+          }
+        }
+        config false;
+        description
+          "Contains the RESTCONF protocol version.";
+      }
+    }
+  }  // grouping restconf
+
+
+  grouping notification {
+    description
+      "Contains the notification message wrapper definition.";
+
+    container notification {
+      description
+        "RESTCONF notification message wrapper.";
+
+      leaf event-time {
+        type yang:date-and-time;
+        mandatory true;
+        description
+          "The time the event was generated by the
+           event source.";
+        reference
+          "RFC 5277, section 4, <eventTime> element.";
+      }
+
+      /* The YANG-specific notification container is encoded
+       * after the 'event-time' element.  The format
+       * corresponds to the notificationContent element
+       * in RFC 5277, section 4. For example:
+       *
+       *  module example-one {
+       *     ...
+       *     notification event1 { ... }
+       *
+       *  }
+       *
+       *  Encoded as element 'event1' in the namespace
+       *  for module 'example-one'.
+       */
+    }
+  }  // grouping notification
+
+}
\ No newline at end of file
diff --git a/model/ietf/ietf-restconf/src/test/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/restconf/restconf/modules/RevisionBuilderTest.java b/model/ietf/ietf-restconf/src/test/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/restconf/rev131019/restconf/restconf/modules/RevisionBuilderTest.java
new file mode 100644 (file)
index 0000000..78fadcc
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2014 Brocade Communications 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019.restconf.restconf.modules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019.RevisionIdentifier;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.restconf.rev131019.restconf.restconf.modules.Module.Revision;
+
+public class RevisionBuilderTest {
+    @Test
+    public void testEmptyString() {
+        Revision revision = RevisionBuilder.getDefaultInstance("");
+        validate(revision, "", null);
+    }
+
+    @Test
+    public void testValidDataString() {
+        String dateString = "2014-04-23";
+        Revision revision = RevisionBuilder.getDefaultInstance(dateString);
+        validate(revision, null, new RevisionIdentifier(dateString));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testNullString() {
+        RevisionBuilder.getDefaultInstance(null);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testBadFormatString() {
+        RevisionBuilder.getDefaultInstance("badFormat");
+    }
+
+    private void validate(final Revision revisionUnderTest, final String expectedRevisionString,
+            final RevisionIdentifier expectedRevisionIdentifier) {
+        assertNotNull(revisionUnderTest);
+        assertEquals(expectedRevisionString, revisionUnderTest.getString());
+        assertEquals(expectedRevisionIdentifier, revisionUnderTest.getRevisionIdentifier());
+    }
+}
\ No newline at end of file
diff --git a/model/ietf/ietf-ted/pom.xml b/model/ietf/ietf-ted/pom.xml
new file mode 100644 (file)
index 0000000..f060fe2
--- /dev/null
@@ -0,0 +1,54 @@
+<?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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-ted</artifactId>
+    <version>2013.10.21.8-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-yang-types</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/model/ietf/ietf-ted/src/main/yang/ted@2013-07-12.yang b/model/ietf/ietf-ted/src/main/yang/ted@2013-07-12.yang
new file mode 100644 (file)
index 0000000..0d0063d
--- /dev/null
@@ -0,0 +1,301 @@
+module ted {
+  yang-version 1;
+  namespace "urn:TBD:params:xml:ns:yang:network:ted";
+  // replace with IANA namespace when assigned
+  prefix ted;
+
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  organization "TBD";
+  contact
+    "TBD";
+  description
+    "Helper module to hold TED attributes for OSPF/ISIS";
+
+  revision 2013-07-12 {
+    description
+      "Initial revision";
+  }
+
+  typedef switching-capabilities {
+    description
+      "Switching Capabilities of an interface.";
+    reference
+      "RFC 5307: IS-IS Extensions in Support of Generalized
+       Multi-Protocol Label Switching (GMPLS)";
+    type enumeration {
+      enum "PSC-1" {
+        description
+          "Packet-Switch Capable-1 (PSC-1)";
+        value 1;
+      }
+      enum "PSC-2" {
+        description
+          "Packet-Switch Capable-2 (PSC-2)";
+        value 2;
+      }
+      enum "PSC-3" {
+        description
+          "Packet-Switch Capable-3 (PSC-3)";
+        value 3;
+      }
+      enum "PSC-4" {
+        description
+          "Packet-Switch Capable-4 (PSC-4)";
+        value 4;
+      }
+      enum "L2SC" {
+        description
+          "Layer-2 Switch Capable (L2SC)";
+        value 51;
+      }
+      enum "TDM" {
+        description
+          "Time-Division-Multiplex Capable (TDM)";
+        value 100;
+      }
+      enum "LSC" {
+        description
+          "Lambda-Switch Capable (LSC)";
+        value 150;
+      }
+      enum "FSC" {
+        description
+          "Fiber-Switch Capable (FSC)";
+        value 200;
+      }
+    }
+  }
+
+  typedef pcc-capabilities {
+    description
+      "Path Computation Capabilities.";
+    reference
+      "RFC 5088, draft-ietf-pce-disco-protoc-isis-07.txt
+       OSPF/ISIS Protocol Extensions for Path Computation Element (PCE) Discovery.";
+    type bits {
+      bit path-computation-with-gmpls-link-constraints {
+        position 0;
+      }
+      bit bidirectional-path-computation {
+        position 1;
+      }
+      bit diverse-path-computation {
+        position 2;
+      }
+      bit load-balanced-path-computation {
+        position 3;
+      }
+      bit synchronized-path-computation {
+        position 4;
+      }
+      bit support-for-multiple-objective-functions {
+        position 5;
+      }
+      bit support-for-additive-path-constraints {
+        position 6;
+      }
+      bit support-for-request-prioritization {
+        position 7;
+      }
+      bit support-for-multiple-requests-per-message {
+        position 8;
+      }
+    }
+  }
+
+
+grouping srlg-attributes {
+    description
+      "Shared Risk Link Group Attributes";
+    reference
+      "RFC 5307, RFC 4203: ISIS / OSPF Extensions in Support of
+       Generalized Multi-Protocol Label Switching (GMPLS)";
+    list interface-switching-capabilities {
+      description
+        "List of interface capabilities for this interface";
+      key "switching-capability";
+      leaf switching-capability {
+        description
+          "Switching Capability for this interface";
+        type ted:switching-capabilities;
+      }
+      leaf encoding {
+        description
+          "Encoding supported by this interface";
+        type uint8;
+      }
+      list max-lsp-bandwidth {
+        description
+          "Maximum LSP Bandwidth at priorities 0-7";
+        max-elements "8";
+        key "priority";
+        leaf priority {
+          type uint8 {
+            range "0..7";
+          }
+        }
+        leaf bandwidth {
+          description
+            "Max LSP Bandwidth for this level";
+          type decimal64 {
+            fraction-digits 2;
+          }
+        }
+      }
+      container packet-switch-capable {
+        when "../switching-capability = PSC-1 or ../switching-capability = PSC-2 or ../switching-capability = PSC-3 or ../switching-capability = PSC-4";
+        description
+          "Interface has packet-switching capabilities";
+        leaf minimum-lsp-bandwidth {
+          description
+            "Minimum LSP Bandwidth. Units in bytes per second";
+          type decimal64 {
+            fraction-digits 2;
+          }
+        }
+        leaf interface-mtu {
+          description
+            "Interface MTU";
+          type uint16;
+        }
+      }
+      container time-division-multiplex-capable {
+        when "../switching-capability = TDM";
+        description
+          "Interface has time-division multiplex capabilities";
+        leaf minimum-lsp-bandwidth {
+          description
+            "Minimum LSP Bandwidth. Units in bytes per second";
+          type decimal64 {
+            fraction-digits 2;
+          }
+        }
+        leaf indication {
+          description
+            "Indication whether the interface supports Standard or Arbitrary SONET/SDH";
+          type uint16;
+        }
+      }
+    }
+    list srlg-values {
+      description
+        "List of Shared Risk Link Group this interface belongs to.";
+      key "srlg-value";
+      leaf srlg-value {
+        description
+          "Shared Risk Link Group value";
+        type uint32;
+      }
+    }
+    leaf link-protection-type {
+      description
+        "Link Protection Type desired for this link";
+      type uint16;
+    }
+  }
+
+  grouping ted-node-attributes {
+    description
+      "Identifier to uniquely identify a node in TED";
+    reference "RFC 5305, RFC 6119: IPv6 Traffic Engineering in IS-IS/OSPF";
+    leaf te-router-id-ipv4 {
+      description
+        "Globally unique IPv4 Traffic Engineering Router ID.";
+      type inet:ipv4-address;
+    }
+    leaf te-router-id-ipv6 {
+      description
+        "Globally unique IPv6 Traffic Engineering Router ID";
+      type inet:ipv6-address;
+    }
+    list ipv4-local-address {
+      description
+        "List of IPv4 Local Address(OSPF). RFC 5786";
+      key "ipv4-prefix";
+      leaf ipv4-prefix {
+        description
+          "Local IPv4 address for the node";
+        type inet:ipv4-prefix;
+      }
+    }
+    list ipv6-local-address {
+      description
+        "List of IPv6 Local Address.";
+      reference
+        "RFC 5786: Advertising a Router's Local Addresses
+         in OSPF Traffic Engineering (TE) Extensions";
+      key "ipv6-prefix";
+      leaf ipv6-prefix {
+        description
+          "Local IPv6 address for the node";
+        type inet:ipv6-prefix;
+      }
+      leaf prefix-option {
+        description
+          "IPv6 prefix option.";
+        type uint8;
+      }
+    }
+    leaf pcc-capabilities {
+      description
+        "OSPF/ISIS PCC capabilities";
+      type pcc-capabilities;
+    }
+  }
+
+  grouping ted-link-attributes {
+    description
+      "TED Attributes associated with the link.";
+    reference "RFC 3630, RFC 3784: IS-IS / OSPF Traffic Engineering (TE)";
+    leaf color {
+      description
+        "Administrative group or color of the link";
+      type uint32;
+    }
+    leaf max-link-bandwidth {
+      description
+        "Maximum bandwidth that can be see on this link in this direction. Units in bytes per second";
+      type decimal64 {
+        fraction-digits 2;
+      }
+    }
+    leaf max-resv-link-bandwidth {
+      description
+        "Maximum amount of bandwidth that can be reserved in this direction in this link. Units in bytes per second";
+      type decimal64 {
+        fraction-digits 2;
+      }
+    }
+    list unreserved-bandwidth {
+      description
+        "Unreserved bandwidth for 0-7 priority levels. Units in bytes per second";
+      max-elements "8";
+      key "priority";
+      leaf priority {
+        type uint8 {
+          range "0..7";
+        }
+      }
+      leaf bandwidth {
+        description
+          "Unreserved bandwidth for this level";
+        type decimal64 {
+          fraction-digits 2;
+        }
+      }
+    }
+    leaf te-default-metric {
+      description
+        "Traffic Engineering Metric";
+      type uint32;
+    }
+    container srlg {
+      description
+        "Shared Risk Link Group Attributes";
+      uses srlg-attributes;
+    }
+  }
+}
diff --git a/model/ietf/ietf-ted/src/main/yang/ted@2013-10-21.yang b/model/ietf/ietf-ted/src/main/yang/ted@2013-10-21.yang
new file mode 100644 (file)
index 0000000..7456623
--- /dev/null
@@ -0,0 +1,306 @@
+module ted {
+  yang-version 1;
+  namespace "urn:TBD:params:xml:ns:yang:network:ted";
+  // replace with IANA namespace when assigned
+  prefix ted;
+
+  import ietf-inet-types {
+    prefix inet;
+    revision-date 2010-09-24;
+  }
+
+  organization "TBD";
+  contact
+    "TBD";
+  description
+    "Helper module to hold TED attributes for OSPF/ISIS";
+
+  revision 2013-10-21 {
+
+    description
+      "Initial revision";
+  }
+
+  typedef switching-capabilities {
+    description
+      "Switching Capabilities of an interface.";
+    reference
+      "RFC 5307: IS-IS Extensions in Support of Generalized
+       Multi-Protocol Label Switching (GMPLS)";
+    type enumeration {
+      enum "PSC-1" {
+        description
+          "Packet-Switch Capable-1 (PSC-1)";
+        value 1;
+      }
+      enum "PSC-2" {
+        description
+          "Packet-Switch Capable-2 (PSC-2)";
+        value 2;
+      }
+      enum "PSC-3" {
+        description
+          "Packet-Switch Capable-3 (PSC-3)";
+        value 3;
+      }
+      enum "PSC-4" {
+        description
+          "Packet-Switch Capable-4 (PSC-4)";
+        value 4;
+      }
+      enum "L2SC" {
+        description
+          "Layer-2 Switch Capable (L2SC)";
+        value 51;
+      }
+      enum "TDM" {
+        description
+          "Time-Division-Multiplex Capable (TDM)";
+        value 100;
+      }
+      enum "LSC" {
+        description
+          "Lambda-Switch Capable (LSC)";
+        value 150;
+      }
+      enum "FSC" {
+        description
+
+          "Fiber-Switch Capable (FSC)";
+        value 200;
+      }
+    }
+  }
+
+  typedef pcc-capabilities {
+    description
+      "Path Computation Capabilities.";
+    reference
+      "RFC 5088, draft-ietf-pce-disco-protoc-isis-07.txt
+       OSPF/ISIS Protocol Extensions for Path Computation Element (PCE) Discovery.";
+    type bits {
+      bit path-computation-with-gmpls-link-constraints {
+        position 0;
+      }
+      bit bidirectional-path-computation {
+        position 1;
+      }
+      bit diverse-path-computation {
+        position 2;
+      }
+      bit load-balanced-path-computation {
+        position 3;
+      }
+      bit synchronized-path-computation {
+        position 4;
+      }
+      bit support-for-multiple-objective-functions {
+        position 5;
+      }
+      bit support-for-additive-path-constraints {
+        position 6;
+      }
+      bit support-for-request-prioritization {
+        position 7;
+      }
+      bit support-for-multiple-requests-per-message {
+        position 8;
+      }
+    }
+  }
+
+  grouping ted-node-attributes {
+    description
+      "Identifier to uniquely identify a node in TED";
+    reference "RFC 5305, RFC 6119: IPv6 Traffic Engineering in IS-IS/OSPF";
+    leaf te-router-id-ipv4 {
+
+      description
+        "Globally unique IPv4 Traffic Engineering Router ID.";
+      type inet:ipv4-address;
+    }
+    leaf te-router-id-ipv6 {
+      description
+        "Globally unique IPv6 Traffic Engineering Router ID";
+      type inet:ipv6-address;
+    }
+    list ipv4-local-address {
+      description
+        "List of IPv4 Local Address(OSPF). RFC 5786";
+      key "ipv4-prefix";
+      leaf ipv4-prefix {
+        description
+          "Local IPv4 address for the node";
+        type inet:ipv4-prefix;
+      }
+    }
+    list ipv6-local-address {
+      description
+        "List of IPv6 Local Address.";
+      reference
+        "RFC 5786: Advertising a Router's Local Addresses
+         in OSPF Traffic Engineering (TE) Extensions";
+      key "ipv6-prefix";
+      leaf ipv6-prefix {
+        description
+          "Local IPv6 address for the node";
+        type inet:ipv6-prefix;
+      }
+      leaf prefix-option {
+        description
+          "IPv6 prefix option.";
+        type uint8;
+      }
+    }
+    leaf pcc-capabilities {
+      description
+        "OSPF/ISIS PCC capabilities";
+      type pcc-capabilities;
+    }
+  }
+
+  grouping ted-link-attributes {
+    description
+      "TED Attributes associated with the link.";
+    reference "RFC 3630, RFC 3784: IS-IS / OSPF Traffic Engineering (TE)";
+
+    leaf color {
+      description
+        "Administrative group or color of the link";
+      type uint32;
+    }
+    leaf max-link-bandwidth {
+      description
+        "Maximum bandwidth that can be see on this link in this direction. Units in bytes per second";
+      type decimal64 {
+        fraction-digits 2;
+      }
+    }
+    leaf max-resv-link-bandwidth {
+      description
+        "Maximum amount of bandwidth that can be reserved in this direction in this link. Units in bytes per second";
+      type decimal64 {
+        fraction-digits 2;
+      }
+    }
+    list unreserved-bandwidth {
+      description
+        "Unreserved bandwidth for 0-7 priority levels. Units in bytes per second";
+      max-elements "8";
+      key "priority";
+      leaf priority {
+        type uint8 {
+          range "0..7";
+        }
+      }
+      leaf bandwidth {
+        description
+          "Unreserved bandwidth for this level";
+        type decimal64 {
+          fraction-digits 2;
+        }
+      }
+    }
+    leaf te-default-metric {
+      description
+        "Traffic Engineering Metric";
+      type uint32;
+    }
+    container srlg {
+      description
+        "Shared Risk Link Group Attributes";
+      uses srlg-attributes;
+    }
+  }
+
+  grouping srlg-attributes {
+    description
+      "Shared Risk Link Group Attributes";
+    reference
+      "RFC 5307, RFC 4203: ISIS / OSPF Extensions in Support of
+       Generalized Multi-Protocol Label Switching (GMPLS)";
+    list interface-switching-capabilities {
+      description
+        "List of interface capabilities for this interface";
+      key "switching-capability";
+      leaf switching-capability {
+        description
+          "Switching Capability for this interface";
+        type ted:switching-capabilities;
+      }
+      leaf encoding {
+        description
+          "Encoding supported by this interface";
+        type uint8;
+      }
+      list max-lsp-bandwidth {
+        description
+          "Maximum LSP Bandwidth at priorities 0-7";
+        max-elements "8";
+        key "priority";
+        leaf priority {
+          type uint8 {
+            range "0..7";
+          }
+        }
+        leaf bandwidth {
+          description
+            "Max LSP Bandwidth for this level";
+          type decimal64 {
+            fraction-digits 2;
+          }
+        }
+      }
+      container packet-switch-capable {
+        when "../switching-capability = PSC-1 or ../switching-capability = PSC-2 or ../switching-capability = PSC-3 or ../switching-capability = PSC-4";
+        description
+          "Interface has packet-switching capabilities";
+        leaf minimum-lsp-bandwidth {
+          description
+            "Minimum LSP Bandwidth. Units in bytes per second";
+          type decimal64 {
+            fraction-digits 2;
+          }
+
+        }
+        leaf interface-mtu {
+          description
+            "Interface MTU";
+          type uint16;
+        }
+      }
+      container time-division-multiplex-capable {
+        when "../switching-capability = TDM";
+        description
+          "Interface has time-division multiplex capabilities";
+        leaf minimum-lsp-bandwidth {
+          description
+            "Minimum LSP Bandwidth. Units in bytes per second";
+          type decimal64 {
+            fraction-digits 2;
+          }
+        }
+        leaf indication {
+          description
+            "Indication whether the interface supports Standard or Arbitrary SONET/SDH";
+          type uint16;
+        }
+      }
+    }
+    list srlg-values {
+      description
+        "List of Shared Risk Link Group this interface belongs to.";
+      key "srlg-value";
+      leaf srlg-value {
+        description
+          "Shared Risk Link Group value";
+        type uint32;
+      }
+    }
+    leaf link-protection-type {
+      description
+        "Link Protection Type desired for this link";
+      type uint16;
+    }
+  }
+}
diff --git a/model/ietf/ietf-topology-isis/pom.xml b/model/ietf/ietf-topology-isis/pom.xml
new file mode 100644 (file)
index 0000000..9063160
--- /dev/null
@@ -0,0 +1,54 @@
+<?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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-topology-isis</artifactId>
+    <version>2013.10.21.8-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-topology-l3-unicast-igp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-ted</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/model/ietf/ietf-topology-isis/src/main/yang/isis-topology@2013-07-12.yang b/model/ietf/ietf-topology-isis/src/main/yang/isis-topology@2013-07-12.yang
new file mode 100644 (file)
index 0000000..23e9dbc
--- /dev/null
@@ -0,0 +1,143 @@
+module isis-topology {
+       yang-version 1;
+       namespace "urn:TBD:params:xml:ns:yang:network:isis-topology";
+       // replace with IANA namespace when assigned
+       prefix "isis";
+       import network-topology {
+           prefix nt;
+           revision-date 2013-07-12;
+       }
+       import l3-unicast-igp-topology {
+               prefix igp;
+               revision-date 2013-07-12;
+       }
+       import ted {
+               prefix ted;
+               revision-date 2013-07-12;
+       }
+       
+       organization "TBD";
+       contact "TBD";
+       description "ISIS Topology model";
+
+       revision "2013-07-12" {
+               description "Initial version";
+       }
+    typedef iso-system-id {
+        description "ISO System ID. RFC 1237";
+        type string {
+            pattern '[0-9a-fA-F]{4}(.[0-9a-fA-F]{4}){2}';
+        }
+    }
+
+    typedef iso-pseudonode-id {
+        description "ISO pseudonode id for broadcast network";
+        type string {
+            pattern '[0-9a-fA-F]{2}';
+        }
+    }
+
+       typedef iso-net-id {
+        description "ISO NET ID. RFC 1237";
+        type string {
+            pattern '[0-9a-fA-F]{2}((.[0-9a-fA-F]{4}){6})';
+        }
+    }
+
+       grouping isis-topology-type {
+           container isis {
+               presence "Indicates ISIS Topology";
+           }
+       }
+
+       augment "/nt:network-topology/nt:topology/nt:topology-types/igp:l3-unicast-igp-topology" {
+           uses isis-topology-type;
+       }
+
+       augment "/nt:network-topology/nt:topology/igp:igp-topology-attributes" {
+           when "../../topology-types/isis";
+           container isis-topogloy-attributes {
+                   leaf net {
+                       type iso-net-id;
+                   }
+           }
+       }
+
+       augment "/nt:network-topology/nt:topology/nt:node/igp:igp-node-attributes" {
+           when "../../../topology-types/isis";
+           uses isis-node-attributes;
+       }
+
+       augment "/nt:network-topology/nt:topology/nt:link/igp:igp-link-attributes" {
+           when "../../../../topology-types/isis";
+           uses isis-link-attributes;
+       }
+
+       grouping isis-node-attributes {
+               container isis-node-attributes {
+                       container iso {
+                               leaf iso-system-id {
+                                       type iso-system-id;
+                               }
+                               leaf iso-pseudonode-id {
+                                       default "0";
+                                       type iso-pseudonode-id;
+                               }
+            }
+            leaf-list net {
+               max-elements 3;
+                       type iso-net-id;
+            }
+            leaf-list multi-topology-id {
+                description "List of Multi Topology Identifier upto 128 (0-127). RFC 4915";
+                max-elements "128";
+                type uint8 {
+                       range "0..127";
+                }
+            }
+            choice router-type {
+               case level-2 {
+                       leaf level-2 {
+                               type empty;
+                       }
+               }
+                case level-1 {
+                    leaf level-1 {
+                        type empty;
+                       }
+                }
+                case level-1-2 {
+                    leaf level-1-2 {
+                               type empty;
+                    }
+               }
+               }
+                       container ted {
+                           uses ted:ted-node-attributes;
+                       }
+               }
+       }
+
+       grouping isis-link-attributes {
+               container isis-link-attributes {
+                       leaf multi-topology-id {
+                               type uint8 {
+                                       range "0..127";
+                               }
+                       }
+                       container ted {
+                           uses ted:ted-link-attributes;       
+                       }
+               }
+       }
+       /*
+       augment "/igp:igp-node-event" {
+               uses isis-topology-type;
+               uses isis-node-attributes;
+       }
+
+       augment "/igp:igp-link-event" {
+               uses isis-topology-type;
+               uses isis-link-attributes;
+       }*/
+} // Module isis-topology
diff --git a/model/ietf/ietf-topology-isis/src/main/yang/isis-topology@2013-10-21.yang b/model/ietf/ietf-topology-isis/src/main/yang/isis-topology@2013-10-21.yang
new file mode 100644 (file)
index 0000000..edf75ca
--- /dev/null
@@ -0,0 +1,143 @@
+module isis-topology {
+    yang-version 1;
+    namespace "urn:TBD:params:xml:ns:yang:network:isis-topology";
+    // replace with IANA namespace when assigned
+    prefix "isis";
+    import network-topology {
+        prefix nt;
+        revision-date 2013-10-21;
+    }
+    import l3-unicast-igp-topology {
+        prefix igp;
+        revision-date 2013-10-21;
+    }
+    import ted {
+        prefix ted;
+        revision-date 2013-10-21;
+    }
+
+    organization "TBD";
+    contact "TBD";
+    description "ISIS Topology model";
+
+    revision "2013-10-21" {
+        description "Initial version";
+    }
+    typedef iso-system-id {
+        description "ISO System ID. RFC 1237";
+        type string {
+            pattern '[0-9a-fA-F]{4}(\.[0-9a-fA-F]{4}){2}';
+        }
+    }
+
+    typedef iso-pseudonode-id {
+        description "ISO pseudonode id for broadcast network";
+        type string {
+            pattern '[0-9a-fA-F]{2}';
+        }
+    }
+    typedef iso-net-id {
+        description "ISO NET ID. RFC 1237";
+        type string {
+            pattern '[0-9a-fA-F]{2}((\.[0-9a-fA-F]{4}){6})';
+        }
+    }
+
+    grouping isis-topology-type {
+        container isis {
+            presence "Indicates ISIS Topology";
+        }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:topology-types/igp:l3-unicast-igp-topology" {
+        uses isis-topology-type;
+    }
+
+    augment "/nt:network-topology/nt:topology/igp:igp-topology-attributes" {
+        when "../nt:topology-types/igp:l3-unicast-igp-topology/isis";
+        container isis-topology-attributes {
+            leaf net {
+                type iso-net-id;
+            }
+        }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node/igp:igp-node-attributes" {
+        when "../../nt:topology-types/igp:l3-unicast-igp-topology/isis";
+        uses isis-node-attributes;
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:link/igp:igp-link-attributes" {
+
+        when "../../nt:topology-types/igp:l3-unicast-igp-topology/isis";
+        uses isis-link-attributes;
+    }
+
+    grouping isis-node-attributes {
+        container isis-node-attributes {
+            container iso {
+                leaf iso-system-id {
+                    type iso-system-id;
+                }
+                leaf iso-pseudonode-id {
+                    default "0";
+                    type iso-pseudonode-id;
+                }
+            }
+            leaf-list net {
+                max-elements 3;
+                type iso-net-id;
+            }
+            leaf-list multi-topology-id {
+                description "List of Multi Topology Identifier upto 128 (0-127). RFC 4915";
+                max-elements "128";
+                type uint8 {
+                    range "0..127";
+                }
+            }
+            choice router-type {
+                case level-2 {
+                    leaf level-2 {
+                        type empty;
+                    }
+                }
+                case level-1 {
+                    leaf level-1 {
+                        type empty;
+                    }
+                }
+                case level-1-2 {
+                    leaf level-1-2 {
+                        type empty;
+                    }
+                }
+            }
+            container ted {
+                uses ted:ted-node-attributes;
+            }
+        }
+    }
+
+    grouping isis-link-attributes {
+        container isis-link-attributes {
+            leaf multi-topology-id {
+                type uint8 {
+                    range "0..127";
+                }
+            }
+            container ted {
+                uses ted:ted-link-attributes;
+            }
+        }
+    }
+
+    augment "/igp:igp-node-event" {
+        uses isis-topology-type;
+        uses isis-node-attributes;
+    }
+
+    augment "/igp:igp-link-event" {
+        uses isis-topology-type;
+        uses isis-link-attributes;
+    }
+} // Module isis-topology
diff --git a/model/ietf/ietf-topology-l3-unicast-igp/pom.xml b/model/ietf/ietf-topology-l3-unicast-igp/pom.xml
new file mode 100644 (file)
index 0000000..071d5aa
--- /dev/null
@@ -0,0 +1,51 @@
+<?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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-topology-l3-unicast-igp</artifactId>
+    <version>2013.10.21.8-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-topology</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/model/ietf/ietf-topology-l3-unicast-igp/src/main/yang/l3-unicast-igp-topology@2013-07-12.yang b/model/ietf/ietf-topology-l3-unicast-igp/src/main/yang/l3-unicast-igp-topology@2013-07-12.yang
new file mode 100644 (file)
index 0000000..99df396
--- /dev/null
@@ -0,0 +1,233 @@
+module l3-unicast-igp-topology {
+    yang-version 1;
+    namespace "urn:TBD:params:xml:ns:yang:nt:l3-unicast-igp-topology";
+    // replace with IANA namespace when assigned
+    prefix "l3t";
+    import network-topology {
+        prefix "nt";
+        revision-date 2013-07-12;
+    }
+    
+    import ietf-inet-types {
+        prefix "inet";
+    }
+
+    organization "TBD";
+    contact "TBD";
+
+    revision "2013-07-12" {
+        description "Initial revision";
+        reference "TBD";
+    }
+    
+    typedef igp-event-type {
+        description "IGP Event type for notifications";
+        type enumeration {
+            enum "add" {
+                value 0;
+                    description "An IGP node or link or prefix or termination-point has been added";
+            }
+            enum "remove" {
+                value 1;
+                description "An IGP node or link or prefix or termination-point has been removed";
+            }
+            enum "update" {
+                value 2;
+                description "An IGP node or link or prefix or termination-point has been updated";
+            }
+        }
+    } // igp-event-type
+
+    identity flag-identity {
+        description "Base type for flags";
+    }
+    identity undefined-flag {
+        base "flag-identity";
+    }
+    
+    typedef flag-type {
+        type identityref {
+            base "flag-identity";
+        }
+    }
+    
+    grouping igp-prefix-attributes {
+        leaf prefix {
+            type inet:ip-prefix;
+        }
+        leaf metric {
+            type uint32;
+        }
+        leaf-list flag {
+            type flag-type;
+        }
+    }
+    
+    grouping l3-unicast-igp-topology-type {
+        container l3-unicast-igp-topology {
+            presence "indicates L3 Unicast IGP Topology";
+        }
+    }
+    
+    grouping igp-topology-attributes {
+        container igp-topology-attributes { 
+            leaf name {
+                description "Name of the topology";
+                    type string;
+            }
+            leaf-list flag {
+                description "Topology flags";
+                type flag-type;
+            }
+        }
+    }
+
+    grouping igp-node-attributes {
+        container igp-node-attributes {
+            leaf name {
+                description "Node name";
+                type inet:domain-name; 
+            }
+            leaf-list flag {
+                description "Node operational flags";
+                type flag-type; 
+            }
+            
+            leaf-list router-id {
+                description "Router-id for the node";
+                type inet:ip-address;
+            }
+            
+            list prefix {  
+                key "prefix";
+                uses igp-prefix-attributes; 
+            }
+        }
+    }
+
+    grouping igp-link-attributes {
+        container igp-link-attributes { 
+            leaf name {
+                description "Link Name";
+                type string;
+            }
+            leaf-list flag {
+                description "Link flags";
+                type flag-type; 
+            }
+            leaf metric {
+                description "Link Metric";
+                type uint32 {
+                    range "0..16777215"  {
+                        description "
+                        "; 
+                        // OSPF/ISIS supports max 3 byte metric. 
+                        // Ideally we would like this restriction to be
+                        // defined in the derived models, however,  
+                        // we are not allowed to augment a "must" statement. 
+                    }
+                }
+            }
+        }
+    } // grouping igp-link-attributes
+
+    grouping igp-termination-point-attributes {
+        container igp-termination-point-attributes {
+            choice termination-point-type {  
+                case ip {
+                   leaf-list ip-address {
+                    description "IPv4 or IPv6 address";
+                    type inet:ip-address;
+                    }
+                }
+                case unnumbered {
+                    leaf unnumbered-id {  
+                    description "Unnumbered interface identifier";
+                    type uint32;
+                    }
+                }
+            }
+        }
+    } // grouping igp-termination-point-attributes
+    
+    
+    augment "/nt:network-topology/nt:topology/nt:topology-types" {  
+        uses l3-unicast-igp-topology-type; 
+    }
+    
+    
+    augment "/nt:network-topology/nt:topology" {
+        when "topology-types/l3-unicast-igp-topology";
+        uses igp-topology-attributes;  
+    }
+    
+    augment "/nt:network-topology/nt:topology/nt:node" {
+        when "../../topology-types/l3-unicast-igp-topology";
+        uses igp-node-attributes; 
+    }
+    
+
+    augment "/nt:network-topology/nt:topology/nt:link" {
+        when "../../topology-types/l3-unicast-igp-topology";
+        uses igp-link-attributes; 
+    }
+    augment "/nt:network-topology/nt:topology/nt:node/nt:termination-point" {
+        when "../../topology-types/l3-unicast-igp-topology";
+        uses igp-termination-point-attributes; 
+    }
+    
+    notification igp-node-event {
+        leaf igp-event-type {
+            type igp-event-type;
+        }
+        leaf topology-ref {
+            type nt:topology-ref;
+        }
+        uses l3-unicast-igp-topology-type; 
+        uses nt:node-attributes;
+        uses igp-node-attributes;
+    }
+
+    notification igp-link-event {
+        leaf igp-event-type {
+            type igp-event-type;
+        }
+        leaf topology-ref {
+            type nt:topology-ref;
+        }
+        uses l3-unicast-igp-topology-type; 
+        uses nt:link-attributes; 
+        uses igp-link-attributes; 
+    }
+
+    notification igp-prefix-event {
+        leaf igp-event-type {
+            type igp-event-type;
+        }
+        leaf topology-ref {
+            type nt:topology-ref;
+        }
+        leaf node-ref {
+            type nt:node-ref;
+        }
+        uses l3-unicast-igp-topology-type; 
+        container prefix {
+            uses igp-prefix-attributes;
+        }
+    }   
+
+    notification termination-point-event {
+        leaf igp-event-type {
+            type igp-event-type;
+        }
+        leaf topology-ref {
+            type nt:topology-ref;
+        }
+        leaf node-ref {
+            type nt:node-ref;
+        }
+        uses l3-unicast-igp-topology-type;
+        uses nt:tp-attributes;
+        uses igp-termination-point-attributes;
+    }
+}
diff --git a/model/ietf/ietf-topology-l3-unicast-igp/src/main/yang/l3-unicast-igp-topology@2013-10-21.yang b/model/ietf/ietf-topology-l3-unicast-igp/src/main/yang/l3-unicast-igp-topology@2013-10-21.yang
new file mode 100644 (file)
index 0000000..00db145
--- /dev/null
@@ -0,0 +1,233 @@
+module l3-unicast-igp-topology {
+    yang-version 1;
+    namespace "urn:TBD:params:xml:ns:yang:nt:l3-unicast-igp-topology";
+    // replace with IANA namespace when assigned
+    prefix "l3t";
+    import network-topology {
+        prefix "nt";
+        revision-date 2013-10-21;
+    }
+
+    import ietf-inet-types {
+        prefix "inet";
+       revision-date 2010-09-24;
+    }
+
+    organization "TBD";
+    contact "TBD";
+
+    revision "2013-10-21" {
+        description "Initial revision";
+        reference "TBD";
+    }
+
+    typedef igp-event-type {
+        description "IGP Event type for notifications";
+            type enumeration {
+                enum "add" {
+                    value 0;
+                        description "An IGP node or link or prefix or termination-point has been added";
+                }
+                enum "remove" {
+                    value 1;
+                    description "An IGP node or link or prefix or termination-point has been removed";
+                }
+                enum "update" {
+                    value 2;
+                    description "An IGP node or link or prefix or termination-point has been updated";
+                }
+            }
+        } // igp-event-type
+
+    identity flag-identity {
+        description "Base type for flags";
+    }
+    identity undefined-flag {
+        base "flag-identity";
+    }
+
+    typedef flag-type {
+
+        type identityref {
+            base "flag-identity";
+        }
+    }
+
+    grouping igp-prefix-attributes {
+        leaf prefix {
+            type inet:ip-prefix;
+        }
+        leaf metric {
+            type uint32;
+        }
+        leaf-list flag {
+            type flag-type;
+        }
+    }
+
+    grouping l3-unicast-igp-topology-type {
+        container l3-unicast-igp-topology {
+            presence "indicates L3 Unicast IGP Topology";
+        }
+    }
+
+    grouping igp-topology-attributes {
+        container igp-topology-attributes {
+            leaf name {
+                description "Name of the topology";
+                    type string;
+            }
+            leaf-list flag {
+                description "Topology flags";
+                type flag-type;
+            }
+        }
+    }
+
+    grouping igp-node-attributes {
+        container igp-node-attributes {
+            leaf name {
+                description "Node name";
+                type inet:domain-name;
+            }
+            leaf-list flag {
+                description "Node operational flags";
+                type flag-type;
+            }
+            leaf-list router-id {
+                description "Router-id for the node";
+
+                type inet:ip-address;
+            }
+            list prefix {
+                key "prefix";
+                uses igp-prefix-attributes;
+            }
+        }
+    }
+
+    grouping igp-link-attributes {
+        container igp-link-attributes {
+            leaf name {
+                description "Link Name";
+                type string;
+            }
+            leaf-list flag {
+                description "Link flags";
+                type flag-type;
+            }
+            leaf metric {
+                description "Link Metric";
+                type uint32 {
+                    range "0..16777215"  {
+                        description "
+                        ";
+                        // OSPF/ISIS supports max 3 byte metric.
+                        // Ideally we would like this restriction to be
+                        // defined in the derived models, however,
+                        // we are not allowed to augment a "must" statement.
+                    }
+                }
+            }
+        }
+    } // grouping igp-link-attributes
+
+    grouping igp-termination-point-attributes {
+        container igp-termination-point-attributes {
+            choice termination-point-type {
+                case ip {
+                   leaf-list ip-address {
+                    description "IPv4 or IPv6 address";
+                    type inet:ip-address;
+                    }
+                }
+                case unnumbered {
+                    leaf unnumbered-id {
+                    description "Unnumbered interface identifier";
+                    type uint32;
+
+                    }
+                }
+            }
+        }
+    } // grouping igp-termination-point-attributes
+
+
+    augment "/nt:network-topology/nt:topology/nt:topology-types" {
+        uses l3-unicast-igp-topology-type;
+    }
+
+    augment "/nt:network-topology/nt:topology" {
+        when "nt:topology-types/l3-unicast-igp-topology";
+        uses igp-topology-attributes;
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node" {
+        when "../nt:topology-types/l3-unicast-igp-topology";
+        uses igp-node-attributes;
+    }
+    augment "/nt:network-topology/nt:topology/nt:link" {
+        when "../nt:topology-types/l3-unicast-igp-topology";
+        uses igp-link-attributes;
+    }
+    augment "/nt:network-topology/nt:topology/nt:node/nt:termination-point" {
+        when "../../nt:topology-types/l3-unicast-igp-topology";
+        uses igp-termination-point-attributes;
+    }
+
+    notification igp-node-event {
+        leaf igp-event-type {
+            type igp-event-type;
+        }
+        leaf topology-ref {
+            type nt:topology-ref;
+        }
+        uses l3-unicast-igp-topology-type;
+        uses nt:node-attributes;
+        uses igp-node-attributes;
+    }
+
+    notification igp-link-event {
+        leaf igp-event-type {
+            type igp-event-type;
+        }
+        leaf topology-ref {
+            type nt:topology-ref;
+        }
+
+        uses l3-unicast-igp-topology-type;
+        uses nt:link-attributes;
+        uses igp-link-attributes;
+    }
+
+    notification igp-prefix-event {
+        leaf igp-event-type {
+            type igp-event-type;
+        }
+        leaf topology-ref {
+            type nt:topology-ref;
+        }
+        leaf node-ref {
+            type nt:node-ref;
+        }
+        uses l3-unicast-igp-topology-type;
+        container prefix {
+            uses igp-prefix-attributes;
+        }
+    }
+
+    notification termination-point-event {
+        leaf igp-event-type {
+            type igp-event-type;
+        }
+        leaf topology-ref {
+            type nt:topology-ref;
+        }
+        leaf node-ref {
+            type nt:node-ref;
+        }
+        uses l3-unicast-igp-topology-type;
+        uses nt:tp-attributes;
+        uses igp-termination-point-attributes;
+    }
+}
diff --git a/model/ietf/ietf-topology-ospf/pom.xml b/model/ietf/ietf-topology-ospf/pom.xml
new file mode 100644 (file)
index 0000000..7344aab
--- /dev/null
@@ -0,0 +1,54 @@
+<?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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-topology-ospf</artifactId>
+    <version>2013.10.21.8-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-topology-l3-unicast-igp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-ted</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/model/ietf/ietf-topology-ospf/src/main/yang/ospf-topology@2013-07-12.yang b/model/ietf/ietf-topology-ospf/src/main/yang/ospf-topology@2013-07-12.yang
new file mode 100644 (file)
index 0000000..1261de8
--- /dev/null
@@ -0,0 +1,176 @@
+module ospf-topology {
+    yang-version 1;
+    namespace "urn:ietf:params:xml:ns:yang:ospf-topology";
+    // replace with IANA namespace when assigned
+    prefix "ospf";
+
+    import network-topology {
+        prefix "nt";
+        revision-date 2013-07-12;
+    }
+
+    import l3-unicast-igp-topology {
+        prefix "igp";
+        revision-date 2013-07-12;
+    }
+    import ietf-inet-types {
+        prefix "inet";
+    }
+    import ted {
+        prefix "ted";
+        revision-date 2013-07-12;
+    }
+
+    organization "TBD";
+    contact "TBD";
+    description "OSPF Topology model";
+
+    revision "2013-07-12" {
+               description "Initial revision";
+               reference "TBD";
+    }
+
+    typedef area-id {
+               description "OSPF Area ID";
+               type uint32;
+    }
+
+    grouping ospf-topology-type {
+               container ospf {
+                       presence "indiates OSPF Topology";
+               }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:topology-types/igp:l3-unicast-igp-topology" {
+               uses ospf-topology-type;
+    }
+
+    augment "/nt:network-topology/nt:topology/igp:igp-topology-attributes" {
+               when "../topology-types/ospf";
+               container ospf-topology-attributes {
+                       leaf area-id {
+                               type area-id;
+                       }
+               }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node/igp:igp-node-attributes" {
+               when "../../../topology-types/ospf";
+               uses ospf-node-attributes;
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:link/igp:igp-link-attributes" {
+               when "../../../topology-types/ospf";
+               uses ospf-link-attributes;
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node/igp:igp-node-attributes/igp:prefix" {
+               when "../../../../topology-types/ospf";
+               uses ospf-prefix-attributes;
+    }
+
+    grouping ospf-node-attributes {
+               container ospf-node-attributes {
+                       choice router-type {
+                               case abr {
+                                       leaf abr {
+                                               type empty;
+                                       }
+                               }
+                               case asbr {
+                                       leaf asbr {
+                                               type empty;
+                                       }
+                               }
+                               case internal {
+                                       leaf internal {
+                                               type empty;
+                                       }
+                               }
+                               case pseudonode {
+                                       leaf pseudonode {
+                                               type empty;
+                                       }
+                               }
+                       }
+                       leaf dr-interface-id {
+                               when "../router-type/pseudonode";
+                               description "For pseudonodes, DR interface-id";
+                               default "0";
+                               type uint32;
+                       }
+                       leaf-list multi-topology-id {
+                               description "List of Multi-Topology Identifier up-to 128 (0-127). RFC 4915";
+                               max-elements "128";
+                               type uint8 {
+                                       range "0..127";
+                               }
+                       }
+                       leaf capabilities {
+                               description "OSPF capabilities as bit vector. RFC 4970";
+                               type bits {
+                                       bit graceful-restart-capable {
+                                               position 0;
+                                       }
+                                       bit graceful-restart-helper {
+                                               position 1;
+                                       }
+                                       bit stub-router-support {
+                                               position 2;
+                                       }
+                                       bit traffic-engineering-support {
+                                               position 3;
+                                       }
+                                       bit point-to-point-over-lan {
+                                               position 4;
+                                       }
+                                       bit experimental-te {
+                                               position 5;
+                                       }
+                               }
+                       }
+                       container ted {
+                               uses ted:ted-node-attributes;
+                       }
+               } // ospf
+    } // ospf-node-attributes
+
+    grouping ospf-link-attributes {
+               container ospf-link-attributes {
+                       leaf multi-topology-id {
+                               type uint8 {
+                                       range "0..127";
+                               }
+                       }
+                       container ted {
+                               uses ted:ted-link-attributes;
+                       }
+               }
+    } // ospf-link-attributes
+
+    grouping ospf-prefix-attributes {
+               container ospf-prefix-attributes {
+                       leaf forwarding-address {
+                               when "../../igp:l3-unicast-igp-topology/igp:ospf/igp:router-type/igp:asbr";
+                               type inet:ipv4-address;
+                       }
+               }
+    }
+
+       /*
+    augment "/igp:igp-node-event" {
+           uses ospf-topology-type;
+           uses ospf:ospf-node-attributes;
+    }
+
+    augment "/igp:igp-link-event" {
+           uses ospf-topology-type;
+           uses ospf:ospf-link-attributes;
+    }
+
+    augment "/igp:igp-prefix-event" {
+           uses ospf-topology-type;
+           uses ospf:ospf-prefix-attributes;
+    }
+    */
+}
diff --git a/model/ietf/ietf-topology-ospf/src/main/yang/ospf-topology@2013-10-21.yang b/model/ietf/ietf-topology-ospf/src/main/yang/ospf-topology@2013-10-21.yang
new file mode 100644 (file)
index 0000000..a8a1507
--- /dev/null
@@ -0,0 +1,178 @@
+module ospf-topology {
+    yang-version 1;
+    namespace "urn:TBD:params:xml:ns:yang:ospf-topology";
+    // replace with IANA namespace when assigned
+
+    prefix "ospf";
+
+    import network-topology {
+        prefix "nt";
+        revision-date 2013-10-21;
+    }
+
+    import l3-unicast-igp-topology {
+        prefix "l3t";
+        revision-date 2013-10-21;
+    }
+    import ietf-inet-types {
+        prefix "inet";
+       revision-date 2010-09-24;
+    }
+    import ted {
+        prefix "ted";
+        revision-date 2013-10-21;
+    }
+
+    organization "TBD";
+    contact "TBD";
+    description "OSPF Topology model";
+
+    revision "2013-10-21" {
+        description "Initial revision";
+        reference "TBD";
+    }
+
+    typedef area-id {
+        description "OSPF Area ID";
+        type uint32;
+    }
+
+    grouping ospf-topology-type {
+        container ospf {
+            presence "indiates OSPF Topology";
+        }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:topology-types/l3t:l3-unicast-igp-topology" {
+        uses ospf-topology-type;
+    }
+
+    augment "/nt:network-topology/nt:topology/l3t:igp-topology-attributes" {
+        when "../nt:topology-types/l3t:l3-unicast-igp-topology/ospf";
+        container ospf-topology-attributes {
+            leaf area-id {
+                type area-id;
+            }
+        }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node/l3t:igp-node-attributes" {
+        when "../../nt:topology-types/l3t:l3-unicast-igp-topology/ospf";
+        uses ospf-node-attributes;
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:link/l3t:igp-link-attributes" {
+        when "../../nt:topology-types/l3t:l3-unicast-igp-topology/ospf";
+        uses ospf-link-attributes;
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node/l3t:igp-node-attributes/l3t:prefix" {
+        when "../../../nt:topology-types/l3t:l3-unicast-igp-topology/ospf";
+        uses ospf-prefix-attributes;
+    }
+
+    grouping ospf-node-attributes {
+        container ospf-node-attributes {
+            choice router-type {
+                case abr {
+                    leaf abr {
+                        type empty;
+                    }
+                }
+                case asbr {
+                    leaf asbr {
+                        type empty;
+                    }
+                }
+                case internal {
+                    leaf internal {
+                        type empty;
+                    }
+                }
+                case pseudonode {
+                    leaf pseudonode {
+                        type empty;
+                    }
+                }
+            }
+            leaf dr-interface-id {
+                when "../router-type/pseudonode";
+                description "For pseudonodes, DR interface-id";
+                default "0";
+                type uint32;
+            }
+            leaf-list multi-topology-id {
+                description "List of Multi-Topology Identifier up-to 128 (0-127). RFC 4915";
+                max-elements "128";
+
+                type uint8 {
+                    range "0..127";
+                }
+            }
+            leaf capabilities {
+                description "OSPF capabilities as bit vector. RFC 4970";
+                type bits {
+                    bit graceful-restart-capable {
+                        position 0;
+                    }
+                    bit graceful-restart-helper {
+                        position 1;
+                    }
+                    bit stub-router-support {
+                        position 2;
+                    }
+                    bit traffic-engineering-support {
+                        position 3;
+                    }
+                    bit point-to-point-over-lan {
+                        position 4;
+                    }
+                    bit experimental-te {
+                        position 5;
+                    }
+                }
+            }
+            container ted {
+                uses ted:ted-node-attributes;
+            }
+        } // ospf
+    } // ospf-node-attributes
+
+    grouping ospf-link-attributes {
+        container ospf-link-attributes {
+            leaf multi-topology-id {
+                type uint8 {
+                    range "0..127";
+                }
+            }
+            container ted {
+                uses ted:ted-link-attributes;
+            }
+        }
+    } // ospf-link-attributes
+
+    grouping ospf-prefix-attributes {
+        container ospf-prefix-attributes {
+
+            leaf forwarding-address {
+                when "../../l3t:l3-unicast-igp-topology/l3t:ospf/l3t:router-type/l3t:asbr";
+                type inet:ipv4-address;
+            }
+        }
+    }
+
+    augment "/l3t:igp-node-event" {
+        uses ospf-topology-type;
+        uses ospf:ospf-node-attributes;
+    }
+
+    augment "/l3t:igp-link-event" {
+        uses ospf-topology-type;
+        uses ospf:ospf-link-attributes;
+    }
+
+    augment "/l3t:igp-prefix-event" {
+        uses ospf-topology-type;
+        uses ospf:ospf-prefix-attributes;
+    }
+}
diff --git a/model/ietf/ietf-topology/pom.xml b/model/ietf/ietf-topology/pom.xml
new file mode 100644 (file)
index 0000000..1954710
--- /dev/null
@@ -0,0 +1,52 @@
+<?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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-topology</artifactId>
+    <version>2013.10.21.8-SNAPSHOT</version>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-yang-types</artifactId>
+        </dependency>
+    </dependencies>
+
+    <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/model/ietf/ietf-topology/src/main/yang/network-topology@2013-07-12.yang b/model/ietf/ietf-topology/src/main/yang/network-topology@2013-07-12.yang
new file mode 100644 (file)
index 0000000..b87035c
--- /dev/null
@@ -0,0 +1,316 @@
+module network-topology  {
+    yang-version 1;
+    namespace "urn:TBD:params:xml:ns:yang:network-topology";
+    // replace with IANA namespace when assigned
+    prefix "nt";
+
+    import ietf-inet-types { prefix "inet"; }
+
+    organization "TBD";
+
+    contact "WILL-BE-DEFINED-LATER";
+/*
+    description 
+        "This module defines a model for the topology of a network.
+        Key design decisions are as follows:
+        A topology consists of a set of nodes and links.  
+        Links are point-to-point and unidirectional.  
+        Bidirectional connections need to be represented through
+        two separate links.  
+        Multipoint connections, broadcast domains etc can be represented 
+        through a hierarchy of nodes, then connecting nodes at 
+        upper layers of the hierarchy.";  
+*/
+    revision 2013-07-12 {
+        description
+            "Initial revision.";
+    }
+        
+    typedef topology-id {
+        type inet:uri;
+        description 
+            "An identifier for a topology.";
+    }
+
+    typedef node-id {
+        type inet:uri;
+        description
+            "An identifier for a node in a topology.  
+            The identifier may be opaque.  
+            The identifier SHOULD be chosen such that the same node in a 
+            real network topology will always be identified through the 
+            same identifier, even if the model is instantiated in separate 
+            datastores. An implementation MAY choose to capture semantics 
+            in the identifier, for example to indicate the type of node 
+            and/or the type of topology that the node is a part of.";  
+    }
+
+    typedef link-id {
+        type inet:uri;
+        description
+            "An identifier for a link in a topology.  
+            The identifier may be opaque.  
+            The identifier SHOULD be chosen such that the same link in a 
+            real network topology will always be identified through the 
+            same identifier, even if the model is instantiated in separate 
+            datastores. An implementation MAY choose to capture semantics 
+            in the identifier, for example to indicate the type of link 
+            and/or the type of topology that the link is a part of.";  
+    }
+
+    typedef tp-id {
+        type inet:uri;
+        description 
+            "An identifier for termination points on a node. 
+            The identifier may be opaque.  
+            The identifier SHOULD be chosen such that the same TP in a 
+            real network topology will always be identified through the 
+            same identifier, even if the model is instantiated in separate 
+            datastores. An implementation MAY choose to capture semantics 
+            in the identifier, for example to indicate the type of TP 
+            and/or the type of node and topology that the TP is a part of.";  
+    }
+
+    typedef tp-ref {
+        type leafref {
+            path "/network-topology/topology/node/termination-point/tp-id";
+        }
+        description 
+            "A type for an absolute reference to a termination point.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+    typedef topology-ref {
+        type leafref {
+            path "/network-topology/topology/topology-id";
+        }
+        description 
+            "A type for an absolute reference a topology instance.";
+    }
+    
+    typedef node-ref {
+        type leafref {
+            path "/network-topology/topology/node/node-id";
+        }
+        description 
+            "A type for an absolute reference to a node instance.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+
+    typedef link-ref {
+        type leafref {
+            path "/network-topology/topology/link/link-id";
+        }
+        description 
+            "A type for an absolute reference a link instance.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+
+    grouping tp-attributes {
+        description 
+            "The data objects needed to define a termination point.
+            (This only includes a single leaf at this point, used
+            to identify the termination point.)  
+            Provided in a grouping so that in addition to the datastore,
+            the data can also be included in notifications.";
+        leaf tp-id {
+            type tp-id;
+        }
+        leaf-list tp-ref {
+            type tp-ref;
+            config false;
+            description 
+                "The leaf list identifies any termination points that the 
+                termination point is dependent on, or maps onto.  
+                Those termination points will themselves be contained 
+                in a supporting node.  
+                This dependency information can be inferred from 
+                the dependencies between links.  For this reason, 
+                this item is not separately configurable.  Hence no
+                corresponding constraint needs to be articulated.  
+                The corresponding information is simply provided by the
+                implementing system.";
+        }
+    } 
+    
+    grouping node-attributes {
+        description
+            "The data objects needed to define a node.
+            The objects are provided in a grouping so that in addition to
+            the datastore, the data can also be included in notifications
+            as needed.";
+        leaf node-id {
+            type node-id;
+            description 
+                "The identifier of a node in the topology.  
+                A node is specific to a topology to which it belongs.";   
+        }
+        list supporting-node {
+            description 
+                "This list defines vertical layering information for nodes. 
+                It allows to capture for any given node, which node (or nodes)
+                in the corresponding underlay topology it maps onto.  
+                A node can map to zero, one, or more nodes below it;
+                accordingly there can be zero, one, or more elements in the list.
+                If there are specific layering requirements, for example
+                specific to a particular type of topology that only allows
+                for certain layering relationships, the choice
+                below can be augmented with additional cases.
+                A list has been chosen rather than a leaf-list in order 
+                to provide room for augmentations, e.g. for 
+                statistics or priorization information associated with 
+                supporting nodes.";
+            key "node-ref";
+            leaf node-ref {
+                type node-ref;
+            }
+        }
+    }
+            
+    grouping link-attributes {
+        // This is a grouping, not defined inline with the link definition itself,
+        // so it can be included in a notification, if needed
+        leaf link-id {
+            type link-id;
+            description
+                "The identifier of a link in the topology.  
+                A link is specific to a topology to which it belongs.";   
+        }
+        container source { 
+            leaf source-node {
+                mandatory true;
+                type node-ref; 
+                description 
+                    "Source node identifier, must be in same topology.";
+            }
+            leaf source-tp {
+                type tp-ref; 
+                description 
+                    "Termination point within source node that terminates the link.";           
+            }
+        }
+        container destination { 
+            leaf dest-node {
+                mandatory true;
+                type node-ref; 
+                description 
+                    "Destination node identifier, must be in same topology.";
+            }
+            leaf dest-tp {
+                type tp-ref;
+                description 
+                    "Termination point within destination node that terminates the link.";
+            }
+        }
+        list supporting-link {
+            key "link-ref";
+            leaf link-ref {
+                type link-ref;
+            }
+        }
+    }
+    
+
+    container network-topology {
+        list topology {
+            description "
+                This is the model of an abstract topology.
+                A topology contins nodes and links.  
+                Each topology MUST be identified by
+                unique topology-id for reason that a network could contain many
+                topologies.
+            ";
+            key "topology-id";
+            leaf topology-id {
+                type topology-id; 
+                description "
+                    It is presumed that a datastore will contain many topologies. To
+                    distinguish between topologies it is vital to have UNIQUE
+                    topology identifiers.
+                ";
+            }
+            container topology-types {
+                description 
+                    "This container is used to identify the type, or types 
+                    (as a topology can support several types simultaneously), 
+                    of the topology.  
+                    Topology types are the subject of several integrity constraints 
+                    that an implementing server can validate in order to 
+                    maintain integrity of the datastore.  
+                    Topology types are indicated through separate data nodes; 
+                    the set of topology types is expected to increase over time.
+                    To add support for a new topology, an augmenting module
+                    needs to augment this container with a new empty optional 
+                    container to indicate the new topology type.  
+                    The use of a container allows to indicate a subcategorization
+                    of topology types.  
+                    The container SHALL NOT be augmented with any data nodes 
+                    that serve a purpose other than identifying a particular 
+                    topology type.  
+                ";
+            }   
+            list underlay-topology {
+                key "topology-ref";
+                leaf topology-ref {
+                    type topology-ref;
+                }  
+                // a list, not a leaf-list, to allow for potential augmentation 
+                // with properties specific to the underlay topology, 
+                // such as statistics, preferences, or cost.  
+                description 
+                    "Identifies the topology, or topologies, that this topology
+                    is dependent on.";
+            }
+            
+            list node {
+                description "The list of network nodes defined for the topology.";
+                key "node-id";
+                uses node-attributes;
+                must "boolean(../underlay-topology[*]/node[./supporting-nodes/node-ref])";
+                    // This constraint is meant to ensure that a referenced node is in fact 
+                    // a node in an underlay topology.  
+                list termination-point {
+                    description
+                        "A termination point can terminate a link.  
+                        Depending on the type of topology, a termination point could, 
+                        for example, refer to a port or an interface."; 
+                    key "tp-id";
+                    uses tp-attributes;
+                }
+            }
+            
+            list link {
+                description "
+                    A Network Link connects a by Local (Source) node and
+                    a Remote (Destination) Network Nodes via a set of the 
+                    nodes' termination points. 
+                    As it is possible to have several links between the same
+                    source and destination nodes, and as a link could potentially
+                    be re-homed between termination points, to ensure that we 
+                    would always know to distinguish between links, every link 
+                    is identified by a dedicated link identifier.  
+                    Note that a link models a point-to-point link, not a multipoint
+                    link.  
+                    Layering dependencies on links in underlay topologies are
+                    not represented as the layering information of nodes and of 
+                    termination points is sufficient.  
+                ";
+                key "link-id";
+                uses link-attributes;
+                must "boolean(../underlay-topology/link[./supporting-link])";
+                    // Constraint: any supporting link must be part of an underlay topology
+                must "boolean(../node[./source/source-node])";
+                    // Constraint: A link must have as source a node of the same topology
+                must "boolean(../node[./destination/dest-node])";
+                    // Constraint: A link must have as source a destination of the same topology
+                must "boolean(../node/termination-point[./source/source-tp])";
+                    // Constraint: The source termination point must be contained in the source node
+                must "boolean(../node/termination-point[./destination/dest-tp])";
+                    // Constraint: The destination termination point must be contained 
+                    // in the destination node
+            }
+        }
+    }
+}
diff --git a/model/ietf/ietf-topology/src/main/yang/network-topology@2013-10-21.yang b/model/ietf/ietf-topology/src/main/yang/network-topology@2013-10-21.yang
new file mode 100644 (file)
index 0000000..a5103aa
--- /dev/null
@@ -0,0 +1,339 @@
+module network-topology  {
+    yang-version 1;
+    namespace "urn:TBD:params:xml:ns:yang:network-topology";
+    // replace with IANA namespace when assigned
+    prefix "nt";
+
+    import ietf-inet-types { prefix "inet"; revision-date 2010-09-24; }
+
+    organization "TBD";
+
+    contact "WILL-BE-DEFINED-LATER";
+
+    description
+        "This module defines a model for the topology of a network.
+        Key design decisions are as follows:
+        A topology consists of a set of nodes and links.
+        Links are point-to-point and unidirectional.
+        Bidirectional connections need to be represented through
+        two separate links.
+        Multipoint connections, broadcast domains etc can be represented
+        through a hierarchy of nodes, then connecting nodes at
+        upper layers of the hierarchy.";
+
+    revision 2013-10-21 {
+        description
+            "Initial revision.";
+    }
+
+    typedef topology-id {
+        type inet:uri;
+        description
+            "An identifier for a topology.";
+    }
+
+    typedef node-id {
+        type inet:uri;
+        description
+            "An identifier for a node in a topology.
+            The identifier may be opaque.
+            The identifier SHOULD be chosen such that the same node in a
+            real network topology will always be identified through the
+            same identifier, even if the model is instantiated in separate
+            datastores. An implementation MAY choose to capture semantics
+            in the identifier, for example to indicate the type of node
+            and/or the type of topology that the node is a part of.";
+    }
+
+
+    typedef link-id {
+        type inet:uri;
+        description
+            "An identifier for a link in a topology.
+            The identifier may be opaque.
+            The identifier SHOULD be chosen such that the same link in a
+            real network topology will always be identified through the
+            same identifier, even if the model is instantiated in separate
+            datastores. An implementation MAY choose to capture semantics
+            in the identifier, for example to indicate the type of link
+            and/or the type of topology that the link is a part of.";
+    }
+
+    typedef tp-id {
+        type inet:uri;
+        description
+            "An identifier for termination points on a node.
+            The identifier may be opaque.
+            The identifier SHOULD be chosen such that the same TP in a
+            real network topology will always be identified through the
+            same identifier, even if the model is instantiated in separate
+            datastores. An implementation MAY choose to capture semantics
+            in the identifier, for example to indicate the type of TP
+            and/or the type of node and topology that the TP is a part of.";
+    }
+
+    typedef tp-ref {
+        type leafref {
+            path "/network-topology/topology/node/termination-point/tp-id";
+        }
+        description
+            "A type for an absolute reference to a termination point.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+    typedef topology-ref {
+        type leafref {
+            path "/network-topology/topology/topology-id";
+        }
+        description
+            "A type for an absolute reference a topology instance.";
+    }
+
+    typedef node-ref {
+        type leafref {
+            path "/network-topology/topology/node/node-id";
+        }
+        description
+
+            "A type for an absolute reference to a node instance.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+
+    typedef link-ref {
+        type leafref {
+            path "/network-topology/topology/link/link-id";
+        }
+        description
+            "A type for an absolute reference a link instance.
+            (This type should not be used for relative references.
+            In such a case, a relative path should be used instead.)";
+    }
+
+    grouping tp-attributes {
+        description
+            "The data objects needed to define a termination point.
+            (This only includes a single leaf at this point, used
+            to identify the termination point.)
+            Provided in a grouping so that in addition to the datastore,
+            the data can also be included in notifications.";
+        leaf tp-id {
+            type tp-id;
+        }
+        leaf-list tp-ref {
+            type tp-ref;
+            config false;
+            description
+                "The leaf list identifies any termination points that the
+                termination point is dependent on, or maps onto.
+                Those termination points will themselves be contained
+                in a supporting node.
+                This dependency information can be inferred from
+                the dependencies between links.  For this reason,
+                this item is not separately configurable.  Hence no
+                corresponding constraint needs to be articulated.
+                The corresponding information is simply provided by the
+                implementing system.";
+        }
+    }
+
+    grouping node-attributes {
+        description
+            "The data objects needed to define a node.
+            The objects are provided in a grouping so that in addition to
+            the datastore, the data can also be included in notifications
+            as needed.";
+
+        leaf node-id {
+            type node-id;
+            description
+                "The identifier of a node in the topology.
+                A node is specific to a topology to which it belongs.";
+        }
+        list supporting-node {
+            description
+                "This list defines vertical layering information for nodes.
+                It allows to capture for any given node, which node (or nodes)
+                in the corresponding underlay topology it maps onto.
+                A node can map to zero, one, or more nodes below it;
+                accordingly there can be zero, one, or more elements in the list.
+                If there are specific layering requirements, for example
+                specific to a particular type of topology that only allows
+                for certain layering relationships, the choice
+                below can be augmented with additional cases.
+                A list has been chosen rather than a leaf-list in order
+                to provide room for augmentations, e.g. for
+                statistics or priorization information associated with
+                supporting nodes.";
+            // This is not what was published in the initial draft,
+            // added topology-ref leaf and added it to the key
+            key "topology-ref node-ref";
+            leaf topology-ref {
+                type topology-ref;
+            }
+            leaf node-ref {
+                type node-ref;
+            }
+        }
+    }
+
+    grouping link-attributes {
+        // This is a grouping, not defined inline with the link definition itself,
+        // so it can be included in a notification, if needed
+        leaf link-id {
+            type link-id;
+            description
+                "The identifier of a link in the topology.
+                A link is specific to a topology to which it belongs.";
+        }
+        container source {
+            leaf source-node {
+                mandatory true;
+                type node-ref;
+                description
+                    "Source node identifier, must be in same topology.";
+            }
+            leaf source-tp {
+                type tp-ref;
+                description
+                    "Termination point within source node that terminates the link.";
+
+            }
+        }
+        container destination {
+            leaf dest-node {
+                mandatory true;
+                type node-ref;
+                description
+                    "Destination node identifier, must be in same topology.";
+            }
+            leaf dest-tp {
+                type tp-ref;
+                description
+                    "Termination point within destination node that terminates the link.";
+            }
+        }
+        list supporting-link {
+            key "link-ref";
+            leaf link-ref {
+                type link-ref;
+            }
+        }
+    }
+
+
+    container network-topology {
+        list topology {
+            description "
+                This is the model of an abstract topology.
+                A topology contains nodes and links.
+                Each topology MUST be identified by
+                unique topology-id for reason that a network could contain many
+                topologies.
+            ";
+            key "topology-id";
+            leaf topology-id {
+                type topology-id;
+                description "
+                    It is presumed that a datastore will contain many topologies. To
+                    distinguish between topologies it is vital to have UNIQUE
+                    topology identifiers.
+                ";
+            }
+            leaf server-provided {
+                type boolean;
+                config false;
+                description "
+                    Indicates whether the topology is configurable by clients,
+                    or whether it is provided by the server.  This leaf is
+
+                    populated by the server implementing the model.
+                    It is set to false for topologies that are created by a client;
+                    it is set to true otherwise.  If it is set to true, any
+                    attempt to edit the topology MUST be rejected.
+                ";
+            }
+            container topology-types {
+                description
+                    "This container is used to identify the type, or types
+                    (as a topology can support several types simultaneously),
+                    of the topology.
+                    Topology types are the subject of several integrity constraints
+                    that an implementing server can validate in order to
+                    maintain integrity of the datastore.
+                    Topology types are indicated through separate data nodes;
+                    the set of topology types is expected to increase over time.
+                    To add support for a new topology, an augmenting module
+                    needs to augment this container with a new empty optional
+                    container to indicate the new topology type.
+                    The use of a container allows to indicate a subcategorization
+                    of topology types.
+                    The container SHALL NOT be augmented with any data nodes
+                    that serve a purpose other than identifying a particular
+                    topology type.
+                ";
+            }
+            list underlay-topology {
+                key "topology-ref";
+                leaf topology-ref {
+                    type topology-ref;
+                }
+                // a list, not a leaf-list, to allow for potential augmentation
+                // with properties specific to the underlay topology,
+                // such as statistics, preferences, or cost.
+                description
+                    "Identifies the topology, or topologies, that this topology
+                    is dependent on.";
+            }
+
+            list node {
+                description "The list of network nodes defined for the topology.";
+                key "node-id";
+                uses node-attributes;
+                must "boolean(../underlay-topology[*]/node[./supporting-nodes/node-ref])";
+                    // This constraint is meant to ensure that a referenced node is in fact
+                    // a node in an underlay topology.
+                list termination-point {
+                    description
+
+                        "A termination point can terminate a link.
+                        Depending on the type of topology, a termination point could,
+                        for example, refer to a port or an interface.";
+                    key "tp-id";
+                    uses tp-attributes;
+                }
+            }
+
+            list link {
+                description "
+                    A Network Link connects a by Local (Source) node and
+                    a Remote (Destination) Network Nodes via a set of the
+                    nodes' termination points.
+                    As it is possible to have several links between the same
+                    source and destination nodes, and as a link could potentially
+                    be re-homed between termination points, to ensure that we
+                    would always know to distinguish between links, every link
+                    is identified by a dedicated link identifier.
+                    Note that a link models a point-to-point link, not a multipoint
+                    link.
+                    Layering dependencies on links in underlay topologies are
+                    not represented as the layering information of nodes and of
+                    termination points is sufficient.
+                ";
+                key "link-id";
+                uses link-attributes;
+                must "boolean(../underlay-topology/link[./supporting-link])";
+                    // Constraint: any supporting link must be part of an underlay topology
+                must "boolean(../node[./source/source-node])";
+                    // Constraint: A link must have as source a node of the same topology
+                must "boolean(../node[./destination/dest-node])";
+                    // Constraint: A link must have as source a destination of the same topology
+                must "boolean(../node/termination-point[./source/source-tp])";
+                    // Constraint: The source termination point must be contained in the source node
+                must "boolean(../node/termination-point[./destination/dest-tp])";
+                    // Constraint: The destination termination point must be contained
+                    // in the destination node
+            }
+        }
+    }
+}
diff --git a/model/ietf/ietf-yang-types-20130715/pom.xml b/model/ietf/ietf-yang-types-20130715/pom.xml
new file mode 100644 (file)
index 0000000..9d6c5ee
--- /dev/null
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+* Copyright (c) 2014 Brocade Communications 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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-yang-types-20130715</artifactId>
+    <version>2013.07.15.8-SNAPSHOT</version>
+    <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/model/ietf/ietf-yang-types-20130715/src/main/yang/ietf-yang-types@2013-07-15.yang b/model/ietf/ietf-yang-types-20130715/src/main/yang/ietf-yang-types@2013-07-15.yang
new file mode 100644 (file)
index 0000000..bdff18c
--- /dev/null
@@ -0,0 +1,467 @@
+module ietf-yang-types {
+
+     namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types";
+     prefix "yang";
+
+     organization
+      "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+     contact
+      "WG Web:   <http://tools.ietf.org/wg/netmod/>
+       WG List:  <mailto:netmod@ietf.org>
+       WG Chair: David Kessens
+                 <mailto:david.kessens@nsn.com>
+
+       WG Chair: Juergen Schoenwaelder
+                 <mailto:j.schoenwaelder@jacobs-university.de>
+
+       Editor:   Juergen Schoenwaelder
+                 <mailto:j.schoenwaelder@jacobs-university.de>";
+
+     description
+      "This module contains a collection of generally useful derived
+       YANG data types.
+
+       Copyright (c) 2013 IETF Trust and the persons identified as
+       authors of the code.  All rights reserved.
+
+       Redistribution and use in source and binary forms, with or
+       without modification, is permitted pursuant to, and subject
+       to the license terms contained in, the Simplified BSD License
+       set forth in Section 4.c of the IETF Trust's Legal Provisions
+       Relating to IETF Documents
+       (http://trustee.ietf.org/license-info).
+
+       This version of this YANG module is part of RFC 6991; see
+       the RFC itself for full legal notices.";
+
+     revision 2013-07-15 {
+       description
+        "This revision adds the following new data types:
+         - yang-identifier
+         - hex-string
+         - uuid
+         - dotted-quad";
+       reference
+        "RFC 6991: Common YANG Data Types";
+     }
+
+     revision 2010-09-24 {
+       description
+        "Initial revision.";
+       reference
+        "RFC 6021: Common YANG Data Types";
+     }
+
+     /*** collection of counter and gauge types ***/
+
+     typedef counter32 {
+       type uint32;
+       description
+        "The counter32 type represents a non-negative integer
+         that monotonically increases until it reaches a
+         maximum value of 2^32-1 (4294967295 decimal), when it
+         wraps around and starts increasing again from zero.
+
+         Counters have no defined 'initial' value, and thus, a
+         single value of a counter has (in general) no information
+         content.  Discontinuities in the monotonically increasing
+         value normally occur at re-initialization of the
+         management system, and at other times as specified in the
+         description of a schema node using this type.  If such
+         other times can occur, for example, the creation of
+         a schema node of type counter32 at times other than
+         re-initialization, then a corresponding schema node
+         should be defined, with an appropriate type, to indicate
+         the last discontinuity.
+
+         The counter32 type should not be used for configuration
+         schema nodes.  A default statement SHOULD NOT be used in
+         combination with the type counter32.
+
+         In the value set and its semantics, this type is equivalent
+         to the Counter32 type of the SMIv2.";
+       reference
+        "RFC 2578: Structure of Management Information Version 2
+                   (SMIv2)";
+     }
+
+     typedef zero-based-counter32 {
+       type yang:counter32;
+       default "0";
+       description
+        "The zero-based-counter32 type represents a counter32
+         that has the defined 'initial' value zero.
+
+         A schema node of this type will be set to zero (0) on creation
+         and will thereafter increase monotonically until it reaches
+         a maximum value of 2^32-1 (4294967295 decimal), when it
+         wraps around and starts increasing again from zero.
+
+         Provided that an application discovers a new schema node
+         of this type within the minimum time to wrap, it can use the
+         'initial' value as a delta.  It is important for a management
+         station to be aware of this minimum time and the actual time
+         between polls, and to discard data if the actual time is too
+         long or there is no defined minimum time.
+        In the value set and its semantics, this type is equivalent
+         to the ZeroBasedCounter32 textual convention of the SMIv2.";
+       reference
+         "RFC 4502: Remote Network Monitoring Management Information
+                    Base Version 2";
+     }
+
+     typedef counter64 {
+       type uint64;
+       description
+        "The counter64 type represents a non-negative integer
+         that monotonically increases until it reaches a
+         maximum value of 2^64-1 (18446744073709551615 decimal),
+         when it wraps around and starts increasing again from zero.
+
+         Counters have no defined 'initial' value, and thus, a
+         single value of a counter has (in general) no information
+         content.  Discontinuities in the monotonically increasing
+         value normally occur at re-initialization of the
+         management system, and at other times as specified in the
+         description of a schema node using this type.  If such
+         other times can occur, for example, the creation of
+         a schema node of type counter64 at times other than
+         re-initialization, then a corresponding schema node
+         should be defined, with an appropriate type, to indicate
+         the last discontinuity.
+
+         The counter64 type should not be used for configuration
+         schema nodes.  A default statement SHOULD NOT be used in
+         combination with the type counter64.
+
+         In the value set and its semantics, this type is equivalent
+         to the Counter64 type of the SMIv2.";
+       reference
+        "RFC 2578: Structure of Management Information Version 2
+                   (SMIv2)";
+     }
+
+     typedef zero-based-counter64 {
+       type yang:counter64;
+       default "0";
+       description
+        "The zero-based-counter64 type represents a counter64 that
+         has the defined 'initial' value zero.
+         A schema node of this type will be set to zero (0) on creation
+         and will thereafter increase monotonically until it reaches
+         a maximum value of 2^64-1 (18446744073709551615 decimal),
+         when it wraps around and starts increasing again from zero.
+
+         Provided that an application discovers a new schema node
+         of this type within the minimum time to wrap, it can use the
+         'initial' value as a delta.  It is important for a management
+         station to be aware of this minimum time and the actual time
+         between polls, and to discard data if the actual time is too
+         long or there is no defined minimum time.
+
+         In the value set and its semantics, this type is equivalent
+         to the ZeroBasedCounter64 textual convention of the SMIv2.";
+       reference
+        "RFC 2856: Textual Conventions for Additional High Capacity
+                   Data Types";
+     }
+
+     typedef gauge32 {
+       type uint32;
+       description
+        "The gauge32 type represents a non-negative integer, which
+         may increase or decrease, but shall never exceed a maximum
+         value, nor fall below a minimum value.  The maximum value
+         cannot be greater than 2^32-1 (4294967295 decimal), and
+         the minimum value cannot be smaller than 0.  The value of
+         a gauge32 has its maximum value whenever the information
+         being modeled is greater than or equal to its maximum
+         value, and has its minimum value whenever the information
+         being modeled is smaller than or equal to its minimum value.
+         If the information being modeled subsequently decreases
+         below (increases above) the maximum (minimum) value, the
+         gauge32 also decreases (increases).
+
+         In the value set and its semantics, this type is equivalent
+         to the Gauge32 type of the SMIv2.";
+       reference
+        "RFC 2578: Structure of Management Information Version 2
+                   (SMIv2)";
+     }
+
+     typedef gauge64 {
+       type uint64;
+       description
+        "The gauge64 type represents a non-negative integer, which
+         may increase or decrease, but shall never exceed a maximum
+         value, nor fall below a minimum value.  The maximum value
+         cannot be greater than 2^64-1 (18446744073709551615), and
+         the minimum value cannot be smaller than 0.  The value of
+         a gauge64 has its maximum value whenever the information
+         being modeled is greater than or equal to its maximum
+         value, and has its minimum value whenever the information
+         being modeled is smaller than or equal to its minimum value.
+         If the information being modeled subsequently decreases
+         below (increases above) the maximum (minimum) value, the
+         gauge64 also decreases (increases).
+
+         In the value set and its semantics, this type is equivalent
+         to the CounterBasedGauge64 SMIv2 textual convention defined
+         in RFC 2856";
+       reference
+        "RFC 2856: Textual Conventions for Additional High Capacity
+                   Data Types";
+     }
+
+     /*** collection of identifier-related types ***/
+
+     typedef object-identifier {
+       type string {
+         pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))'
+               + '(\.(0|([1-9]\d*)))*';
+       }
+       description
+        "The object-identifier type represents administratively
+         assigned names in a registration-hierarchical-name tree.
+
+         Values of this type are denoted as a sequence of numerical
+         non-negative sub-identifier values.  Each sub-identifier
+         value MUST NOT exceed 2^32-1 (4294967295).  Sub-identifiers
+         are separated by single dots and without any intermediate
+         whitespace.
+
+         The ASN.1 standard restricts the value space of the first
+         sub-identifier to 0, 1, or 2.  Furthermore, the value space
+         of the second sub-identifier is restricted to the range
+         0 to 39 if the first sub-identifier is 0 or 1.  Finally,
+         the ASN.1 standard requires that an object identifier
+         has always at least two sub-identifiers.  The pattern
+         captures these restrictions.
+
+         Although the number of sub-identifiers is not limited,
+         module designers should realize that there may be
+         implementations that stick with the SMIv2 limit of 128
+         sub-identifiers.
+         This type is a superset of the SMIv2 OBJECT IDENTIFIER type
+         since it is not restricted to 128 sub-identifiers.  Hence,
+         this type SHOULD NOT be used to represent the SMIv2 OBJECT
+         IDENTIFIER type; the object-identifier-128 type SHOULD be
+         used instead.";
+       reference
+        "ISO9834-1: Information technology -- Open Systems
+         Interconnection -- Procedures for the operation of OSI
+         Registration Authorities: General procedures and top
+         arcs of the ASN.1 Object Identifier tree";
+     }
+
+     typedef object-identifier-128 {
+       type object-identifier {
+         pattern '\d*(\.\d*){1,127}';
+       }
+       description
+        "This type represents object-identifiers restricted to 128
+         sub-identifiers.
+
+         In the value set and its semantics, this type is equivalent
+         to the OBJECT IDENTIFIER type of the SMIv2.";
+       reference
+        "RFC 2578: Structure of Management Information Version 2
+                   (SMIv2)";
+     }
+
+     typedef yang-identifier {
+       type string {
+         length "1..max";
+         pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*';
+         pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*';
+       }
+       description
+         "A YANG identifier string as defined by the 'identifier'
+          rule in Section 12 of RFC 6020.  An identifier must
+          start with an alphabetic character or an underscore
+          followed by an arbitrary sequence of alphabetic or
+          numeric characters, underscores, hyphens, or dots.
+
+          A YANG identifier MUST NOT start with any possible
+          combination of the lowercase or uppercase character
+          sequence 'xml'.";
+       reference
+         "RFC 6020: YANG - A Data Modeling Language for the Network
+                    Configuration Protocol (NETCONF)";
+     }
+     /*** collection of types related to date and time***/
+
+     typedef date-and-time {
+       type string {
+         pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
+               + '(Z|[\+\-]\d{2}:\d{2})';
+       }
+       description
+        "The date-and-time type is a profile of the ISO 8601
+         standard for representation of dates and times using the
+         Gregorian calendar.  The profile is defined by the
+         date-time production in Section 5.6 of RFC 3339.
+
+         The date-and-time type is compatible with the dateTime XML
+         schema type with the following notable exceptions:
+
+         (a) The date-and-time type does not allow negative years.
+
+         (b) The date-and-time time-offset -00:00 indicates an unknown
+             time zone (see RFC 3339) while -00:00 and +00:00 and Z
+             all represent the same time zone in dateTime.
+
+         (c) The canonical format (see below) of data-and-time values
+             differs from the canonical format used by the dateTime XML
+             schema type, which requires all times to be in UTC using
+             the time-offset 'Z'.
+
+         This type is not equivalent to the DateAndTime textual
+         convention of the SMIv2 since RFC 3339 uses a different
+         separator between full-date and full-time and provides
+         higher resolution of time-secfrac.
+
+         The canonical format for date-and-time values with a known time
+         zone uses a numeric time zone offset that is calculated using
+         the device's configured known offset to UTC time.  A change of
+         the device's offset to UTC time will cause date-and-time values
+         to change accordingly.  Such changes might happen periodically
+         in case a server follows automatically daylight saving time
+         (DST) time zone offset changes.  The canonical format for
+         date-and-time values with an unknown time zone (usually
+         referring to the notion of local time) uses the time-offset
+         -00:00.";
+       reference
+        "RFC 3339: Date and Time on the Internet: Timestamps
+         RFC 2579: Textual Conventions for SMIv2
+         XSD-TYPES: XML Schema Part 2: Datatypes Second Edition";
+     }
+     typedef timeticks {
+       type uint32;
+       description
+        "The timeticks type represents a non-negative integer that
+         represents the time, modulo 2^32 (4294967296 decimal), in
+         hundredths of a second between two epochs.  When a schema
+         node is defined that uses this type, the description of
+         the schema node identifies both of the reference epochs.
+
+         In the value set and its semantics, this type is equivalent
+         to the TimeTicks type of the SMIv2.";
+       reference
+        "RFC 2578: Structure of Management Information Version 2
+                   (SMIv2)";
+     }
+
+     typedef timestamp {
+       type yang:timeticks;
+       description
+        "The timestamp type represents the value of an associated
+         timeticks schema node at which a specific occurrence
+         happened.  The specific occurrence must be defined in the
+         description of any schema node defined using this type.  When
+         the specific occurrence occurred prior to the last time the
+         associated timeticks attribute was zero, then the timestamp
+         value is zero.  Note that this requires all timestamp values
+         to be reset to zero when the value of the associated timeticks
+         attribute reaches 497+ days and wraps around to zero.
+
+         The associated timeticks schema node must be specified
+         in the description of any schema node using this type.
+
+         In the value set and its semantics, this type is equivalent
+         to the TimeStamp textual convention of the SMIv2.";
+       reference
+        "RFC 2579: Textual Conventions for SMIv2";
+     }
+
+     /*** collection of generic address types ***/
+
+     typedef phys-address {
+       type string {
+         pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
+       }
+       description
+        "Represents media- or physical-level addresses represented
+         as a sequence octets, each octet represented by two hexadecimal
+         numbers.  Octets are separated by colons.  The canonical
+         representation uses lowercase characters.
+
+         In the value set and its semantics, this type is equivalent
+         to the PhysAddress textual convention of the SMIv2.";
+       reference
+        "RFC 2579: Textual Conventions for SMIv2";
+     }
+
+     typedef mac-address {
+       type string {
+         pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
+       }
+       description
+        "The mac-address type represents an IEEE 802 MAC address.
+         The canonical representation uses lowercase characters.
+
+         In the value set and its semantics, this type is equivalent
+         to the MacAddress textual convention of the SMIv2.";
+       reference
+        "IEEE 802: IEEE Standard for Local and Metropolitan Area
+                   Networks: Overview and Architecture
+         RFC 2579: Textual Conventions for SMIv2";
+     }
+
+     /*** collection of XML-specific types ***/
+
+     typedef xpath1.0 {
+       type string;
+       description
+        "This type represents an XPATH 1.0 expression.
+
+         When a schema node is defined that uses this type, the
+         description of the schema node MUST specify the XPath
+         context in which the XPath expression is evaluated.";
+       reference
+        "XPATH: XML Path Language (XPath) Version 1.0";
+     }
+
+     /*** collection of string types ***/
+
+     typedef hex-string {
+       type string {
+         pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
+       }
+       description
+        "A hexadecimal string with octets represented as hex digits
+         separated by colons.  The canonical representation uses
+         lowercase characters.";
+     }
+
+     typedef uuid {
+       type string {
+         pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-'
+               + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}';
+       }
+       description
+        "A Universally Unique IDentifier in the string representation
+         defined in RFC 4122.  The canonical representation uses
+         lowercase characters.
+
+         The following is an example of a UUID in string representation:
+         f81d4fae-7dec-11d0-a765-00a0c91e6bf6
+         ";
+       reference
+        "RFC 4122: A Universally Unique IDentifier (UUID) URN
+                   Namespace";
+     }
+
+     typedef dotted-quad {
+       type string {
+         pattern
+           '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+         + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])';
+       }
+       description
+         "An unsigned 32-bit number expressed in the dotted-quad
+          notation, i.e., four octets written as decimal numbers
+          and separated with the '.' (full stop) character.";
+     }
+   }
\ No newline at end of file
diff --git a/model/ietf/ietf-yang-types/pom.xml b/model/ietf/ietf-yang-types/pom.xml
new file mode 100644 (file)
index 0000000..9c20f89
--- /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>
+        <artifactId>model-ietf</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>ietf-yang-types</artifactId>
+    <version>2010.09.24.8-SNAPSHOT</version>
+    <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/model/ietf/ietf-yang-types/src/main/yang/ietf-yang-types.yang b/model/ietf/ietf-yang-types/src/main/yang/ietf-yang-types.yang
new file mode 100644 (file)
index 0000000..51d9f8b
--- /dev/null
@@ -0,0 +1,396 @@
+ module ietf-yang-types {
+
+   namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types";
+   prefix "yang";
+
+   organization
+    "IETF NETMOD (NETCONF Data Modeling Language) Working Group";
+
+   contact
+    "WG Web:   <http://tools.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     WG Chair: David Partain
+               <mailto:david.partain@ericsson.com>
+
+     WG Chair: David Kessens
+               <mailto:david.kessens@nsn.com>
+
+     Editor:   Juergen Schoenwaelder
+               <mailto:j.schoenwaelder@jacobs-university.de>";
+
+   description
+    "This module contains a collection of generally useful derived
+     YANG data types.
+
+     Copyright (c) 2010 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or without
+     modification, is permitted pursuant to, and subject to the license
+     terms contained in, the Simplified BSD License set forth in Section
+     4.c of the IETF Trust's Legal Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 6021; see
+     the RFC itself for full legal notices.";
+
+   revision 2010-09-24 {
+     description
+      "Initial revision.";
+     reference
+      "RFC 6021: Common YANG Data Types";
+   }
+
+   /*** collection of counter and gauge types ***/
+
+   typedef counter32 {
+     type uint32;
+     description
+      "The counter32 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter32 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter32 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter32.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter32 {
+     type yang:counter32;
+     default "0";
+     description
+      "The zero-based-counter32 type represents a counter32
+       that has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^32-1 (4294967295 decimal), when it
+       wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter32 textual convention of the SMIv2.";
+     reference
+       "RFC 4502: Remote Network Monitoring Management Information
+                  Base Version 2";
+   }
+
+   typedef counter64 {
+     type uint64;
+     description
+      "The counter64 type represents a non-negative integer
+       that monotonically increases until it reaches a
+       maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Counters have no defined 'initial' value, and thus, a
+       single value of a counter has (in general) no information
+       content.  Discontinuities in the monotonically increasing
+       value normally occur at re-initialization of the
+       management system, and at other times as specified in the
+       description of a schema node using this type.  If such
+       other times can occur, for example, the creation of
+       a schema node of type counter64 at times other than
+       re-initialization, then a corresponding schema node
+       should be defined, with an appropriate type, to indicate
+       the last discontinuity.
+
+       The counter64 type should not be used for configuration
+       schema nodes.  A default statement SHOULD NOT be used in
+       combination with the type counter64.
+
+       In the value set and its semantics, this type is equivalent
+       to the Counter64 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef zero-based-counter64 {
+     type yang:counter64;
+     default "0";
+     description
+      "The zero-based-counter64 type represents a counter64 that
+       has the defined 'initial' value zero.
+
+       A schema node of this type will be set to zero (0) on creation
+       and will thereafter increase monotonically until it reaches
+       a maximum value of 2^64-1 (18446744073709551615 decimal),
+       when it wraps around and starts increasing again from zero.
+
+       Provided that an application discovers a new schema node
+       of this type within the minimum time to wrap, it can use the
+       'initial' value as a delta.  It is important for a management
+       station to be aware of this minimum time and the actual time
+       between polls, and to discard data if the actual time is too
+       long or there is no defined minimum time.
+
+       In the value set and its semantics, this type is equivalent
+       to the ZeroBasedCounter64 textual convention of the SMIv2.";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   typedef gauge32 {
+     type uint32;
+     description
+      "The gauge32 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^32-1 (4294967295 decimal), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge32 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge32 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the Gauge32 type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef gauge64 {
+     type uint64;
+     description
+      "The gauge64 type represents a non-negative integer, which
+       may increase or decrease, but shall never exceed a maximum
+       value, nor fall below a minimum value.  The maximum value
+       cannot be greater than 2^64-1 (18446744073709551615), and
+       the minimum value cannot be smaller than 0.  The value of
+       a gauge64 has its maximum value whenever the information
+       being modeled is greater than or equal to its maximum
+       value, and has its minimum value whenever the information
+       being modeled is smaller than or equal to its minimum value.
+       If the information being modeled subsequently decreases
+       below (increases above) the maximum (minimum) value, the
+       gauge64 also decreases (increases).
+
+       In the value set and its semantics, this type is equivalent
+       to the CounterBasedGauge64 SMIv2 textual convention defined
+       in RFC 2856";
+     reference
+      "RFC 2856: Textual Conventions for Additional High Capacity
+                 Data Types";
+   }
+
+   /*** collection of identifier related types ***/
+
+   typedef object-identifier {
+     type string {
+       pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))'
+             + '(\.(0|([1-9]\d*)))*';
+     }
+     description
+      "The object-identifier type represents administratively
+       assigned names in a registration-hierarchical-name tree.
+
+       Values of this type are denoted as a sequence of numerical
+       non-negative sub-identifier values.  Each sub-identifier
+       value MUST NOT exceed 2^32-1 (4294967295).  Sub-identifiers
+       are separated by single dots and without any intermediate
+       whitespace.
+
+       The ASN.1 standard restricts the value space of the first
+       sub-identifier to 0, 1, or 2.  Furthermore, the value space
+       of the second sub-identifier is restricted to the range
+       0 to 39 if the first sub-identifier is 0 or 1.  Finally,
+       the ASN.1 standard requires that an object identifier
+       has always at least two sub-identifier.  The pattern
+       captures these restrictions.
+
+       Although the number of sub-identifiers is not limited,
+       module designers should realize that there may be
+       implementations that stick with the SMIv2 limit of 128
+       sub-identifiers.
+
+       This type is a superset of the SMIv2 OBJECT IDENTIFIER type
+       since it is not restricted to 128 sub-identifiers.  Hence,
+       this type SHOULD NOT be used to represent the SMIv2 OBJECT
+       IDENTIFIER type, the object-identifier-128 type SHOULD be
+       used instead.";
+     reference
+      "ISO9834-1: Information technology -- Open Systems
+       Interconnection -- Procedures for the operation of OSI
+       Registration Authorities: General procedures and top
+       arcs of the ASN.1 Object Identifier tree";
+   }
+
+
+
+
+   typedef object-identifier-128 {
+     type object-identifier {
+       pattern '\d*(\.\d*){1,127}';
+     }
+     description
+      "This type represents object-identifiers restricted to 128
+       sub-identifiers.
+
+       In the value set and its semantics, this type is equivalent
+       to the OBJECT IDENTIFIER type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   /*** collection of date and time related types ***/
+
+   typedef date-and-time {
+     type string {
+       pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?'
+             + '(Z|[\+\-]\d{2}:\d{2})';
+     }
+     description
+      "The date-and-time type is a profile of the ISO 8601
+       standard for representation of dates and times using the
+       Gregorian calendar.  The profile is defined by the
+       date-time production in Section 5.6 of RFC 3339.
+
+       The date-and-time type is compatible with the dateTime XML
+       schema type with the following notable exceptions:
+
+       (a) The date-and-time type does not allow negative years.
+
+       (b) The date-and-time time-offset -00:00 indicates an unknown
+           time zone (see RFC 3339) while -00:00 and +00:00 and Z all
+           represent the same time zone in dateTime.
+
+       (c) The canonical format (see below) of data-and-time values
+           differs from the canonical format used by the dateTime XML
+           schema type, which requires all times to be in UTC using the
+           time-offset 'Z'.
+
+       This type is not equivalent to the DateAndTime textual
+       convention of the SMIv2 since RFC 3339 uses a different
+       separator between full-date and full-time and provides
+       higher resolution of time-secfrac.
+
+       The canonical format for date-and-time values with a known time
+       zone uses a numeric time zone offset that is calculated using
+       the device's configured known offset to UTC time.  A change of
+       the device's offset to UTC time will cause date-and-time values
+       to change accordingly.  Such changes might happen periodically
+       in case a server follows automatically daylight saving time
+       (DST) time zone offset changes.  The canonical format for
+       date-and-time values with an unknown time zone (usually referring
+       to the notion of local time) uses the time-offset -00:00.";
+     reference
+      "RFC 3339: Date and Time on the Internet: Timestamps
+       RFC 2579: Textual Conventions for SMIv2
+       XSD-TYPES: XML Schema Part 2: Datatypes Second Edition";
+   }
+
+   typedef timeticks {
+     type uint32;
+     description
+      "The timeticks type represents a non-negative integer that
+       represents the time, modulo 2^32 (4294967296 decimal), in
+       hundredths of a second between two epochs.  When a schema
+       node is defined that uses this type, the description of
+       the schema node identifies both of the reference epochs.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeTicks type of the SMIv2.";
+     reference
+      "RFC 2578: Structure of Management Information Version 2 (SMIv2)";
+   }
+
+   typedef timestamp {
+     type yang:timeticks;
+     description
+      "The timestamp type represents the value of an associated
+       timeticks schema node at which a specific occurrence happened.
+       The specific occurrence must be defined in the description
+       of any schema node defined using this type.  When the specific
+       occurrence occurred prior to the last time the associated
+       timeticks attribute was zero, then the timestamp value is
+       zero.  Note that this requires all timestamp values to be
+       reset to zero when the value of the associated timeticks
+       attribute reaches 497+ days and wraps around to zero.
+
+       The associated timeticks schema node must be specified
+       in the description of any schema node using this type.
+
+       In the value set and its semantics, this type is equivalent
+       to the TimeStamp textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of generic address types ***/
+
+   typedef phys-address {
+     type string {
+       pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?';
+     }
+     description
+      "Represents media- or physical-level addresses represented
+       as a sequence octets, each octet represented by two hexadecimal
+       numbers.  Octets are separated by colons.  The canonical
+       representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the PhysAddress textual convention of the SMIv2.";
+     reference
+      "RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   typedef mac-address {
+     type string {
+       pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}';
+     }
+     description
+      "The mac-address type represents an IEEE 802 MAC address.
+       The canonical representation uses lowercase characters.
+
+       In the value set and its semantics, this type is equivalent
+       to the MacAddress textual convention of the SMIv2.";
+     reference
+      "IEEE 802: IEEE Standard for Local and Metropolitan Area
+                 Networks: Overview and Architecture
+       RFC 2579: Textual Conventions for SMIv2";
+   }
+
+   /*** collection of XML specific types ***/
+
+   typedef xpath1.0 {
+     type string;
+     description
+      "This type represents an XPATH 1.0 expression.
+
+       When a schema node is defined that uses this type, the
+       description of the schema node MUST specify the XPath
+       context in which the XPath expression is evaluated.";
+     reference
+      "XPATH: XML Path Language (XPath) Version 1.0";
+   }
+
+ }
diff --git a/model/ietf/pom.xml b/model/ietf/pom.xml
new file mode 100644 (file)
index 0000000..0e958f8
--- /dev/null
@@ -0,0 +1,36 @@
+<?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>
+        <artifactId>model-parent</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>model-ietf</artifactId>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <modules>
+        <module>ietf-inet-types</module>
+        <module>ietf-interfaces</module>
+        <module>ietf-yang-types</module>
+        <module>ietf-yang-types-20130715</module>
+        <module>ietf-ted</module>
+        <module>ietf-topology</module>
+        <module>ietf-topology-isis</module>
+        <module>ietf-topology-l3-unicast-igp</module>
+        <module>ietf-topology-ospf</module>
+        <module>ietf-restconf</module>
+    </modules>
+</project>
diff --git a/model/ietf/src/main/yang/.gitignore b/model/ietf/src/main/yang/.gitignore
new file mode 100644 (file)
index 0000000..e50f3cf
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# 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
+#
+
diff --git a/model/l2-types/pom.xml b/model/l2-types/pom.xml
new file mode 100644 (file)
index 0000000..0b27bcd
--- /dev/null
@@ -0,0 +1,41 @@
+<?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>
+        <artifactId>model-parent</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>opendaylight-l2-types</artifactId>
+    <version>2013.08.27.8-SNAPSHOT</version>
+
+    <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/model/l2-types/src/main/yang/opendaylight-l2-types.yang b/model/l2-types/src/main/yang/opendaylight-l2-types.yang
new file mode 100644 (file)
index 0000000..2eecb51
--- /dev/null
@@ -0,0 +1,223 @@
+module opendaylight-l2-types {
+       namespace "urn:opendaylight:l2:types";
+       prefix "ethertype";
+
+       description 
+               "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";
+
+       revision "2013-08-27" {
+               description "Initial revision";
+       }
+
+       typedef vlan-pcp {
+               description 
+                       "IEEE 802.1p priority. It indicates the frame priority level. 
+                        Values are from 0 (best effort) to 7 (highest); 
+                        1 represents the lowest priority.";
+               type uint8 {
+                       range "0..7";
+               }
+       }
+
+       typedef vlan-dei {
+               description 
+                       "Drop Eligible Indicator (DEI): a 1-bit field. (formerly CFI). 
+                        May be used separately or in conjunction with PCP to indicate frames 
+                        eligible to be dropped in the presence of congestion.";
+               type boolean;
+       }
+
+       typedef vlan-id {
+               type uint16 {
+                       range "0..4095";
+               }
+       }
+
+
+       typedef ether-type {
+               type uint32;
+       }
+       /*
+       typedef known-ether-type {
+               type enumeration {      
+                       enum "ipv4" {
+                               value 2048; // 0x0800
+                               description "Internet Protocol version 4 (IPv4)";
+                       }
+                       enum "arp" {
+                               value 2054; // 0x0806
+                               description "Address Resolution Protocol (ARP)";
+                       }
+                       enum "wake-on-lan" {
+                               value 2114; // 0x0842
+                               description "Wake-on-LAN[3]";
+                       }
+                       enum "ietf-trill" {
+                               value 8947; // 0x22F3
+                               description "IETF TRILL Protocol";
+                       }
+                       enum "decnet-phase-iv" {
+                               value 24579; // 0x6003
+                               description "DECnet Phase IV";
+                       }
+                       enum "reverse-arp" {
+                               value 32821; // 0x8035
+                               description "Reverse Address Resolution Protocol";
+                       }
+                       enum "apple-talk" {
+                               value 32923; // 0x809B
+                               description "AppleTalk (Ethertalk)";
+                       }
+                       enum "apple-talk-arp" {
+                               value 33011; // 0x80F3
+                               description "AppleTalk Address Resolution Protocol (AARP)";
+                       }
+                       enum "vlan-tagged" {
+                               value 33024; // 0x8100
+                               description "VLAN-tagged frame (IEEE 802.1Q) & Shortest Path Bridging IEEE 802.1aq[4]";
+                       }
+                       enum "ipx" {
+                               value 33079; // 0x8137
+                               description "IPX";
+                       }
+                       enum "ipx2" {
+                               value 33080; // 0x8138
+                               description "IPX";
+                       }
+                       enum "qnx-qnet" {
+                               value 33284; // 0x8204
+                               description "QNX Qnet";
+                       }
+                       enum "ipv6" {
+                               value 34525; // 0x86DD
+                               description "Internet Protocol Version 6 (IPv6)";
+                       }
+                       enum "ethernet-flow-control" {
+                               value 34824; // 0x8808
+                               description "Ethernet flow control";
+                       }
+                       enum "slow-protocols" {
+                               value 34825; // 0x8809
+                               description "Slow Protocols (IEEE 802.3)";
+                       }
+                       enum "cobra-net" {
+                               value 34841; // 0x8819
+                               description "CobraNet";
+                       }
+                       enum "mpls-unicast" {
+                               value 34887; // 0x8847
+                               description "MPLS unicast";
+                       }
+                       enum "mpls-multicast" {
+                               value 34888; // 0x8848
+                               description "MPLS multicast";
+                       }
+                       enum "PPP-over-ethernet-discovery" {
+                               value 34915; // 0x8863
+                               description "PPPoE Discovery Stage";
+                       }
+                       enum "PPP-over-ethernet-session" {
+                               value 34916; // 0x8864
+                               description "PPPoE Session Stage";
+                       }
+                       enum "jumbo" {
+                               value 34928; // 0x8870
+                               description "Jumbo Frames[2]";
+                       }
+                       enum "homeplug" {
+                               value 34939; // 0x887B
+                               description "HomePlug 1.0 MME";
+                       }
+                       enum "eap-over-lan" {
+                               value 34958; // 0x888E
+                               description "EAP over LAN (IEEE 802.1X)";
+                       }
+                       enum "profinet" {
+                               value 34962; // 0x8892
+                               description "PROFINET Protocol";
+                       }
+                       enum "hyper-scsi" {
+                               value 34970; // 0x889A
+                               description "HyperSCSI (SCSI over Ethernet)";
+                       }
+                       enum "ata-over-ethernet" {
+                               value 34978; // 0x88A2
+                               description "ATA over Ethernet";
+                       }
+                       enum "ethercat" {
+                               value 34980; // 0x88A4
+                               description "EtherCAT Protocol";
+                       }
+                       enum "provider-bridging" {
+                               value 34984; // 0x88A8
+                               description "Provider Bridging (IEEE 802.1ad) & Shortest Path Bridging IEEE 802.1aq[5]";
+                       }
+                       enum "ethernet-powerlink" {
+                               value 34987; // 0x88AB
+                               description "Ethernet Powerlink[citation needed]";
+                       }
+                       enum "lldp" {
+                               value 35020; // 0x88CC
+                               description "Link Layer Discovery Protocol (LLDP)";
+                       }
+                       enum "sercos-3" {
+                               value 35021; // 0x88CD
+                               description "SERCOS III";
+                       }
+                       enum "homeplug-av-mme" {
+                               value 35041; // 0x88E1
+                               description "HomePlug AV MME[citation needed]";
+                       }
+                       enum "media-redudancy-protocol" {
+                               value 35043; // 0x88E3
+                               description "Media Redundancy Protocol (IEC62439-2)";
+                       }
+                       enum "mac-security" {
+                               value 35045; // 0x88E5
+                               description "MAC security (IEEE 802.1AE)";
+                       }
+                       enum "precision-time-protocol" {
+                               value 35063; // 0x88F7
+                               description "Precision Time Protocol (IEEE 1588)";
+                       }
+                       enum "connectivity-fault-management" {
+                               value 35074; // 0x8902
+                               description "IEEE 802.1ag Connectivity Fault Management (CFM) Protocol / ITU-T Recommendation Y.1731 (OAM)";
+                       }
+                       enum "fibre-channel-over-ethernet" {
+                               value 35078; // 0x8906
+                               description "Fibre Channel over Ethernet (FCoE)";
+                       }
+                       enum "fibre-channel-over-ethernet-initialization" {
+                               value 35092; // 0x8914
+                               description "FCoE Initialization Protocol";
+                       }
+                       enum "rmda-over-converged-ethernet" {
+                               value 35093; // 0x8915
+                               description "RDMA over Converged Ethernet (RoCE)";
+                       }
+                       enum "high-availability-seamless-redudancy" {
+                               value 35119; // 0x892F
+                               description "High-availability Seamless Redundancy (HSR)";
+                       }
+                       enum "ethernet-configuration-testing-protocol" {
+                               value 36864; // 0x9000
+                               description "Ethernet Configuration Testing Protocol[6]";
+                       }
+                       enum "q-in-q" {
+                               value 37120; // 0x9100
+                               description "Q-in-Q";
+                       }
+                       enum "veritas-low-latency" {
+                               value 51966; // 0xCAFE
+                               description "Veritas Low Latency Transport (LLT)[7] for Veritas Cluster Server";
+                       }
+               }
+
+       }
+       */
+}
diff --git a/model/pom.xml b/model/pom.xml
new file mode 100644 (file)
index 0000000..cc77098
--- /dev/null
@@ -0,0 +1,89 @@
+<?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>yangtools-parent</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+        <relativePath>../common/parent</relativePath>
+    </parent>
+    <groupId>org.opendaylight.yangtools.model</groupId>
+    <!--<version>0.8.0-SNAPSHOT</version>-->
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>model-parent</artifactId>
+    <packaging>pom</packaging>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <modules>
+        <module>yang-ext</module>
+        <module>iana</module>
+        <module>ietf</module>
+        <module>l2-types</module>
+    </modules>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <yangFilesRootDir>src/main/yang</yangFilesRootDir>
+                            <codeGenerators>
+                                <generator>
+                                    <codeGeneratorClass>
+                                        org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
+                                    </codeGeneratorClass>
+                                    <outputBaseDir>
+                                        target/generated-sources/sal
+                                    </outputBaseDir>
+                                </generator>
+                                <generator>
+                                    <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
+                                    <outputBaseDir>target/site/restconf</outputBaseDir>
+                                </generator>
+                                <generator>
+                                    <codeGeneratorClass>org.opendaylight.yangtools.yang.wadl.generator.maven.WadlGenerator</codeGeneratorClass>
+                                    <outputBaseDir>target/site/restconf</outputBaseDir>
+                                </generator>
+                            </codeGenerators>
+                            <inspectDependencies>true</inspectDependencies>
+                        </configuration>
+                    </execution>
+                </executions>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>maven-sal-api-gen-plugin</artifactId>
+                        <version>0.8.0-SNAPSHOT</version>
+                        <type>jar</type>
+                    </dependency>
+                </dependencies>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/model/src/main/yang/.gitignore b/model/src/main/yang/.gitignore
new file mode 100644 (file)
index 0000000..e50f3cf
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# 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
+#
+
diff --git a/model/src/site/site.xml b/model/src/site/site.xml
new file mode 100644 (file)
index 0000000..d219e60
--- /dev/null
@@ -0,0 +1,25 @@
+<?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 name="${project.name}">
+
+    <skin>
+        <groupId>org.apache.maven.skins</groupId>
+        <artifactId>maven-fluido-skin</artifactId>
+        <version>1.3.0</version>
+    </skin>
+
+    <body>
+        <menu ref="parent"/>
+        <menu ref="modules"/>
+        <menu ref="reports"/>
+    </body>
+
+</project>
+
diff --git a/model/yang-ext/pom.xml b/model/yang-ext/pom.xml
new file mode 100644 (file)
index 0000000..3cbe176
--- /dev/null
@@ -0,0 +1,43 @@
+<?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>
+        <artifactId>model-parent</artifactId>
+        <groupId>org.opendaylight.yangtools.model</groupId>
+        <version>0.8.0-SNAPSHOT</version>
+    </parent>
+
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>yang-ext</artifactId>
+    <version>2013.09.07.8-SNAPSHOT</version>
+    <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/model/yang-ext/src/main/yang/yang-ext.yang b/model/yang-ext/src/main/yang/yang-ext.yang
new file mode 100644 (file)
index 0000000..0fbe94d
--- /dev/null
@@ -0,0 +1,79 @@
+module yang-ext {
+    yang-version 1;
+    namespace "urn:opendaylight:yang:extension:yang-ext";
+    prefix "ext";
+    
+    contact "Anton Tkacik <ttkacik@cisco.com>";
+
+    description 
+            "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";
+
+    revision "2013-07-09" {
+        description "";
+    }
+
+    // Augmentation name
+
+    extension "augment-identifier" {
+        description 
+           "YANG language extension which assigns an identifier to 
+            augmentation. Augment identifier is used to identify
+            specific augment statement by name. 
+
+            The identifier syntax is defined formally defined by the rule
+            'identifier' in Section 12 of RFC 6020.
+
+            All augment identifiers defined in a namespace MUST be unique.
+            The namespace of augment identifiers is shared by module and
+            its submodules.";
+
+            /*
+                Discussion:
+                This extension allows for ease of development / debug
+                of YANG modules and it is suitable for code generation,
+                where each augment statement is nicely identified by
+                unique name instead of combination of augment target
+                and when condition. 
+            */
+        argument "identifier";
+    }
+
+
+    // Context-aware RPCs
+
+    grouping rpc-context-ref {
+        description 
+           "A reference to RPC context.";
+        leaf context-instance {
+            type instance-identifier;
+            description "Pointer to the context. ";
+        }
+    }
+
+    extension "rpc-context-instance" {
+        description
+           "YANG language extension which defines enclosing (parent) 
+            schema node as referencable context for RPCs.
+
+            The argument is identity which is used to identify RPC context
+            type.";
+
+        argument "context-type";
+    }
+
+    extension "context-reference" {
+        argument "context-type";
+    }
+
+    extension "context-instance" {
+        argument "context-type";
+    }
+    
+    extension "instance-target" {
+       argument "path";
+    }
+}
diff --git a/yang/yang-binding/pom.xml b/yang/yang-binding/pom.xml
new file mode 100644 (file)
index 0000000..0d03ad7
--- /dev/null
@@ -0,0 +1,52 @@
+<?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>yangtools-parent</artifactId>
+        <version>0.8.0-SNAPSHOT</version>
+        <relativePath>/../../common/parent/pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>yang-binding</artifactId>
+    <name>${project.artifactId}</name>
+    <description>Java binding for YANG</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>concepts</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</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>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentable.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentable.java
new file mode 100644 (file)
index 0000000..832cdcd
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.binding;
+
+/**
+ * Augmentable (extensible) object which could carry additional data defined by
+ * third-party extension, without introducing conflict between various
+ * extension.
+ * 
+ * This interface uses extended version of ExtensibleInterface pattern which
+ * also adds marker interface for augmentations (extensions) -
+ * {@link Augmentable}
+ * 
+ * @author Tony Tkacik
+ * @param <T>
+ *            Base class which should implements this interface and is target
+ *            for augmentation.
+ */
+public interface Augmentable<T> {
+
+    /**
+     * Returns instance of augmentation.
+     * 
+     * @param augmentationType
+     *            Type of augmentation to be returned.
+     * @return instance of augmentation.
+     */
+    <E extends Augmentation<T>> E getAugmentation(Class<E> augmentationType);
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentation.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Augmentation.java
new file mode 100644 (file)
index 0000000..cb6f1a1
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.binding;
+
+/**
+ * Augmentation (extension) of other interface.
+ * 
+ * This interface uniquely bounds Augmentation to generated 
+ * interface.
+ * 
+ * All interfaces generated from YANG Augmentation statement
+ * must implement this interface with parameter <code>P</code>
+ * which uniquely points to it's target class.
+ * 
+ * 
+ *
+ * @param <T> Class to which this implementation is extension.
+ */
+public interface Augmentation<T> {
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AugmentationHolder.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/AugmentationHolder.java
new file mode 100644 (file)
index 0000000..472c3c2
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 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.binding;
+
+import java.util.Map;
+
+/**
+ *
+ * Augmentable (extensible) object which could carry additional data defined by
+ * third-party extension, without introducing conflict between various
+ * extension.
+ *
+ *
+ * @author Tony Tkacik
+ * @param <T>
+ *            Base class which should is target
+ *            for augmentations.
+ */
+public interface AugmentationHolder<T> {
+
+    /**
+     * Returns map of all augmentations.
+     *
+     * @return map of all augmentations.
+     */
+    Map<Class<? extends Augmentation<T>>,Augmentation<T>> augmentations();
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BaseIdentity.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BaseIdentity.java
new file mode 100644 (file)
index 0000000..9f55b64
--- /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.binding;
+
+/**
+ * Base Identity
+ * 
+ */
+public abstract class BaseIdentity {
+
+    public final static BaseIdentity INSTANCE = new BaseIdentity() {
+    };
+
+    protected BaseIdentity() {
+
+    }
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingCodec.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingCodec.java
new file mode 100644 (file)
index 0000000..a812126
--- /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.binding;
+
+import org.opendaylight.yangtools.concepts.Codec;
+
+public interface BindingCodec<P, I> extends BindingSerializer<P, I>, BindingDeserializer<I, P>, Codec<P, I> {
+
+    @Override
+    P serialize(I input);
+
+    @Override
+    I deserialize(P input);
+
+    I deserialize(P input, InstanceIdentifier<?> bindingIdentifier);
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingDeserializer.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingDeserializer.java
new file mode 100644 (file)
index 0000000..dea3d99
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * 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.binding;
+
+public interface BindingDeserializer<P,I> {
+
+    P deserialize(I input);
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingMapping.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingMapping.java
new file mode 100644 (file)
index 0000000..b13ab14
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * 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.binding;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableSet;
+import java.text.SimpleDateFormat;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+
+public final class BindingMapping {
+
+    public static final String VERSION = "0.6";
+
+    public static final Set<String> JAVA_RESERVED_WORDS = ImmutableSet.of("abstract", "assert", "boolean", "break",
+            "byte", "case", "catch", "char", "class", "const", "continue", "default", "double", "do", "else", "enum",
+            "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "instanceof",
+            "int", "interface", "long", "native", "new", "null", "package", "private", "protected", "public", "return",
+            "short", "static", "strictfp", "super", "switch", "synchronized", "this", "throw", "throws", "transient",
+            "true", "try", "void", "volatile", "while");
+
+    public static final String DATA_ROOT_SUFFIX = "Data";
+    public static final String RPC_SERVICE_SUFFIX = "Service";
+    public static final String NOTIFICATION_LISTENER_SUFFIX = "Listener";
+    public static final String QNAME_STATIC_FIELD_NAME = "QNAME";
+    public static final String PACKAGE_PREFIX = "org.opendaylight.yang.gen.v1";
+    public static final String AUGMENTATION_FIELD = "augmentation";
+
+    private static final Splitter CAMEL_SPLITTER = Splitter.on(CharMatcher.anyOf(" _.-").precomputed())
+            .omitEmptyStrings().trimResults();
+    private static final Pattern COLON_SLASH_SLASH = Pattern.compile("://", Pattern.LITERAL);
+    private static final String QUOTED_DOT = Matcher.quoteReplacement(".");
+    private static final Splitter DOT_SPLITTER = Splitter.on('.');
+
+    public static final String MODULE_INFO_CLASS_NAME = "$YangModuleInfoImpl";
+    public static final String MODEL_BINDING_PROVIDER_CLASS_NAME = "$YangModelBindingProvider";
+
+    public static final String RPC_INPUT_SUFFIX = "Input";
+    public static final String RPC_OUTPUT_SUFFIX = "Output";
+
+    private static final ThreadLocal<SimpleDateFormat> PACKAGE_DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
+
+        @Override
+        protected SimpleDateFormat initialValue() {
+            return new SimpleDateFormat("yyMMdd");
+        }
+
+        @Override
+        public void set(final SimpleDateFormat value) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
+    private BindingMapping() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
+    public static String getRootPackageName(final QName module) {
+        return getRootPackageName(module.getModule());
+    }
+
+    public static String getRootPackageName(final QNameModule module) {
+        checkArgument(module != null, "Module must not be null");
+        checkArgument(module.getRevision() != null, "Revision must not be null");
+        checkArgument(module.getNamespace() != null, "Namespace must not be null");
+        final StringBuilder packageNameBuilder = new StringBuilder();
+
+        packageNameBuilder.append(BindingMapping.PACKAGE_PREFIX);
+        packageNameBuilder.append('.');
+
+        String namespace = module.getNamespace().toString();
+        namespace = COLON_SLASH_SLASH.matcher(namespace).replaceAll(QUOTED_DOT);
+
+        final char[] chars = namespace.toCharArray();
+        for (int i = 0; i < chars.length; ++i) {
+            switch (chars[i]) {
+            case '/':
+            case ':':
+            case '-':
+            case '@':
+            case '$':
+            case '#':
+            case '\'':
+            case '*':
+            case '+':
+            case ',':
+            case ';':
+            case '=':
+                chars[i] = '.';
+            }
+        }
+
+        packageNameBuilder.append(chars);
+        packageNameBuilder.append(".rev");
+        packageNameBuilder.append(PACKAGE_DATE_FORMAT.get().format(module.getRevision()));
+        return normalizePackageName(packageNameBuilder.toString());
+
+    }
+
+    public static String normalizePackageName(final String packageName) {
+        if (packageName == null) {
+            return null;
+        }
+
+        final StringBuilder builder = new StringBuilder();
+        boolean first = true;
+
+        for (String p : DOT_SPLITTER.split(packageName.toLowerCase())) {
+            if (first) {
+                first = false;
+            } else {
+                builder.append('.');
+            }
+
+            if (Character.isDigit(p.charAt(0)) || BindingMapping.JAVA_RESERVED_WORDS.contains(p)) {
+                builder.append('_');
+            }
+            builder.append(p);
+        }
+
+        return builder.toString();
+    }
+
+    public static String getMethodName(final QName name) {
+        checkArgument(name != null, "Name should not be null.");
+        return getMethodName(name.getLocalName());
+    }
+
+    public static String getClassName(final String localName) {
+        checkArgument(localName != null, "Name should not be null.");
+        return toFirstUpper(toCamelCase(localName));
+    }
+
+    public static String getMethodName(final String yangIdentifier) {
+        checkArgument(yangIdentifier != null,"Identifier should not be null");
+        return toFirstLower(toCamelCase(yangIdentifier));
+    }
+
+    public static String getClassName(final QName name) {
+        checkArgument(name != null, "Name should not be null.");
+        return toFirstUpper(toCamelCase(name.getLocalName()));
+    }
+
+    public static String getPropertyName(final String yangIdentifier) {
+        final String potential = toFirstLower(toCamelCase(yangIdentifier));
+        if ("class".equals(potential)) {
+            return "xmlClass";
+        }
+        return potential;
+    }
+
+    private static String toCamelCase(final String rawString) {
+        checkArgument(rawString != null, "String should not be null");
+        Iterable<String> components = CAMEL_SPLITTER.split(rawString);
+        StringBuilder builder = new StringBuilder();
+        for (String comp : components) {
+            builder.append(toFirstUpper(comp));
+        }
+        return checkNumericPrefix(builder.toString());
+    }
+
+    private static String checkNumericPrefix(final String rawString) {
+        if (rawString == null || rawString.isEmpty()) {
+            return rawString;
+        }
+        char firstChar = rawString.charAt(0);
+        if (firstChar >= '0' && firstChar <= '9') {
+            return "_" + rawString;
+        } else {
+            return rawString;
+        }
+    }
+
+    /**
+     * Returns the {@link String} {@code s} with an
+     * {@link Character#isUpperCase(char) upper case} first character. This
+     * function is null-safe.
+     *
+     * @param s
+     *            the string that should get an upper case first character. May
+     *            be <code>null</code>.
+     * @return the {@link String} {@code s} with an upper case first character
+     *         or <code>null</code> if the input {@link String} {@code s} was
+     *         <code>null</code>.
+     */
+    public static String toFirstUpper(final String s) {
+        if (s == null || s.length() == 0) {
+            return s;
+        }
+        if (Character.isUpperCase(s.charAt(0))) {
+            return s;
+        }
+        if (s.length() == 1) {
+            return s.toUpperCase();
+        }
+        return s.substring(0, 1).toUpperCase() + s.substring(1);
+    }
+
+    /**
+     * Returns the {@link String} {@code s} with an
+     * {@link Character#isLowerCase(char) lower case} first character. This
+     * function is null-safe.
+     *
+     * @param s
+     *            the string that should get an lower case first character. May
+     *            be <code>null</code>.
+     * @return the {@link String} {@code s} with an lower case first character
+     *         or <code>null</code> if the input {@link String} {@code s} was
+     *         <code>null</code>.
+     */
+    private static String toFirstLower(final String s) {
+        if (s == null || s.length() == 0) {
+            return s;
+        }
+        if (Character.isLowerCase(s.charAt(0))) {
+            return s;
+        }
+        if (s.length() == 1) {
+            return s.toLowerCase();
+        }
+        return s.substring(0, 1).toLowerCase() + s.substring(1);
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingSerializer.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingSerializer.java
new file mode 100644 (file)
index 0000000..fb85eae
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.binding;
+
+public interface BindingSerializer<P,I> {
+    P serialize(I input);
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingStreamEventWriter.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/BindingStreamEventWriter.java
new file mode 100644 (file)
index 0000000..4aeb309
--- /dev/null
@@ -0,0 +1,445 @@
+/*
+ * 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.binding;
+
+import java.io.Closeable;
+import java.io.Flushable;
+import java.io.IOException;
+
+
+/**
+ * Event Stream Writer for Binding Representation
+ *
+ *
+ * <h3>Emmiting Event Stream</h3>
+ *
+ * <ul>
+ * <li><code>container</code> - Container node representation, start event is
+ * emitted using {@link #startContainerNode(Class, int)} and node end event is
+ * emitted using {@link #endNode()}. Container node is implementing
+ * {@link DataObject} interface.
+ *
+ * <li><code>list</code> - YANG list statement has two representation in event
+ * stream - unkeyed list and map. Unkeyed list is YANG list which did not
+ * specify key.
+ *
+ * <ul>
+ * <li><code>Map</code> - Map start event is emitted using
+ * {@link #startMapNode(Class, int)} and is ended using {@link #endNode()}. Each map
+ * entry start is emitted using {@link #startMapEntryNode(Identifier, int)} with Map of keys
+ * and finished using {@link #endNode()}.</li>
+ *
+ * <li><code>UnkeyedList</code> - Unkeyed list represent list without keys,
+ * unkeyed list start is emitted using {@link #startUnkeyedList(Class, int)} list
+ * end is emitted using {@link #endNode()}. Each list item is emitted using
+ * {@link #startUnkeyedListItem(int)} and ended using {@link #endNode()}.</li>
+ * </ul></li>
+ *
+ * <li><code>leaf</code> - Leaf node event is emitted using
+ * {@link #leafNode(String, Object)}. {@link #endNode()} MUST be not emitted for
+ * leaf node.</li>
+ *
+ * <li><code>leaf-list</code> - Leaf list start is emitted using
+ * {@link #startLeafSet(String, int)}. Leaf list end is emitted using
+ * {@link #endNode()}. Leaf list entries are emitted using
+ * {@link #leafSetEntryNode(Object)}.
+ *
+ * <li><code>anyxml - Anyxml node event is emitted using
+ * {@link #leafNode(String, Object)}. {@link #endNode()} MUST be not emitted
+ * for anyxml node.</code></li>
+ *
+ *
+ * <li><code>choice</code> Choice node event is emitted by
+ * {@link #startChoiceNode(Class, int)} event and must be immediately followed by
+ * {@link #startCase(Class, int)} event. Choice node is finished by emitting an
+ * {@link #endNode()} event.</li>
+ *
+ * <li>
+ * <code>case</code> - Case node may be emitted only inside choice node by
+ * invoking {@link #startCase(Class, int)}. Case node is finished be emitting an
+ * {@link #endNode()} event.</li>
+ *
+ * <li>
+ * <code>augment</code> - Represents augmentation, augmentation node is started
+ * by invoking {@link #startAugmentationNode(Class)} and
+ * finished by invoking {@link #endNode()}.</li>
+ *
+ * </ul>
+ *
+ * <h3>Implementation notes</h3> This interface is not intended to be
+ * implemented by users of generated Binding DTOs but to be used by utilities,
+ * which needs to emit NormalizedNode model from Binding DTOs.
+ * <p>
+ * This interface is intended as API definition of facade for real Event /
+ * Stream Writer, without explicitly requiring stream writer and related
+ * interfaces to be imported by all generated Binding DTOs.
+ * <p>
+ * Existence of this interface in base Java Binding package is required to
+ * support runtime generation of users of this interface in OSGI and OSGI-like
+ * environment, since this package is only package which is imported by all
+ * generated Binding DTOs and wired in OSGI.
+ *
+ *
+ */
+public interface BindingStreamEventWriter extends Closeable, Flushable {
+
+    /**
+     * Methods in this interface allow users to hint the underlying
+     * implementation about the sizing of container-like constructors
+     * (leafLists, containers, etc.). These hints may be taken into account by a
+     * particular implementation to improve performance, but clients are not
+     * required to provide hints. This constant should be used by clients who
+     * either do not have the sizing information, or do not wish to divulge it
+     * (for whatever reasons). Implementations are free to ignore these hints
+     * completely, but if they do use them, they are expected to be resilient in
+     * face of missing and mismatched hints, which is to say the user can
+     * specify startLeafSet(..., 1) and then call leafNode() 15 times.
+     * <p>
+     * The acceptable hint values are non-negative integers and this constant,
+     * all other values will result, based on implementation preference, in the
+     * hint being completely ignored or IllegalArgumentException being thrown.
+     */
+    int UNKNOWN_SIZE = -1;
+
+    /**
+     *
+     * Emits a leaf node event with supplied value.
+     *
+     * @param localName
+     *            name of node as defined in schema, namespace and revision are
+     *            derived from parent node.
+     * @param value
+     *            Value of leaf node.
+     * @throws IllegalArgumentException
+     *             If emitted leaf node has invalid value in current context or
+     *             was emitted multiple times.
+     * @throws IllegalStateException
+     *             If node was emitted inside <code>map</code>,
+     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void leafNode(String localName, Object value) throws IOException, IllegalArgumentException;
+
+    /**
+     *
+     * Emits a start of leaf set (leaf-list).
+     * <p>
+     * Emits start of leaf set, during writing leaf set event, only
+     * {@link #leafSetEntryNode(Object)} calls are valid. Leaf set event is
+     * finished by calling {@link #endNode()}.
+     *
+     * @param localName
+     *            name of node as defined in schema, namespace and revision are
+     *            derived from parent node.
+     * @param childSizeHint
+     *            Non-negative count of expected direct child nodes or
+     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
+     *            and should not fail writing of child events, if there are more
+     *            events than count.
+     * @throws IllegalArgumentException
+     *             If emitted leaf node is invalid in current context or was
+     *             emitted multiple times.
+     * @throws IllegalStateException
+     *             If node was emitted inside <code>map</code>,
+     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void startLeafSet(String localName, int childSizeHint) throws IOException, IllegalArgumentException;
+
+    /**
+     * Emits a leaf set entry node
+     *
+     * @param value
+     *            Value of leaf set entry node.
+     * @throws IllegalArgumentException
+     *             If emitted leaf node has invalid value.
+     * @throws IllegalStateException
+     *             If node was emitted outside <code>leaf set</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void leafSetEntryNode(Object value) throws IOException, IllegalArgumentException;
+
+    /**
+     *
+     * Emits start of new container.
+     *
+     * <p>
+     * End of container event is emitted by invoking {@link #endNode()}.
+     *
+     * <p>
+     * Valid sub-events are:
+     * <ul>
+     * <li>{@link #leafNode(String, Object)}</li>
+     * <li>{@link #startContainerNode(Class, int)}</li>
+     * <li>{@link #startChoiceNode(Class, int)}</li>
+     * <li>{@link #startLeafSet(String, int)}</li>
+     * <li>{@link #startMapNode(Class, int)}</li>
+     * <li>{@link #startUnkeyedList(Class, int)}</li>
+     * <li>{@link #startAugmentationNode(Class)}</li>
+     * </ul>
+     *
+     * @param container
+     *            name of node as defined in schema, namespace and revision are
+     *            derived from parent node.
+     * @param childSizeHint
+     *            Non-negative count of expected direct child nodes or
+     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
+     *            and should not fail writing of child events, if there are more
+     *            events than count.
+     * @throws IllegalArgumentException
+     *             If emitted node is invalid in current context or was emitted
+     *             multiple times.
+     * @throws IllegalStateException
+     *             If node was emitted inside <code>map</code>,
+     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void startContainerNode(Class<? extends DataObject> container, int childSizeHint) throws IOException, IllegalArgumentException;
+
+    /**
+     *
+     * Emits start of unkeyed list node event.
+     *
+     * <p>
+     * End of unkeyed list event is emitted by invoking {@link #endNode()}.
+     * Valid subevents is only {@link #startUnkeyedListItem(int)}. All other
+     * methods will throw {@link IllegalArgumentException}.
+     *
+     * @param localName
+     *            name of node as defined in schema, namespace and revision are
+     *            derived from parent node.
+     * @param childSizeHint
+     *            Non-negative count of expected direct child nodes or
+     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
+     *            and should not fail writing of child events, if there are more
+     *            events than count.
+     * @throws IllegalArgumentException
+     *             If emitted node is invalid in current context or was emitted
+     *             multiple times.
+     * @throws IllegalStateException
+     *             If node was emitted inside <code>map</code>,
+     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void startUnkeyedList(Class<? extends DataObject> localName, int childSizeHint) throws IOException, IllegalArgumentException;
+
+    /**
+     * Emits start of new unkeyed list item.
+     *
+     * <p>
+     * Unkeyed list item event is finished by invoking {@link #endNode()}. Valid
+     * sub-events are:
+     * <p>
+     * Valid sub-events are:
+     *
+     * <ul>
+     * <li>{@link #leafNode(String, Object)}</li>
+     * <li>{@link #startContainerNode(Class, int)}</li>
+     * <li>{@link #startChoiceNode(Class, int)}</li>
+     * <li>{@link #startLeafSet(String, int)}</li>
+     * <li>{@link #startMapNode(Class, int)}</li>
+     * <li>{@link #startUnkeyedList(Class, int)}</li>
+     * <li>{@link #startAugmentationNode(Class)}</li>
+     * </ul>
+     *
+     *
+     * @param childSizeHint
+     *            Non-negative count of expected direct child nodes or
+     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
+     *            and should not fail writing of child events, if there are more
+     *            events than count.
+     * @throws IllegalStateException
+     *             If node was emitted outside <code>unkeyed list</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void startUnkeyedListItem(int childSizeHint) throws IOException, IllegalStateException;
+
+    /**
+     *
+     * Emits start of unordered map node event.
+     *
+     * <p>
+     * End of map node event is emitted by invoking {@link #endNode()}. Valid
+     * subevents is only {@link #startMapEntryNode(Identifier, int)}. All other methods will
+     * throw {@link IllegalArgumentException}.
+     *
+     * @param mapEntryType
+     *            Class of list item, which has defined key.
+     * @param childSizeHint
+     *            Non-negative count of expected direct child nodes or
+     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
+     *            and should not fail writing of child events, if there are more
+     *            events than count.
+     * @throws IllegalArgumentException
+     * @throws IllegalStateException
+     *             If node was emitted inside <code>map</code>,
+     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    <T extends DataObject & Identifiable<?>> void startMapNode(Class<T> mapEntryType, int childSizeHint)
+            throws IOException, IllegalArgumentException;
+
+    /**
+     *
+     * Emits start of ordered map node event.
+     *
+     * <p>
+     * End of map node event is emitted by invoking {@link #endNode()}. Valid
+     * subevents is only {@link #startMapEntryNode(Identifier, int)}. All other methods will
+     * throw {@link IllegalArgumentException}.
+     *
+     * @param mapEntryType
+     *            Class of list item, which has defined key.
+     * @param childSizeHint
+     *            Non-negative count of expected direct child nodes or
+     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
+     *            and should not fail writing of child events, if there are more
+     *            events than count.
+     * @throws IllegalArgumentException
+     * @throws IllegalStateException
+     *             If node was emitted inside <code>map</code>,
+     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    <T extends DataObject & Identifiable<?>> void startOrderedMapNode(Class<T> mapEntryType, int childSizeHint)
+           throws IOException, IllegalArgumentException;
+
+    /**
+     *
+     * Emits start of map entry.
+     *
+     * <p>
+     * End of map entry event is emitted by invoking {@link #endNode()}.
+     *
+     * <p>
+     * Valid sub-events are:
+     * <ul>
+     * <li>{@link #leafNode(String, Object)}</li>
+     * <li>{@link #startContainerNode(Class, int)}</li>
+     * <li>{@link #startChoiceNode(Class, int)}</li>
+     * <li>{@link #startLeafSet(String, int)}</li>
+     * <li>{@link #startMapNode(Class, int)}</li>
+     * <li>{@link #startUnkeyedList(Class, int)}</li>
+     * <li>{@link #startAugmentationNode(Class)}</li>
+     * </ul>
+     *
+     * @param keyValues
+     *            Key of map entry node
+     * @param childSizeHint
+     *            Non-negative count of expected direct child nodes or
+     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
+     *            and should not fail writing of child events, if there are more
+     *            events than count.
+     * @throws IllegalArgumentException
+     *             If key contains incorrect value.
+     * @throws IllegalStateException
+     *             If node was emitted outside <code>map entry</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void startMapEntryNode(Identifier<?> keyValues, int childSizeHint) throws IOException, IllegalArgumentException;
+
+    /**
+     * Emits start of choice node.
+     *
+     * <p>
+     * Valid sub-event in {@link #startCase(Class, int)}, which selects case
+     * which should be written.
+     *
+     * @param choice
+     *            Choice class.
+     * @param childSizeHint
+     *            Non-negative count of expected direct child nodes or
+     *            {@link #UNKNOWN_SIZE} if count is unknown. This is only hint
+     *            and should not fail writing of child events, if there are more
+     *            events than count.
+     * @throws IllegalArgumentException
+     * @throws IllegalStateException
+     *             If node was emitted inside <code>map</code>, <code>choice</code>,
+     *             <code>unkeyed list</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void startChoiceNode(Class<? extends DataContainer> choice, int childSizeHint) throws IOException, IllegalArgumentException;
+
+    /**
+     *
+     * Starts a case node.
+     *
+     * <p>
+     * Valid sub-events are:
+     * <ul>
+     * <li>{@link #leafNode(String, Object)}</li>
+     * <li>{@link #startContainerNode(Class, int)}</li>
+     * <li>{@link #startChoiceNode(Class, int)}</li>
+     * <li>{@link #startLeafSet(String, int)}</li>
+     * <li>{@link #startMapNode(Class, int)}</li>
+     * <li>{@link #startUnkeyedList(Class, int)}</li>
+     * <li>{@link #startAugmentationNode(Class)}</li>
+     * </ul>
+     *
+     * @param caze Case class
+     * @throws IllegalArgumentException
+     * @throws IOException if an underlying IO error occurs
+     */
+    void startCase(Class<? extends DataObject> caze, int childSizeHint) throws IOException, IllegalArgumentException;
+
+    /**
+     * Emits start of augmentation node.
+     *
+     * <p>
+     * End of augmentation event is emitted by invoking {@link #endNode()}.
+     *
+     * <p>
+     * Valid sub-events are:
+     *
+     * <ul>
+     * <li>{@link #leafNode(String, Object)}</li>
+     * <li>{@link #startContainerNode(Class, int)}</li>
+     * <li>{@link #startChoiceNode(Class, int)}</li>
+     * <li>{@link #startLeafSet(String, int)}</li>
+     * <li>{@link #startMapNode(Class, int)}</li>
+     * <li>{@link #startUnkeyedList(Class, int)}</li>
+     * </ul>
+     *
+     * <p>
+     * Note this is only method, which does not require childSizeHint, since
+     * maximum value is always size of <code>possibleChildren</code>.
+     *
+     * @param augmentationType augmentation class
+     * @throws IllegalArgumentException
+     *             If augmentation is invalid in current context.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void startAugmentationNode(Class<? extends Augmentation<?>> augmentationType) throws IOException, IllegalArgumentException;
+
+    /**
+     * Emits anyxml node event.
+     *
+     * @param name
+     * @param value
+     * @throws IllegalArgumentException
+     * @throws IllegalStateException
+     *             If node was emitted inside <code>map</code>,
+     *             <code>choice</code> <code>unkeyed list</code> node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void anyxmlNode(String name, Object value) throws IOException, IllegalArgumentException;
+
+    /**
+     * Emits end event for node.
+     *
+     * @throws IllegalStateException If there is no open node.
+     * @throws IOException if an underlying IO error occurs
+     */
+    void endNode() throws IOException, IllegalStateException;
+
+    @Override
+    void flush() throws IOException;
+
+    @Override
+    void close() throws IOException;
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/ChildOf.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/ChildOf.java
new file mode 100644 (file)
index 0000000..28b4e0c
--- /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.binding;
+
+/**
+ * Child of parent container
+ * 
+ * Marker interface uniquelly bounding generated Java interfaces to their 
+ * parent container.
+ * 
+ * Any nested Java interface generated from YANG must implement this interface,
+ * where parameter <code>P</code> points to it's defining data node container
+ * (interface generated for List, Container, Case).
+ * 
+ * In case of children added by augmentation (which implements {@link Augmentation})
+ * interfaces representing nested container must implements {@link ChildOf} with
+ * same argument as Augmentation.
+ * 
+ * @param <P> Parent container
+ */
+public interface ChildOf<P> extends DataObject {
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataContainer.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataContainer.java
new file mode 100644 (file)
index 0000000..f4bc7a3
--- /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.binding;
+
+/**
+ * Data Container - object contains structured data
+ * 
+ * Marker interface which must be implmeneted by all interfaces
+ * generated for YANG:
+ * <ul>
+ * <li>Rpc Input
+ * <li>Output 
+ * <li>Notification
+ * <li>Container
+ * <li>List
+ * <li>Case
+ * </ul>
+ */
+public interface DataContainer {
+
+    Class<? extends DataContainer> getImplementedInterface();
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObject.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObject.java
new file mode 100644 (file)
index 0000000..6d36646
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.binding;
+
+/**
+ * Data container is an interface which has structured contents.
+ * 
+ * @author Tony Tkacik
+ *
+ */
+public interface DataObject extends DataContainer {
+
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectSerializer.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectSerializer.java
new file mode 100644 (file)
index 0000000..faa7056
--- /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.yang.binding;
+
+import java.io.IOException;
+
+/**
+ * A serializer which writes DataObject to supplied stream event writer.
+ */
+public interface DataObjectSerializer {
+    /**
+     * Writes stream events representing object to supplied stream
+     *
+     * @param obj
+     *            Source of stream events
+     * @param stream
+     *            Stream to which events should be written.
+     */
+    void serialize(DataObject obj, BindingStreamEventWriter stream) throws IOException;
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectSerializerImplementation.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectSerializerImplementation.java
new file mode 100644 (file)
index 0000000..4c9b3c8
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.binding;
+
+import java.io.IOException;
+
+/**
+ * SPI-level contract for implementations of {@link DataObjectSerializer}.
+ * The contract is kept between implementation of {@link DataObjectSerializerRegistry},
+ * which maintains the lookup context required for recursive serialization.
+ *
+ * FIXME: this interface needs to be moved into .spi, but due to classpath funkyness
+ *        of OSGi, that change has to be carefully orchestrated to ensure proper imports
+ *        exist in all generated packages. One avenue how to achieve that is to move
+ *        {@link YangModuleInfo} and modify code generator to add a static field
+ *        to all generated classes which will point to the per-model YangModuleInfo
+ *        (currently all users of it have to walk the package hierarchy, so that
+ *        is an improvement in and of itself).
+ *
+ */
+public interface DataObjectSerializerImplementation {
+    /**
+     *
+     * Writes stream events for supplied data object to provided stream.
+     *
+     * DataObjectSerializerRegistry may be used to lookup serializers
+     * for other generated classes  in order to support writing
+     * their events.
+     *
+     */
+    void serialize(DataObjectSerializerRegistry reg,DataObject obj, BindingStreamEventWriter stream) throws IOException;
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectSerializerRegistry.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataObjectSerializerRegistry.java
new file mode 100644 (file)
index 0000000..3c6a74b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.binding;
+
+/**
+ * SPI-level contract for registry of {@link DataObjectSerializer}.
+ * The contract is kept between implementation of {@link DataObjectSerializerImplementation},
+ * Registry provides lookup for serializers to support recursive
+ * serialization of nested {@link DataObject}s.
+ *
+ * FIXME: this interface needs to be moved into .spi, but due to classpath funkyness
+ *        of OSGi, that change has to be carefully orchestrated to ensure proper imports
+ *        exist in all generated pacakges. One avenue how to achieve that is to move
+ *        {@link YangModuleInfo} and modify code generator to add a static field
+ *        to all generated classes which will point to the per-model YangModuleInfo
+ *        (currently all users of it have to walk the package hierarchy, so that
+ *        is an improvement in and of itself).
+ *
+ */
+public interface DataObjectSerializerRegistry {
+
+    DataObjectSerializer getSerializer(Class<? extends DataObject> binding);
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataRoot.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/DataRoot.java
new file mode 100644 (file)
index 0000000..66fdfde
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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.binding;
+
+/**
+ * Data Root of YANG module
+ * 
+ */
+public interface DataRoot {
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Identifiable.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Identifiable.java
new file mode 100644 (file)
index 0000000..6f45c8c
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * 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.binding;
+
+
+/**
+ * Identifiable object, which could be identified by it's key
+ * 
+ * @author ttkacik
+ *
+ * @param <T> Identifier class for this object
+ */
+public interface Identifiable<T extends Identifier<? extends Identifiable<T>>> {
+    
+    /**
+     * Returns an unique key for the object
+     * 
+     * @return Key for the object
+     */
+    T getKey();
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Identifier.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Identifier.java
new file mode 100644 (file)
index 0000000..a99b451
--- /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.binding;
+
+/**
+ * 
+ * Object is unique identifier for another object
+ * 
+ * 
+ * 
+ * @param <T>
+ *            Class of object for which this object is identifier
+ * @author ttkacik
+ */
+public interface Identifier<T extends Identifiable<?>> extends org.opendaylight.yangtools.concepts.Identifier {
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java
new file mode 100644 (file)
index 0000000..f99f3a4
--- /dev/null
@@ -0,0 +1,702 @@
+/*
+ * 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.binding;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.MoreObjects.ToStringHelper;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import org.opendaylight.yangtools.concepts.Builder;
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.concepts.Path;
+import org.opendaylight.yangtools.util.HashCodeBuilder;
+
+/**
+ *
+ * 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 class InstanceIdentifier<T extends DataObject> implements Path<InstanceIdentifier<? extends DataObject>>, Immutable, Serializable {
+    private static final Field PATHARGUMENTS_FIELD;
+    private static final long serialVersionUID = 2L;
+    /*
+     * Protected to differentiate internal and external access. Internal
+     * access is required never to modify the contents. References passed
+     * to outside entities have to be wrapped in an unmodifiable view.
+     */
+    protected transient final Iterable<PathArgument> pathArguments;
+    private final Class<T> targetType;
+    private final boolean wildcarded;
+    private final int hash;
+
+    static {
+        final Field f;
+        try {
+            f = InstanceIdentifier.class.getDeclaredField("pathArguments");
+        } catch (NoSuchFieldException | SecurityException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+        f.setAccessible(true);
+        PATHARGUMENTS_FIELD = f;
+    }
+
+    InstanceIdentifier(final Class<T> type, final Iterable<PathArgument> pathArguments, final boolean wildcarded, final int hash) {
+        this.pathArguments = Preconditions.checkNotNull(pathArguments);
+        this.targetType = Preconditions.checkNotNull(type);
+        this.wildcarded = wildcarded;
+        this.hash = hash;
+    }
+
+    /**
+     * Return the type of data which this InstanceIdentifier identifies.
+     *
+     * @return Target type
+     */
+    public final Class<T> getTargetType() {
+        return targetType;
+    }
+
+    /**
+     * Return the path argument chain which makes up this instance identifier.
+     *
+     * @return Path argument chain. Immutable and does not contain nulls.
+     */
+    public final Iterable<PathArgument> getPathArguments() {
+        return Iterables.unmodifiableIterable(pathArguments);
+    }
+
+    /**
+     * Check whether an instance identifier contains any wildcards. A wildcard
+     * is an path argument which has a null key.
+     *
+     * @return true if any of the path arguments has a null key.
+     */
+    public final boolean isWildcarded() {
+        return wildcarded;
+    }
+
+    @Override
+    public final int hashCode() {
+        return hash;
+    }
+
+    @Override
+    public final boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        final InstanceIdentifier<?> other = (InstanceIdentifier<?>) obj;
+        if (pathArguments == other.pathArguments) {
+            return true;
+        }
+
+        /*
+         * We could now just go and compare the pathArguments, but that
+         * can be potentially expensive. Let's try to avoid that by
+         * checking various things that we have cached from pathArguments
+         * and trying to prove the identifiers are *not* equal.
+         */
+        if (hash != other.hash) {
+            return false;
+        }
+        if (wildcarded != other.wildcarded) {
+            return false;
+        }
+        if (targetType != other.targetType) {
+            return false;
+        }
+        if (fastNonEqual(other)) {
+            return false;
+        }
+
+        // Everything checks out so far, so we have to do a full equals
+        return Iterables.elementsEqual(pathArguments, other.pathArguments);
+    }
+
+    /**
+     * Perform class-specific fast checks for non-equality. This allows
+     * subclasses to avoid iterating over the pathArguments by performing
+     * quick checks on their specific fields.
+     *
+     * @param other The other identifier, guaranteed to be the same class
+     * @return true if the other identifier cannot be equal to this one.
+     */
+    protected boolean fastNonEqual(final InstanceIdentifier<?> other) {
+        return false;
+    }
+
+    @Override
+    public final String toString() {
+        return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
+    }
+
+    /**
+     * Add class-specific toString attributes.
+     *
+     * @param toStringHelper ToStringHelper instance
+     * @return ToStringHelper instance which was passed in
+     */
+    protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+        return toStringHelper.add("targetType", targetType).add("path", Iterables.toString(pathArguments));
+    }
+
+    /**
+     * 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.
+     */
+    public final <I extends DataObject> InstanceIdentifier<I> firstIdentifierOf(final Class<I> type) {
+        int i = 1;
+        for (final PathArgument a : pathArguments) {
+            if (type.equals(a.getType())) {
+                @SuppressWarnings("unchecked")
+                final InstanceIdentifier<I> ret = (InstanceIdentifier<I>) internalCreate(Iterables.limit(pathArguments, i));
+                return ret;
+            }
+
+            ++i;
+        }
+
+        return null;
+    }
+
+    /**
+     * Return the key associated with the first component of specified type in
+     * an identifier.
+     *
+     * @param listItem component type
+     * @param listKey component key type
+     * @return key associated with the component, or null if the component type
+     *         is not present.
+     */
+    public final <N extends Identifiable<K> & DataObject, K extends Identifier<N>> K firstKeyOf(final Class<N> listItem, final Class<K> listKey) {
+        for (final PathArgument i : pathArguments) {
+            if (listItem.equals(i.getType())) {
+                @SuppressWarnings("unchecked")
+                final K ret = ((IdentifiableItem<N, K>)i).getKey();
+                return ret;
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Check whether an identifier is contained in this identifier. This is a strict subtree check, which requires all
+     * PathArguments to match exactly, e.g.
+     *
+     *
+     * 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 themselves.
+     *
+     * 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 false.
+     *
+     * @param other
+     * @return
+     */
+    @Override
+    public final boolean contains(final InstanceIdentifier<? extends DataObject> other) {
+        Preconditions.checkNotNull(other, "other should not be null");
+
+        final Iterator<?> lit = pathArguments.iterator();
+        final Iterator<?> oit = other.pathArguments.iterator();
+
+        while (lit.hasNext()) {
+            if (!oit.hasNext()) {
+                return false;
+            }
+
+            if (!lit.next().equals(oit.next())) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Check whether this instance identifier contains the other identifier after wildcard expansion. This is similar
+     * to {@link #contains(InstanceIdentifier)}, with the exception that a wildcards are assumed to match the their
+     * non-wildcarded PathArgument counterpart.
+     *
+     * @param other Identifier which should be checked for inclusion.
+     * @return true if this identifier contains the other object
+     */
+    public final boolean containsWildcarded(final InstanceIdentifier<?> other) {
+        Preconditions.checkNotNull(other, "other should not be null");
+
+        final Iterator<PathArgument> lit = pathArguments.iterator();
+        final Iterator<PathArgument> oit = other.pathArguments.iterator();
+
+        while (lit.hasNext()) {
+            if (!oit.hasNext()) {
+                return false;
+            }
+
+            final PathArgument la = lit.next();
+            final PathArgument oa = oit.next();
+
+            if (!la.getType().equals(oa.getType())) {
+                return false;
+            }
+            if (la instanceof IdentifiableItem<?, ?> && oa instanceof IdentifiableItem<?, ?> && !la.equals(oa)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * Create a builder rooted at this key.
+     *
+     * @return A builder instance
+     */
+    public InstanceIdentifierBuilder<T> builder() {
+        return new InstanceIdentifierBuilderImpl<T>(new Item<T>(targetType), pathArguments, hash, isWildcarded());
+    }
+
+    private InstanceIdentifier<?> childIdentifier(final PathArgument arg) {
+        return trustedCreate(arg, Iterables.concat(pathArguments, Collections.singleton(arg)), HashCodeBuilder.nextHashCode(hash, arg), isWildcarded());
+    }
+
+    @SuppressWarnings("unchecked")
+    public final <N extends ChildOf<? super T>> InstanceIdentifier<N> child(final Class<N> container) {
+        final PathArgument arg = new Item<>(container);
+        return (InstanceIdentifier<N>) childIdentifier(arg);
+    }
+
+    @SuppressWarnings("unchecked")
+    public final <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> KeyedInstanceIdentifier<N, K> child(
+            final Class<N> listItem, final K listKey) {
+        final PathArgument arg = new IdentifiableItem<>(listItem, listKey);
+        return (KeyedInstanceIdentifier<N, K>) childIdentifier(arg);
+    }
+
+    @SuppressWarnings("unchecked")
+    public final <N extends DataObject & Augmentation<? super T>> InstanceIdentifier<N> augmentation(
+            final Class<N> container) {
+        final PathArgument arg = new Item<>(container);
+        return (InstanceIdentifier<N>) childIdentifier(arg);
+    }
+
+    @Deprecated
+    private List<PathArgument> legacyCache;
+
+    /**
+     * @deprecated Use {@link #getPathArguments()} instead.
+     */
+    @Deprecated
+    public final List<PathArgument> getPath() {
+        if (legacyCache == null) {
+            legacyCache = ImmutableList.<PathArgument>copyOf(pathArguments);
+        }
+
+        return legacyCache;
+    }
+
+    /**
+     * Create a new InstanceIdentifierBuilder given a base InstanceIdentifier
+     *
+     * @param base
+     * @param <T>
+     * @return
+     *
+     * @deprecated Use {@link #builder()} instead.
+     */
+    @Deprecated
+    public static <T extends DataObject> InstanceIdentifierBuilder<T> builder(final InstanceIdentifier<T> base) {
+        return base.builder();
+    }
+
+    /**
+     * 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(final Class<T> container) {
+        return new InstanceIdentifierBuilderImpl<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(
+            final Class<N> listItem, final K listKey) {
+        return new InstanceIdentifierBuilderImpl<N>().addNode(listItem, listKey);
+    }
+
+    /**
+     * Create an instance identifier for a very specific object type. This method
+     * implements {@link #create(Iterable)} semantics, except it is used by internal
+     * callers, which have assured that the argument is an immutable Iterable.
+     *
+     *
+     * @param pathArguments The path to a specific node in the data tree
+     * @return InstanceIdentifier instance
+     * @throws IllegalArgumentException if pathArguments is empty or
+     *         contains a null element.
+     */
+    private static InstanceIdentifier<?> internalCreate(final Iterable<PathArgument> pathArguments) {
+        final Iterator<? extends PathArgument> it = Preconditions.checkNotNull(pathArguments, "pathArguments may not be null").iterator();
+        final HashCodeBuilder<PathArgument> hashBuilder = new HashCodeBuilder<>();
+        boolean wildcard = false;
+        PathArgument a = null;
+
+        while (it.hasNext()) {
+            a = it.next();
+            Preconditions.checkArgument(a != null, "pathArguments may not contain null elements");
+
+            // TODO: sanity check ChildOf<>;
+            hashBuilder.addArgument(a);
+
+            if (Identifiable.class.isAssignableFrom(a.getType()) && !(a instanceof IdentifiableItem<?, ?>)) {
+                wildcard = true;
+            }
+        }
+        Preconditions.checkArgument(a != null, "pathArguments may not be empty");
+
+        return trustedCreate(a, pathArguments, hashBuilder.build(), wildcard);
+    }
+
+    /**
+     * Create an instance identifier for a very specific object type.
+     *
+     * Example
+     * <pre>
+     *  List&lt;PathArgument&gt; path = Arrays.asList(new Item(Nodes.class))
+     *  new InstanceIdentifier(path);
+     * </pre>
+     *
+     * @param pathArguments The path to a specific node in the data tree
+     * @return InstanceIdentifier instance
+     * @throws IllegalArgumentException if pathArguments is empty or
+     *         contains a null element.
+     */
+    public static InstanceIdentifier<?> create(final Iterable<? extends PathArgument> pathArguments) {
+        if (pathArguments instanceof ImmutableCollection<?>) {
+            @SuppressWarnings("unchecked")
+            final Iterable<PathArgument> immutableArguments = (Iterable<PathArgument>) pathArguments;
+            return internalCreate(immutableArguments);
+        } else {
+            return internalCreate(ImmutableList.copyOf(pathArguments));
+        }
+    }
+
+    /**
+     * 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
+     * @return InstanceIdentifier instance
+     */
+    @SuppressWarnings("unchecked")
+    public static <T extends DataObject> InstanceIdentifier<T> create(final Class<T> type) {
+        return (InstanceIdentifier<T>) create(Collections.<PathArgument> singletonList(new Item<>(type)));
+    }
+
+    /**
+     * Return the key associated with the last component of the specified identifier.
+     *
+     * @param id instance identifier
+     * @return key associated with the last component
+     * @throws IllegalArgumentException if the supplied identifier type cannot have a key.
+     * @throws NullPointerException if id is null.
+     */
+    public static <N extends Identifiable<K> & DataObject, K extends Identifier<N>> K keyOf(final InstanceIdentifier<N> id) {
+        Preconditions.checkNotNull(id);
+        Preconditions.checkArgument(id instanceof KeyedInstanceIdentifier, "%s does not have a key", id);
+
+        @SuppressWarnings("unchecked")
+        final K ret = ((KeyedInstanceIdentifier<N, K>)id).getKey();
+        return ret;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    static InstanceIdentifier<?> trustedCreate(final PathArgument arg, final Iterable<PathArgument> pathArguments, final int hash, boolean wildcarded) {
+        if (Identifiable.class.isAssignableFrom(arg.getType()) && !(wildcarded)) {
+            Identifier<?> key = null;
+            if (arg instanceof IdentifiableItem<?, ?>) {
+                key = ((IdentifiableItem<?, ?>)arg).key;
+            } else {
+                wildcarded = true;
+            }
+
+            return new KeyedInstanceIdentifier(arg.getType(), pathArguments, wildcarded, hash, key);
+        } else {
+            return new InstanceIdentifier(arg.getType(), pathArguments, wildcarded, hash);
+        }
+    }
+
+    /**
+     * Path argument of {@link InstanceIdentifier}.
+     * <p>
+     * Interface which implementations are used as path components of the
+     * path in overall data tree.
+     */
+    public interface PathArgument extends Comparable<PathArgument> {
+        Class<? extends DataObject> getType();
+    }
+
+    private static abstract class AbstractPathArgument<T extends DataObject> implements PathArgument, Serializable {
+        private static final long serialVersionUID = 1L;
+        private final Class<T> type;
+
+        protected AbstractPathArgument(final Class<T> type) {
+            this.type = Preconditions.checkNotNull(type, "Type may not be null.");
+        }
+
+        @Override
+        public final Class<T> getType() {
+            return type;
+        }
+
+        @Override
+        public int hashCode() {
+            return type.hashCode();
+        }
+
+        @Override
+        public boolean equals(final Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            final AbstractPathArgument<?> other = (AbstractPathArgument<?>) obj;
+            return type.equals(other.type);
+        }
+
+        @Override
+        public int compareTo(final PathArgument arg) {
+            return type.getCanonicalName().compareTo(arg.getType().getCanonicalName());
+        }
+    }
+
+    /**
+     * 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> extends AbstractPathArgument<T> {
+        private static final long serialVersionUID = 1L;
+
+        public Item(final Class<T> type) {
+            super(type);
+        }
+
+        @Override
+        public String toString() {
+            return getType().getName();
+        }
+    }
+
+    /**
+     * 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>> extends AbstractPathArgument<I> {
+        private static final long serialVersionUID = 1L;
+        private final T key;
+
+        public IdentifiableItem(final Class<I> type, final T key) {
+            super(type);
+            this.key = Preconditions.checkNotNull(key, "Key may not be null.");
+        }
+
+        public T getKey() {
+            return this.key;
+        }
+
+        @Override
+        public boolean equals(final Object obj) {
+            return super.equals(obj) && key.equals(((IdentifiableItem<?, ?>) obj).getKey());
+        }
+
+        @Override
+        public int hashCode() {
+            return super.hashCode() * 31 + key.hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return getType().getName() + "[key=" + key + "]";
+        }
+    }
+
+
+    public interface InstanceIdentifierBuilder<T extends DataObject> extends Builder<InstanceIdentifier<T>> {
+        /**
+         * 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
+         */
+        @Override
+        InstanceIdentifier<T> build();
+
+        /*
+         * @deprecated use #build()
+         */
+        @Deprecated
+        InstanceIdentifier<T> toInstance();
+    }
+
+    private void writeObject(final java.io.ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+        out.writeInt(Iterables.size(pathArguments));
+        for (Object o : pathArguments) {
+            out.writeObject(o);
+        }
+    }
+
+    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+
+        final int size = in.readInt();
+        final List<PathArgument> args = new ArrayList<>(size);
+        for (int i = 0; i < size; ++i) {
+            args.add((PathArgument) in.readObject());
+        }
+
+        try {
+            PATHARGUMENTS_FIELD.set(this, ImmutableList.copyOf(args));
+        } catch (IllegalArgumentException | IllegalAccessException e) {
+            throw new IOException(e);
+        }
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierBuilderImpl.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierBuilderImpl.java
new file mode 100644 (file)
index 0000000..6060f57
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * 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.binding;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import org.opendaylight.yangtools.util.HashCodeBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+final class InstanceIdentifierBuilderImpl<T extends DataObject> implements InstanceIdentifier.InstanceIdentifierBuilder<T> {
+    private final ImmutableList.Builder<PathArgument> pathBuilder = ImmutableList.builder();
+    private final HashCodeBuilder<PathArgument> hashBuilder;
+    private final Iterable<? extends PathArgument> basePath;
+    private boolean wildcard = false;
+    private PathArgument arg = null;
+
+    InstanceIdentifierBuilderImpl() {
+        this.hashBuilder = new HashCodeBuilder<>();
+        this.basePath = null;
+    }
+
+    InstanceIdentifierBuilderImpl(final PathArgument item, final Iterable<? extends PathArgument> pathArguments, final int hash, final boolean wildcard) {
+        this.hashBuilder = new HashCodeBuilder<>(hash);
+        this.basePath = pathArguments;
+        this.wildcard = wildcard;
+        this.arg = item;
+    }
+
+    @Override
+    public int hashCode() {
+        return hashBuilder.build();
+    }
+
+    @SuppressWarnings("unchecked")
+    <N extends DataObject> InstanceIdentifierBuilderImpl<N> addNode(final Class<N> container) {
+        arg = new Item<N>(container);
+        hashBuilder.addArgument(arg);
+        pathBuilder.add(arg);
+
+        if (Identifiable.class.isAssignableFrom(container)) {
+            wildcard = true;
+        }
+
+        return (InstanceIdentifierBuilderImpl<N>) this;
+    }
+
+    @SuppressWarnings("unchecked")
+    <N extends DataObject & Identifiable<K>, K extends Identifier<N>> InstanceIdentifierBuilderImpl<N> addNode(final Class<N> listItem, final K listKey) {
+        arg = new IdentifiableItem<N, K>(listItem, listKey);
+        hashBuilder.addArgument(arg);
+        pathBuilder.add(arg);
+        return (InstanceIdentifierBuilderImpl<N>) this;
+    }
+
+    @Override
+    public <N extends ChildOf<? super T>> InstanceIdentifierBuilderImpl<N> child(final Class<N> container) {
+        return addNode(container);
+    }
+
+    @Override
+    public <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> InstanceIdentifierBuilderImpl<N> child(final Class<N> listItem, final K listKey) {
+        return addNode(listItem, listKey);
+    }
+
+    /**
+     * Build an identifier which refers to a specific augmentation of the current InstanceIdentifier referenced by
+     * the builder
+     *
+     * @param container
+     * @param <N>
+     * @return
+     */
+    @Override
+    public <N extends DataObject & Augmentation<? super T>> InstanceIdentifierBuilderImpl<N> augmentation(final Class<N> container) {
+        return addNode(container);
+    }
+
+    @Override
+    public InstanceIdentifier<T> build() {
+        Preconditions.checkState(arg != null, "No path arguments present");
+
+        final Iterable<PathArgument> pathArguments;
+        if (basePath == null) {
+            pathArguments = pathBuilder.build();
+        } else {
+            pathArguments = Iterables.concat(basePath, pathBuilder.build());
+        }
+
+        @SuppressWarnings("unchecked")
+        final InstanceIdentifier<T> ret = (InstanceIdentifier<T>) InstanceIdentifier.trustedCreate(arg, pathArguments, hashBuilder.build(), wildcard);
+        return ret;
+    }
+
+    /*
+     * @deprecated Use #build() instead.
+     */
+    @Override
+    @Deprecated
+    public InstanceIdentifier<T> toInstance() {
+        return build();
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifier.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/KeyedInstanceIdentifier.java
new file mode 100644 (file)
index 0000000..a69b988
--- /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.binding;
+
+/**
+ * An {@link InstanceIdentifier}, which has a list key attached at its last path
+ * element.
+ *
+ * @param <T> Target data type
+ * @param <K> Target key type
+ */
+public class KeyedInstanceIdentifier<T extends Identifiable<K> & DataObject, K extends Identifier<T>> extends InstanceIdentifier<T> {
+    private static final long serialVersionUID = 1L;
+    private final K key;
+
+    KeyedInstanceIdentifier(final Class<T> type, final Iterable<PathArgument> pathArguments, final boolean wildcarded, final int hash, final K key) {
+        super(type, pathArguments, wildcarded, hash);
+        this.key = key;
+    }
+
+    /**
+     * Return the key attached to this identifier. This method is equivalent to
+     * calling {@link InstanceIdentifier#keyOf(InstanceIdentifier)}.
+     *
+     * @return Key associated with this instance identifier.
+     */
+    public final K getKey() {
+        return key;
+    }
+
+    @Override
+    public final InstanceIdentifierBuilder<T> builder() {
+        return new InstanceIdentifierBuilderImpl<T>(new InstanceIdentifier.IdentifiableItem<T, K>(getTargetType(), key), pathArguments, hashCode(), isWildcarded());
+    }
+
+    @Override
+    protected boolean fastNonEqual(final InstanceIdentifier<?> other) {
+        final KeyedInstanceIdentifier<?, ?> kii = (KeyedInstanceIdentifier<?, ?>) other;
+
+        /*
+         * We could do an equals() here, but that may actually be expensive.
+         * equals() in superclass falls back to a full compare, which will
+         * end up running that equals anyway, so do not bother here.
+         */
+        return (key == null) != (kii.key == null);
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Notification.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/Notification.java
new file mode 100644 (file)
index 0000000..fca5230
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.binding;
+
+/**
+ * Marker interface for YANG-defined notifications
+ *
+ *
+ */
+public interface Notification extends DataContainer {
+
+}
+
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/NotificationListener.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/NotificationListener.java
new file mode 100644 (file)
index 0000000..6737cf5
--- /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.binding;
+
+import java.util.EventListener;
+
+/**
+ * Marker interface for generated notification listener interfaces. This interface
+ * exists solely as support for generated code. Users should never implement this
+ * interface directly, but rather implement one of the sub-interfaces generated
+ * from a YANG model.
+ *
+ * <p>
+ * The subclasses of this interface have callbacks for events, which are derived
+ * from {@link Notification} class in form void
+ * on{NotificationType}(NotificationType notification).
+ *
+ * <p>
+ * E.g. if we have notification SessionUp the callback will have signature:
+ * <code>void  onSessionUp(SessionUp notification)</code>
+ */
+public interface NotificationListener extends EventListener {
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/RpcImplementation.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/RpcImplementation.java
new file mode 100644 (file)
index 0000000..4761fdd
--- /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.binding;
+
+import java.util.Set;
+import java.util.concurrent.Future;
+
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+public interface RpcImplementation {
+
+    // Fixme: Change to RpcInput
+    Set<Class<? extends DataContainer>> getSupportedInputs();
+
+    // Fixme: Change to RpcInput
+    <T extends DataContainer> Future<RpcResult<?>> invoke(Class<T> type, T input);
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/RpcInput.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/RpcInput.java
new file mode 100644 (file)
index 0000000..11b95bd
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * 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.binding;
+
+public interface RpcInput extends DataContainer {
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/RpcService.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/RpcService.java
new file mode 100644 (file)
index 0000000..3757f5e
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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.binding;
+
+/**
+ * Marker interface for tagging generated YANG Modules
+ *
+ */
+public interface RpcService {
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/YangModelBindingProvider.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/YangModelBindingProvider.java
new file mode 100644 (file)
index 0000000..fc05db8
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.binding;
+
+import java.util.ServiceLoader;
+
+/**
+ *
+ * Provider of YangModuleInfo for specified package / model.
+ *
+ * Implementation of this interface should be discoverable
+ * via {@link ServiceLoader}
+ *
+ *
+ *
+ */
+public interface YangModelBindingProvider {
+
+    /**
+     * YangModuleInfo associated to package
+     *
+     * @return
+     */
+    YangModuleInfo getModuleInfo();
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/YangModuleInfo.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/YangModuleInfo.java
new file mode 100644 (file)
index 0000000..be32812
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * 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.binding;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Set;
+
+public interface YangModuleInfo {
+
+    /**
+     * Returns yang module name
+     *
+     * @return
+     */
+    String getName();
+
+    /**
+     *
+     * Returns revision of yang module.
+     *
+     * @return
+     */
+    String getRevision();
+
+    /**
+     * Returns XML namespace associated to the YANG module
+     *
+     * @return XML namespace associated to the YANG module.
+     */
+    String getNamespace();
+
+    InputStream getModuleSourceStream() throws IOException;
+
+    Set<YangModuleInfo> getImportedModules();
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/annotations/ModuleQName.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/annotations/ModuleQName.java
new file mode 100644 (file)
index 0000000..e92bbec
--- /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.binding.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Maintains information about yang module from which class using this annotation was generated.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.PACKAGE})
+public @interface ModuleQName {
+    String namespace();
+    String revision();
+    String name();
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/annotations/QName.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/annotations/QName.java
new file mode 100644 (file)
index 0000000..cd689a9
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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.binding.annotations;
+
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface QName {
+
+    String namespace();
+    String revision();
+    String name();
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/annotations/RoutingContext.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/annotations/RoutingContext.java
new file mode 100644 (file)
index 0000000..169d9ef
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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.binding.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+
+
+@Inherited
+@Documented
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface RoutingContext {
+
+    Class<? extends BaseIdentity> value();
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/package-info.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/package-info.java
new file mode 100644 (file)
index 0000000..eee24a9
--- /dev/null
@@ -0,0 +1,8 @@
+/*
+ * 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.binding;
\ No newline at end of file
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/AbstractMappedRpcInvoker.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/AbstractMappedRpcInvoker.java
new file mode 100644 (file)
index 0000000..8ee514e
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015 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.binding.util;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.Future;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AbstractMappedRpcInvoker<T> extends RpcServiceInvoker {
+    private static final Logger LOG = LoggerFactory.getLogger(AbstractMappedRpcInvoker.class);
+    private final Map<T, RpcMethodInvoker> map;
+
+    protected AbstractMappedRpcInvoker(final Map<T, Method> map) {
+        final Builder<T, RpcMethodInvoker> b = ImmutableMap.builder();
+
+        for (Entry<T, Method> e : map.entrySet()) {
+            if (BindingReflections.isRpcMethod(e.getValue())) {
+                b.put(e.getKey(), RpcMethodInvoker.from(e.getValue()));
+            } else {
+                LOG.debug("Method {} is not an RPC method, ignoring it", e.getValue());
+            }
+        }
+
+        this.map = b.build();
+    }
+
+    protected abstract T qnameToKey(final QName qname);
+
+    @Override
+    public final Future<RpcResult<?>> invokeRpc(@Nonnull final RpcService impl, @Nonnull final QName rpcName, @Nullable final DataObject input) {
+        Preconditions.checkNotNull(impl, "implemetation must be supplied");
+
+        RpcMethodInvoker invoker = map.get(qnameToKey(rpcName));
+        Preconditions.checkArgument(invoker != null, "Supplied RPC is not valid for implementation %s", impl);
+        return invoker.invokeOn(impl, input);
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/AugmentationFieldGetter.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/AugmentationFieldGetter.java
new file mode 100644 (file)
index 0000000..9347685
--- /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.binding.util;
+
+import org.opendaylight.yangtools.yang.binding.AugmentationHolder;
+
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import java.lang.reflect.Field;
+import java.util.Collections;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class AugmentationFieldGetter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AugmentationFieldGetter.class);
+
+    private static final AugmentationFieldGetter DUMMY = new AugmentationFieldGetter() {
+        @Override
+        protected Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object input) {
+            return Collections.emptyMap();
+        }
+    };
+
+    private static final AugmentationFieldGetter AUGMENTATION_HOLDER_GETTER = new AugmentationFieldGetter() {
+
+        @Override
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        protected Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object input) {
+            return (Map) ((AugmentationHolder<?>) input).augmentations();
+        }
+    };
+
+    /**
+     *
+     * Retrieves augmentations from supplied object
+     *
+     * @param input Input Data object, from which augmentations should be extracted
+     * @return Map of Augmentation class to augmentation
+     */
+    protected abstract Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object input);
+
+    private static final LoadingCache<Class<?>, AugmentationFieldGetter> AUGMENTATION_GETTERS = CacheBuilder
+            .newBuilder().weakKeys().softValues().build(new AugmentationGetterLoader());
+
+    public static AugmentationFieldGetter getGetter(final Class<? extends Object> clz) {
+        if(AugmentationHolder.class.isAssignableFrom(clz)) {
+            return AUGMENTATION_HOLDER_GETTER;
+        }
+        return AUGMENTATION_GETTERS.getUnchecked(clz);
+    }
+
+    private static final class AugmentationGetterLoader extends CacheLoader<Class<?>, AugmentationFieldGetter> {
+
+        @Override
+        public AugmentationFieldGetter load(final Class<?> key) throws Exception {
+            Field field;
+            try {
+                field = key.getDeclaredField(BindingMapping.AUGMENTATION_FIELD);
+            } catch (NoSuchFieldException | SecurityException e) {
+                LOG.debug("Failed to acquire augmentation field", e);
+                return DUMMY;
+            }
+            field.setAccessible(true);
+
+            return new ReflectionAugmentationFieldGetter(field);
+        }
+    }
+
+    private static final class ReflectionAugmentationFieldGetter extends AugmentationFieldGetter {
+        private final Field augmentationField;
+
+        ReflectionAugmentationFieldGetter(final Field augmentationField) {
+            this.augmentationField = Preconditions.checkNotNull(augmentationField);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        protected Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Object input) {
+            try {
+                return (Map<Class<? extends Augmentation<?>>, Augmentation<?>>) augmentationField.get(input);
+            } catch (IllegalArgumentException | IllegalAccessException e) {
+                throw new IllegalStateException("Failed to access augmentation field", e);
+            }
+        }
+    }
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/BindingReflections.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/BindingReflections.java
new file mode 100644 (file)
index 0000000..d2456f5
--- /dev/null
@@ -0,0 +1,670 @@
+/*
+ * 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.binding.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Optional;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.common.collect.Sets;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Notification;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BindingReflections {
+
+    private static final long EXPIRATION_TIME = 60;
+    private static final String ROOT_PACKAGE_PATTERN_STRING = "(org.opendaylight.yang.gen.v1.[a-z0-9_\\.]*\\.rev[0-9][0-9][0-1][0-9][0-3][0-9])";
+    private static final Pattern ROOT_PACKAGE_PATTERN = Pattern.compile(ROOT_PACKAGE_PATTERN_STRING);
+    private static final Logger LOG = LoggerFactory.getLogger(BindingReflections.class);
+
+    private static final LoadingCache<Class<?>, Optional<QName>> CLASS_TO_QNAME = CacheBuilder.newBuilder() //
+            .weakKeys() //
+            .expireAfterAccess(EXPIRATION_TIME, TimeUnit.SECONDS) //
+            .build(new ClassToQNameLoader());
+
+    private BindingReflections() {
+        throw new UnsupportedOperationException("Utility class.");
+    }
+
+    /**
+     * Find augmentation target class from concrete Augmentation class
+     *
+     * This method uses first generic argument of implemented
+     * {@link Augmentation} interface.
+     *
+     * @param augmentation
+     *            {@link Augmentation} subclass for which we want to determine
+     *            augmentation target.
+     * @return Augmentation target - class which augmentation provides
+     *         additional extensions.
+     */
+    public static Class<? extends Augmentable<?>> findAugmentationTarget(
+            final Class<? extends Augmentation<?>> augmentation) {
+        return ClassLoaderUtils.findFirstGenericArgument(augmentation, Augmentation.class);
+    }
+
+    /**
+     * Find data hierarchy parent from concrete Data class
+     *
+     * This method uses first generic argument of implemented {@link ChildOf}
+     * interface.
+     *
+     * @param childClass
+     *            child class for which we want to find the parent class.
+     * @return Parent class, e.g. class of which the childClass is ChildOf.
+     */
+    public static Class<?> findHierarchicalParent(final Class<? extends ChildOf<?>> childClass) {
+        return ClassLoaderUtils.findFirstGenericArgument(childClass, ChildOf.class);
+    }
+
+    /**
+     * Find data hierarchy parent from concrete Data class
+     *
+     * This method is shorthand which gets DataObject class by invoking
+     * {@link DataObject#getImplementedInterface()} and uses
+     * {@link #findHierarchicalParent(Class)}.
+     *
+     * @param child
+     *            Child object for which the parent needs to be located.
+     * @return Parent class, or null if a parent is not found.
+     */
+    public static Class<?> findHierarchicalParent(final DataObject child) {
+        if (child instanceof ChildOf) {
+            return ClassLoaderUtils.findFirstGenericArgument(child.getImplementedInterface(), ChildOf.class);
+        }
+        return null;
+    }
+
+    /**
+     * Returns a QName associated to supplied type
+     *
+     * @param dataType
+     * @return QName associated to supplied dataType. If dataType is
+     *         Augmentation method does not return canonical QName, but QName
+     *         with correct namespace revision, but virtual local name, since
+     *         augmentations do not have name.
+     *
+     *         May return null if QName is not present.
+     */
+    public static final QName findQName(final Class<?> dataType) {
+        return CLASS_TO_QNAME.getUnchecked(dataType).orNull();
+    }
+
+    /**
+     * Checks if method is RPC invocation
+     *
+     *
+     *
+     * @param possibleMethod
+     *            Method to check
+     * @return true if method is RPC invocation, false otherwise.
+     */
+    public static boolean isRpcMethod(final Method possibleMethod) {
+        return possibleMethod != null && RpcService.class.isAssignableFrom(possibleMethod.getDeclaringClass())
+                && Future.class.isAssignableFrom(possibleMethod.getReturnType())
+                && possibleMethod.getParameterTypes().length <= 1;
+    }
+
+    /**
+     *
+     * Extracts Output class for RPC method
+     *
+     * @param targetMethod
+     *            method to scan
+     * @return Optional.absent() if result type could not be get, or return type
+     *         is Void.
+     */
+    @SuppressWarnings("rawtypes")
+    public static Optional<Class<?>> resolveRpcOutputClass(final Method targetMethod) {
+        checkState(isRpcMethod(targetMethod), "Supplied method is not Rpc invocation method");
+        Type futureType = targetMethod.getGenericReturnType();
+        Type rpcResultType = ClassLoaderUtils.getFirstGenericParameter(futureType);
+        Type rpcResultArgument = ClassLoaderUtils.getFirstGenericParameter(rpcResultType);
+        if (rpcResultArgument instanceof Class && !Void.class.equals(rpcResultArgument)) {
+            return Optional.<Class<?>> of((Class) rpcResultArgument);
+        }
+        return Optional.absent();
+    }
+
+    /**
+     *
+     * Extracts input class for RPC method
+     *
+     * @param targetMethod
+     *            method to scan
+     * @return Optional.absent() if rpc has no input, Rpc input type otherwise.
+     */
+    @SuppressWarnings("unchecked")
+    public static Optional<Class<? extends DataContainer>> resolveRpcInputClass(final Method targetMethod) {
+        @SuppressWarnings("rawtypes")
+        Class[] types = targetMethod.getParameterTypes();
+        if (types.length == 0) {
+            return Optional.absent();
+        }
+        if (types.length == 1) {
+            return Optional.<Class<? extends DataContainer>> of(types[0]);
+        }
+        throw new IllegalArgumentException("Method has 2 or more arguments.");
+    }
+
+    public static QName getQName(final Class<? extends BaseIdentity> context) {
+        return findQName(context);
+    }
+
+    /**
+     *
+     * Checks if class is child of augmentation.
+     *
+     *
+     * @param clazz
+     * @return
+     */
+    public static boolean isAugmentationChild(final Class<?> clazz) {
+        // FIXME: Current resolver could be still confused when
+        // child node was added by grouping
+        checkArgument(clazz != null);
+
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        Class<?> parent = findHierarchicalParent((Class) clazz);
+        if (parent == null) {
+            LOG.debug("Did not find a parent for class {}", clazz);
+            return false;
+        }
+
+        String clazzModelPackage = getModelRootPackageName(clazz.getPackage());
+        String parentModelPackage = getModelRootPackageName(parent.getPackage());
+
+        return !clazzModelPackage.equals(parentModelPackage);
+    }
+
+    /**
+     * Returns root package name for suplied package.
+     *
+     * @param pkg
+     *            Package for which find model root package.
+     * @return Package of model root.
+     */
+    public static String getModelRootPackageName(final Package pkg) {
+        return getModelRootPackageName(pkg.getName());
+    }
+
+    /**
+     * Returns root package name for supplied package name.
+     *
+     * @param name
+     *            Package for which find model root package.
+     * @return Package of model root.
+     */
+    public static String getModelRootPackageName(final String name) {
+        checkArgument(name != null, "Package name should not be null.");
+        checkArgument(name.startsWith(BindingMapping.PACKAGE_PREFIX), "Package name not starting with %s, is: %s",
+                BindingMapping.PACKAGE_PREFIX, name);
+        Matcher match = ROOT_PACKAGE_PATTERN.matcher(name);
+        checkArgument(match.find(), "Package name '%s' does not match required pattern '%s'", name,
+                ROOT_PACKAGE_PATTERN_STRING);
+        return match.group(0);
+    }
+
+    public static final QNameModule getQNameModule(final Class<?> clz) {
+        if(DataContainer.class.isAssignableFrom(clz) || BaseIdentity.class.isAssignableFrom(clz)) {
+            return findQName(clz).getModule();
+        }
+        try {
+            YangModuleInfo modInfo = BindingReflections.getModuleInfo(clz);
+            return getQNameModule(modInfo);
+        } catch (Exception e) {
+            throw new IllegalStateException("Unable to get QName of defining model.", e);
+        }
+    }
+
+    public static final QNameModule getQNameModule(final YangModuleInfo modInfo) {
+        return QNameModule.create(URI.create(modInfo.getNamespace()), QName.parseRevision(modInfo.getRevision()));
+    }
+
+    /**
+     *
+     * Returns instance of {@link YangModuleInfo} of declaring model for
+     * specific class.
+     *
+     * @param cls
+     * @return Instance of {@link YangModuleInfo} associated with model, from
+     *         which this class was derived.
+     * @throws Exception
+     */
+    public static YangModuleInfo getModuleInfo(final Class<?> cls) throws Exception {
+        checkArgument(cls != null);
+        String packageName = getModelRootPackageName(cls.getPackage());
+        final String potentialClassName = getModuleInfoClassName(packageName);
+        return ClassLoaderUtils.withClassLoader(cls.getClassLoader(), new Callable<YangModuleInfo>() {
+            @Override
+            public YangModuleInfo call() throws ClassNotFoundException, IllegalAccessException,
+                    IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+                Class<?> moduleInfoClass = Thread.currentThread().getContextClassLoader().loadClass(potentialClassName);
+                return (YangModuleInfo) moduleInfoClass.getMethod("getInstance").invoke(null);
+            }
+        });
+    }
+
+    public static String getModuleInfoClassName(final String packageName) {
+        return packageName + "." + BindingMapping.MODULE_INFO_CLASS_NAME;
+    }
+
+    /**
+     *
+     * Check if supplied class is derived from YANG model.
+     *
+     * @param cls
+     *            Class to check
+     * @return true if class is derived from YANG model.
+     */
+    public static boolean isBindingClass(final Class<?> cls) {
+        if (DataContainer.class.isAssignableFrom(cls) || Augmentation.class.isAssignableFrom(cls)) {
+            return true;
+        }
+        return (cls.getName().startsWith(BindingMapping.PACKAGE_PREFIX));
+    }
+
+    /**
+     *
+     * Checks if supplied method is callback for notifications.
+     *
+     * @param method
+     * @return true if method is notification callback.
+     */
+    public static boolean isNotificationCallback(final Method method) {
+        checkArgument(method != null);
+        if (method.getName().startsWith("on") && method.getParameterTypes().length == 1) {
+            Class<?> potentialNotification = method.getParameterTypes()[0];
+            if (isNotification(potentialNotification)
+                    && method.getName().equals("on" + potentialNotification.getSimpleName())) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     *
+     * Checks is supplied class is Notification.
+     *
+     * @param potentialNotification
+     * @return
+     */
+    public static boolean isNotification(final Class<?> potentialNotification) {
+        checkArgument(potentialNotification != null, "potentialNotification must not be null.");
+        return Notification.class.isAssignableFrom(potentialNotification);
+    }
+
+    /**
+     *
+     * Loads {@link YangModuleInfo} infos available on current classloader.
+     *
+     * This method is shorthand for {@link #loadModuleInfos(ClassLoader)} with
+     * {@link Thread#getContextClassLoader()} for current thread.
+     *
+     * @return Set of {@link YangModuleInfo} available for current classloader.
+     */
+    public static ImmutableSet<YangModuleInfo> loadModuleInfos() {
+        return loadModuleInfos(Thread.currentThread().getContextClassLoader());
+    }
+
+    /**
+     *
+     * Loads {@link YangModuleInfo} infos available on supplied classloader.
+     *
+     * {@link YangModuleInfo} are discovered using {@link ServiceLoader} for
+     * {@link YangModelBindingProvider}. {@link YangModelBindingProvider} are
+     * simple classes which holds only pointers to actual instance
+     * {@link YangModuleInfo}.
+     *
+     * When {@link YangModuleInfo} is available, all dependencies are
+     * recursivelly collected into returning set by collecting results of
+     * {@link YangModuleInfo#getImportedModules()}.
+     *
+     *
+     * @param loader
+     *            Classloader for which {@link YangModuleInfo} should be
+     *            retrieved.
+     * @return Set of {@link YangModuleInfo} available for supplied classloader.
+     */
+    public static ImmutableSet<YangModuleInfo> loadModuleInfos(final ClassLoader loader) {
+        Builder<YangModuleInfo> moduleInfoSet = ImmutableSet.<YangModuleInfo> builder();
+        ServiceLoader<YangModelBindingProvider> serviceLoader = ServiceLoader.load(YangModelBindingProvider.class,
+                loader);
+        for (YangModelBindingProvider bindingProvider : serviceLoader) {
+            YangModuleInfo moduleInfo = bindingProvider.getModuleInfo();
+            checkState(moduleInfo != null, "Module Info for %s is not available.", bindingProvider.getClass());
+            collectYangModuleInfo(bindingProvider.getModuleInfo(), moduleInfoSet);
+        }
+        return moduleInfoSet.build();
+    }
+
+    private static void collectYangModuleInfo(final YangModuleInfo moduleInfo,
+            final Builder<YangModuleInfo> moduleInfoSet) {
+        moduleInfoSet.add(moduleInfo);
+        for (YangModuleInfo dependency : moduleInfo.getImportedModules()) {
+            collectYangModuleInfo(dependency, moduleInfoSet);
+        }
+    }
+
+    /**
+     *
+     * Checks if supplied class represents RPC Input / RPC Output.
+     *
+     * @param targetType
+     *            Class to be checked
+     * @return true if class represents RPC Input or RPC Output class.
+     */
+    public static boolean isRpcType(final Class<? extends DataObject> targetType) {
+        return DataContainer.class.isAssignableFrom(targetType) //
+                && !ChildOf.class.isAssignableFrom(targetType) //
+                && !Notification.class.isAssignableFrom(targetType) //
+                && (targetType.getName().endsWith("Input") || targetType.getName().endsWith("Output"));
+    }
+
+    /**
+     *
+     * Scans supplied class and returns an iterable of all data children
+     * classes.
+     *
+     * @param type
+     *            YANG Modeled Entity derived from DataContainer
+     * @return Iterable of all data children, which have YANG modeled entity
+     */
+    @SuppressWarnings("unchecked")
+    public static Iterable<Class<? extends DataObject>> getChildrenClasses(final Class<? extends DataContainer> type) {
+        checkArgument(type != null, "Target type must not be null");
+        checkArgument(DataContainer.class.isAssignableFrom(type), "Supplied type must be derived from DataContainer");
+        List<Class<? extends DataObject>> ret = new LinkedList<>();
+        for (Method method : type.getMethods()) {
+            Optional<Class<? extends DataContainer>> entity = getYangModeledReturnType(method);
+            if (entity.isPresent()) {
+                ret.add((Class<? extends DataObject>) entity.get());
+            }
+        }
+        return ret;
+    }
+
+    /**
+     *
+     * Scans supplied class and returns an iterable of all data children
+     * classes.
+     *
+     * @param type
+     *            YANG Modeled Entity derived from DataContainer
+     * @return Iterable of all data children, which have YANG modeled entity
+     */
+    public static Map<Class<?>, Method> getChildrenClassToMethod(final Class<?> type) {
+        checkArgument(type != null, "Target type must not be null");
+        checkArgument(DataContainer.class.isAssignableFrom(type), "Supplied type must be derived from DataContainer");
+        Map<Class<?>, Method> ret = new HashMap<>();
+        for (Method method : type.getMethods()) {
+            Optional<Class<? extends DataContainer>> entity = getYangModeledReturnType(method);
+            if (entity.isPresent()) {
+                ret.put(entity.get(), method);
+            }
+        }
+        return ret;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static Optional<Class<? extends DataContainer>> getYangModeledReturnType(final Method method) {
+        if (method.getName().equals("getClass") || !method.getName().startsWith("get")
+                || method.getParameterTypes().length > 0) {
+            return Optional.absent();
+        }
+
+        @SuppressWarnings("rawtypes")
+        Class returnType = method.getReturnType();
+        if (DataContainer.class.isAssignableFrom(returnType)) {
+            return Optional.<Class<? extends DataContainer>> of(returnType);
+        } else if (List.class.isAssignableFrom(returnType)) {
+            try {
+                return ClassLoaderUtils.withClassLoader(method.getDeclaringClass().getClassLoader(),
+                        new Callable<Optional<Class<? extends DataContainer>>>() {
+                            @SuppressWarnings("rawtypes")
+                            @Override
+                            public Optional<Class<? extends DataContainer>> call() {
+                                Type listResult = ClassLoaderUtils.getFirstGenericParameter(method
+                                        .getGenericReturnType());
+                                if (listResult instanceof Class
+                                        && DataContainer.class.isAssignableFrom((Class) listResult)) {
+                                    return Optional.<Class<? extends DataContainer>> of((Class) listResult);
+                                }
+                                return Optional.absent();
+                            }
+
+                        });
+            } catch (Exception e) {
+                /*
+                 *
+                 * It is safe to log this this exception on debug, since this
+                 * method should not fail. Only failures are possible if the
+                 * runtime / backing.
+                 */
+                LOG.debug("Unable to find YANG modeled return type for {}", method, e);
+            }
+        }
+        return Optional.absent();
+    }
+
+    private static class ClassToQNameLoader extends CacheLoader<Class<?>, Optional<QName>> {
+
+        @Override
+        public Optional<QName> load(final Class<?> key) throws Exception {
+            return resolveQNameNoCache(key);
+        }
+    }
+
+    /**
+     *
+     * Tries to resolve QName for supplied class.
+     *
+     * Looks up for static field with name from constant
+     * {@link BindingMapping#QNAME_STATIC_FIELD_NAME} and returns value if
+     * present.
+     *
+     * If field is not present uses {@link #computeQName(Class)} to compute
+     * QName for missing types.
+     *
+     * @param key
+     * @return
+     */
+    private static Optional<QName> resolveQNameNoCache(final Class<?> key) {
+        try {
+            Field field = key.getField(BindingMapping.QNAME_STATIC_FIELD_NAME);
+            Object obj = field.get(null);
+            if (obj instanceof QName) {
+                return Optional.of((QName) obj);
+            }
+
+        } catch (NoSuchFieldException e) {
+            return Optional.of(computeQName(key));
+
+        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
+            /*
+             *
+             * It is safe to log this this exception on debug, since this method
+             * should not fail. Only failures are possible if the runtime /
+             * backing.
+             */
+            LOG.debug("Unexpected exception during extracting QName for {}", key, e);
+        }
+        return Optional.absent();
+    }
+
+    /**
+     * Computes QName for supplied class
+     *
+     * Namespace and revision are same as {@link YangModuleInfo} associated with
+     * supplied class.
+     * <p>
+     * If class is
+     * <ul>
+     * <li>rpc input: local name is "input".
+     * <li>rpc output: local name is "output".
+     * <li>augmentation: local name is "module name".
+     * </ul>
+     *
+     * There is also fallback, if it is not possible to compute QName using
+     * following algorithm returns module QName.
+     *
+     * FIXME: Extend this algorithm to also provide QName for YANG modeled
+     * simple types.
+     *
+     * @throws IllegalStateException
+     *             If YangModuleInfo could not be resolved
+     * @throws IllegalArgumentException
+     *             If supplied class was not derived from YANG model.
+     *
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private static QName computeQName(final Class key) {
+        if (isBindingClass(key)) {
+            YangModuleInfo moduleInfo;
+            try {
+                moduleInfo = getModuleInfo(key);
+            } catch (Exception e) {
+                throw new IllegalStateException("Unable to get QName for " + key + ". YangModuleInfo was not found.", e);
+            }
+            final QName module = QName.cachedReference(getModuleQName(moduleInfo));
+            if (Augmentation.class.isAssignableFrom(key)) {
+                return module;
+            } else if (isRpcType(key)) {
+                final String className = key.getSimpleName();
+                if (className.endsWith(BindingMapping.RPC_OUTPUT_SUFFIX)) {
+                    return QName.cachedReference(QName.create(module, "output"));
+                } else {
+                    return QName.cachedReference(QName.create(module, "input"));
+                }
+            }
+            /*
+             * Fallback for Binding types which do not have QNAME field
+             */
+            return module;
+        } else {
+            throw new IllegalArgumentException("Supplied class " + key + "is not derived from YANG.");
+        }
+    }
+
+    /**
+     * Given a {@link YangModuleInfo}, create a QName representing it. The QName
+     * is formed by reusing the module's namespace and revision using the
+     * module's name as the QName's local name.
+     *
+     * @param moduleInfo
+     *            module information
+     * @return QName representing the module
+     */
+    public static QName getModuleQName(final YangModuleInfo moduleInfo) {
+        checkArgument(moduleInfo != null, "moduleInfo must not be null.");
+        return QName.create(moduleInfo.getNamespace(), moduleInfo.getRevision(), moduleInfo.getName());
+    }
+
+    /**
+     * Extracts augmentation from Binding DTO field using reflection
+     *
+     * @param input
+     *            Instance of DataObject which is augmentable and may contain
+     *            augmentation
+     * @return Map of augmentations if read was successful, otherwise empty map.
+     */
+    public static Map<Class<? extends Augmentation<?>>, Augmentation<?>> getAugmentations(final Augmentable<?> input) {
+        return AugmentationFieldGetter.getGetter(input.getClass()).getAugmentations(input);
+    }
+
+    /**
+     *
+     * Determines if two augmentation classes or case classes represents same
+     * data.
+     * <p>
+     * Two augmentations or cases could be substituted only if and if:
+     * <ul>
+     * <li>Both implements same interfaces</li>
+     * <li>Both have same children</li>
+     * <li>If augmentations: Both have same augmentation target class. Target
+     * class was generated for data node in grouping.</li>
+     * <li>If cases: Both are from same choice. Choice class was generated for
+     * data node in grouping.</li>
+     * </ul>
+     * <p>
+     * <b>Explanation:</b> Binding Specification reuses classes generated for
+     * groupings as part of normal data tree, this classes from grouping could
+     * be used at various locations and user may not be aware of it and may use
+     * incorrect case or augmentation in particular subtree (via copy
+     * constructors, etc).
+     *
+     * @param potential
+     *            Class which is potential substition
+     * @param target
+     *            Class which should be used at particular subtree
+     * @return true if and only if classes represents same data.
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static boolean isSubstitutionFor(final Class potential, final Class target) {
+        HashSet<Class> subImplemented = Sets.newHashSet(potential.getInterfaces());
+        HashSet<Class> targetImplemented = Sets.newHashSet(target.getInterfaces());
+        if (!subImplemented.equals(targetImplemented)) {
+            return false;
+        }
+        if (Augmentation.class.isAssignableFrom(potential)
+                && !BindingReflections.findAugmentationTarget(potential).equals(
+                        BindingReflections.findAugmentationTarget(target))) {
+            return false;
+        }
+        for (Method potentialMethod : potential.getMethods()) {
+            try {
+                Method targetMethod = target.getMethod(potentialMethod.getName(), potentialMethod.getParameterTypes());
+                if (!potentialMethod.getReturnType().equals(targetMethod.getReturnType())) {
+                    return false;
+                }
+            } catch (NoSuchMethodException e) {
+                // Counterpart method is missing, so classes could not be
+                // substituted.
+                return false;
+            } catch (SecurityException e) {
+                throw new IllegalStateException("Could not compare methods", e);
+            }
+        }
+        return true;
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/ClassBasedRpcServiceInvoker.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/ClassBasedRpcServiceInvoker.java
new file mode 100644 (file)
index 0000000..69a8179
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015 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.binding.util;
+
+import com.google.common.base.Preconditions;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.QName;
+
+final class ClassBasedRpcServiceInvoker extends AbstractMappedRpcInvoker<String> {
+    private static final LoadingCache<Class<? extends RpcService>, RpcServiceInvoker> INVOKERS = CacheBuilder.newBuilder()
+            .weakKeys()
+            .build(new CacheLoader<Class<? extends RpcService>, RpcServiceInvoker>() {
+                @Override
+                public RpcServiceInvoker load(final Class<? extends RpcService> key) {
+                    final Map<String, Method> ret = new HashMap<>();
+                    for (Method m : key.getMethods()) {
+                        ret.put(m.getName(), m);
+                    }
+
+                    return new ClassBasedRpcServiceInvoker(ret);
+                }
+            });
+
+    ClassBasedRpcServiceInvoker(final Map<String, Method> ret) {
+        super(ret);
+    }
+
+    @Override
+    protected String qnameToKey(final QName qname) {
+        return BindingMapping.getMethodName(qname);
+    }
+
+    static RpcServiceInvoker instanceFor(final Class<? extends RpcService> type) {
+        Preconditions.checkArgument(type.isInterface());
+        Preconditions.checkArgument(BindingReflections.isBindingClass(type));
+        return INVOKERS.getUnchecked(type);
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/ClassLoaderUtils.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/ClassLoaderUtils.java
new file mode 100644 (file)
index 0000000..e9ddbfb
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * 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.binding.util;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.locks.Lock;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @deprecated Use {@link org.opendaylight.yangtools.util.ClassLoaderUtils} instead.
+ */
+@Deprecated
+public final class ClassLoaderUtils {
+    private static final Logger LOG = LoggerFactory.getLogger(ClassLoaderUtils.class);
+
+    private ClassLoaderUtils() {
+        throw new UnsupportedOperationException("Utility class");
+    }
+
+    /**
+     *
+     * Runs {@link Supplier} with provided {@link ClassLoader}.
+     *
+     * Invokes supplies function and makes sure that original {@link ClassLoader}
+     * is context {@link ClassLoader} after execution.
+     *
+     * @param cls {@link ClassLoader} to be used.
+     * @param function Function to be executed.
+     * @return Result of supplier invocation.
+     *
+     */
+    public static <V> V withClassLoader(final ClassLoader cls, final Supplier<V> function) {
+        checkNotNull(cls, "Classloader should not be null");
+        checkNotNull(function, "Function should not be null");
+
+        final ClassLoader oldCls = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(cls);
+            return function.get();
+        } finally {
+            Thread.currentThread().setContextClassLoader(oldCls);
+        }
+    }
+
+    /**
+     *
+     * Runs {@link Callable} with provided {@link ClassLoader}.
+     *
+     * Invokes supplies function and makes sure that original {@link ClassLoader}
+     * is context {@link ClassLoader} after execution.
+     *
+     * @param cls {@link ClassLoader} to be used.
+     * @param function Function to be executed.
+     * @return Result of callable invocation.
+     *
+     */
+    public static <V> V withClassLoader(final ClassLoader cls, final Callable<V> function) throws Exception {
+        checkNotNull(cls, "Classloader should not be null");
+        checkNotNull(function, "Function should not be null");
+
+        final ClassLoader oldCls = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(cls);
+            return function.call();
+        } finally {
+            Thread.currentThread().setContextClassLoader(oldCls);
+        }
+    }
+
+    /**
+     *
+     * Runs {@link Callable} with provided {@link ClassLoader} and Lock.
+     *
+     * Invokes supplies function after acquiring lock
+     * and makes sure that original {@link ClassLoader}
+     * is context {@link ClassLoader} and lock is unlocked
+     * after execution.
+     *
+     * @param cls {@link ClassLoader} to be used.
+     * @param function Function to be executed.
+     * @return Result of Callable invocation.
+     *
+     */
+    public static <V> V withClassLoaderAndLock(final ClassLoader cls, final Lock lock, final Supplier<V> function) {
+        checkNotNull(lock, "Lock should not be null");
+
+        lock.lock();
+        try {
+            return withClassLoader(cls, function);
+        } finally {
+            lock.unlock();
+        }
+    }
+
+    public static Object construct(final Constructor<? extends Object> constructor, final List<Object> objects)
+            throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+        final Object[] initargs = objects.toArray();
+        return constructor.newInstance(initargs);
+    }
+
+    /**
+     *
+     * Loads class using this supplied classloader.
+     *
+     *
+     * @param cls
+     * @param name String name of class.
+     * @return
+     * @throws ClassNotFoundException
+     */
+    public static Class<?> loadClass(final ClassLoader cls, final String name) throws ClassNotFoundException {
+        if ("byte[]".equals(name)) {
+            return byte[].class;
+        }
+        if ("char[]".equals(name)) {
+            return char[].class;
+        }
+
+        try {
+            return cls.loadClass(name);
+        } catch (ClassNotFoundException e) {
+            String[] components = name.split("\\.");
+            String potentialOuter;
+            int length = components.length;
+            if (length > 2 && (potentialOuter = components[length - 2]) != null && Character.isUpperCase(potentialOuter.charAt(0))) {
+                String outerName = Joiner.on(".").join(Arrays.asList(components).subList(0, length - 1));
+                String innerName = outerName + "$" + components[length-1];
+                return cls.loadClass(innerName);
+            } else {
+                throw e;
+            }
+        }
+    }
+
+    public static Class<?> loadClassWithTCCL(final String name) throws ClassNotFoundException {
+        return loadClass(Thread.currentThread().getContextClassLoader(), name);
+    }
+
+    public static Class<?> tryToLoadClassWithTCCL(final String fullyQualifiedName) {
+        try {
+            return loadClassWithTCCL(fullyQualifiedName);
+        } catch (ClassNotFoundException e) {
+            LOG.debug("Failed to load class {}", fullyQualifiedName, e);
+            return null;
+        }
+    }
+
+    public static <S,G,P> Class<P> findFirstGenericArgument(final Class<S> scannedClass, final Class<G> genericType) {
+        return withClassLoader(scannedClass.getClassLoader(), ClassLoaderUtils.<S,G,P>findFirstGenericArgumentTask(scannedClass, genericType));
+    }
+
+    private static <S,G,P> Supplier<Class<P>> findFirstGenericArgumentTask(final Class<S> scannedClass, final Class<G> genericType) {
+        return new Supplier<Class<P>>() {
+            @Override
+            @SuppressWarnings("unchecked")
+            public Class<P> get() {
+                final ParameterizedType augmentationGeneric = findParameterizedType(scannedClass, genericType);
+                if (augmentationGeneric != null) {
+                    return (Class<P>) augmentationGeneric.getActualTypeArguments()[0];
+                }
+                return null;
+            }
+        };
+    }
+
+    public static ParameterizedType findParameterizedType(final Class<?> subclass, final Class<?> genericType) {
+        Preconditions.checkNotNull(subclass);
+        Preconditions.checkNotNull(genericType);
+
+        for (Type type : subclass.getGenericInterfaces()) {
+            if (type instanceof ParameterizedType && genericType.equals(((ParameterizedType) type).getRawType())) {
+                return (ParameterizedType) type;
+            }
+        }
+
+        LOG.debug("Class {} does not declare interface {}", subclass, genericType);
+        return null;
+    }
+
+    public static Type getFirstGenericParameter(final Type type) {
+        if (type instanceof ParameterizedType) {
+            return ((ParameterizedType) type).getActualTypeArguments()[0];
+        }
+        return null;
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/DataObjectReadingUtil.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/DataObjectReadingUtil.java
new file mode 100644 (file)
index 0000000..cf98712
--- /dev/null
@@ -0,0 +1,349 @@
+/*
+ * 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.binding.util;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.opendaylight.yangtools.yang.binding.Augmentable;
+import org.opendaylight.yangtools.yang.binding.Augmentation;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
+
+public class DataObjectReadingUtil {
+
+    private DataObjectReadingUtil() {
+        throw new UnsupportedOperationException("Utility class. Instantion is not allowed.");
+    }
+
+    /**
+     *
+     * @param parent
+     *            Parent object on which read operation will be performed
+     * @param parentPath
+     *            Path, to parent object.
+     * @param childPath
+     *            Path, which is nested to parent, and should be readed.
+     * @return Value of object.
+     */
+    public static final <T extends DataObject, P extends DataObject> Map<InstanceIdentifier<T>, T> readData(final P parent,
+            final InstanceIdentifier<P> parentPath, final InstanceIdentifier<T> childPath) {
+        checkArgument(parent != null, "Parent must not be null.");
+        checkArgument(parentPath != null, "Parent path must not be null");
+        checkArgument(childPath != null, "Child path must not be null");
+        checkArgument(parentPath.containsWildcarded(childPath), "Parent object must be parent of child.");
+
+        List<PathArgument> pathArgs = subList(parentPath.getPathArguments(), childPath.getPathArguments());
+        @SuppressWarnings("rawtypes")
+        Map<InstanceIdentifier, DataContainer> lastFound = Collections
+                .<InstanceIdentifier, DataContainer> singletonMap(parentPath, parent);
+        for (PathArgument pathArgument : pathArgs) {
+            @SuppressWarnings("rawtypes")
+            final ImmutableMap.Builder<InstanceIdentifier, DataContainer> potentialBuilder = ImmutableMap.builder();
+            for (@SuppressWarnings("rawtypes")
+            Entry<InstanceIdentifier, DataContainer> entry : lastFound.entrySet()) {
+                potentialBuilder.putAll(readData(entry, pathArgument));
+            }
+            lastFound = potentialBuilder.build();
+            if (lastFound.isEmpty()) {
+                return Collections.emptyMap();
+            }
+        }
+        @SuppressWarnings({ "unchecked", "rawtypes" })
+        final Map<InstanceIdentifier<T>, T> result = (Map) lastFound;
+        return result;
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static Map<InstanceIdentifier, DataContainer> readData(final Entry<InstanceIdentifier, DataContainer> entry,
+            final PathArgument pathArgument) {
+        return readData(entry.getValue(), entry.getKey(), pathArgument);
+    }
+
+    public static final <T extends DataObject> Optional<T> readData(final DataObject source, final Class<T> child) {
+        checkArgument(source != null, "Object should not be null.");
+        checkArgument(child != null, "Child type should not be null");
+        Class<? extends DataContainer> parentClass = source.getImplementedInterface();
+
+        @SuppressWarnings("unchecked")
+        T potential = (T) resolveReadStrategy(parentClass, child).read(source, child);
+        return Optional.fromNullable(potential);
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static final Map<InstanceIdentifier, DataContainer> readData(final DataContainer parent,
+            final InstanceIdentifier parentPath, final PathArgument child) {
+        checkArgument(parent != null, "Object should not be null.");
+        checkArgument(child != null, "Child argument should not be null");
+        Class<? extends DataContainer> parentClass = parent.getImplementedInterface();
+        return resolveReadStrategy(parentClass, child.getType()).readUsingPathArgument(parent, child, parentPath);
+    }
+
+    private static DataObjectReadingStrategy resolveReadStrategy(final Class<? extends DataContainer> parentClass,
+            final Class<? extends DataContainer> type) {
+
+        DataObjectReadingStrategy strategy = createReadStrategy(parentClass, type);
+        // FIXME: Add caching of strategies
+        return strategy;
+    }
+
+    private static DataObjectReadingStrategy createReadStrategy(final Class<? extends DataContainer> parent,
+            final Class<? extends DataContainer> child) {
+
+        if (Augmentable.class.isAssignableFrom(parent) && Augmentation.class.isAssignableFrom(child)) {
+            return REAUSABLE_AUGMENTATION_READING_STRATEGY;
+        }
+
+        /*
+         * FIXME Ensure that this strategies also works for children of cases.
+         * Possible edge-case is : Parent container uses grouping foo case is
+         * added by augmentation also uses foo.
+         */
+        if (Identifiable.class.isAssignableFrom(child)) {
+            @SuppressWarnings("unchecked")
+            final Class<? extends Identifiable<?>> identifiableClass = (Class<? extends Identifiable<?>>) child;
+            return new ListItemReadingStrategy(parent, identifiableClass);
+        }
+        return new ContainerReadingStrategy(parent, child);
+    }
+
+    private static Method resolveGetterMethod(final Class<? extends DataContainer> parent, final Class<?> child) {
+        String methodName = "get" + child.getSimpleName();
+        try {
+            return parent.getMethod(methodName);
+        } catch (NoSuchMethodException e) {
+            throw new IllegalArgumentException(e);
+        } catch (SecurityException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static abstract class DataObjectReadingStrategy {
+
+        private final Class<? extends DataContainer> parentType;
+        private final Class<? extends DataContainer> childType;
+        private final Method getterMethod;
+
+        @SuppressWarnings("unchecked")
+        public DataObjectReadingStrategy(final Class parentType, final Class childType) {
+            super();
+            checkArgument(DataContainer.class.isAssignableFrom(parentType));
+            checkArgument(DataContainer.class.isAssignableFrom(childType));
+            this.parentType = parentType;
+            this.childType = childType;
+            this.getterMethod = resolveGetterMethod(parentType, childType);
+        }
+
+        @SuppressWarnings("unchecked")
+        public DataObjectReadingStrategy(final Class parentType, final Class childType, final Method getter) {
+            this.parentType = parentType;
+            this.childType = childType;
+            this.getterMethod = getter;
+        }
+
+        @SuppressWarnings("unused")
+        protected Class<? extends DataContainer> getParentType() {
+            return parentType;
+        }
+
+        protected Class<? extends DataContainer> getChildType() {
+            return childType;
+        }
+
+        protected Method getGetterMethod() {
+            return getterMethod;
+        }
+
+        public abstract Map<InstanceIdentifier, DataContainer> readUsingPathArgument(DataContainer parent,
+                PathArgument childArgument, InstanceIdentifier targetBuilder);
+
+        public abstract DataContainer read(DataContainer parent, Class<?> childType);
+
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static class ContainerReadingStrategy extends DataObjectReadingStrategy {
+
+        public ContainerReadingStrategy(final Class<? extends DataContainer> parent, final Class<? extends DataContainer> child) {
+            super(parent, child);
+            checkArgument(child.isAssignableFrom(getGetterMethod().getReturnType()));
+        }
+
+        @Override
+        public Map<InstanceIdentifier, DataContainer> readUsingPathArgument(final DataContainer parent,
+                final PathArgument childArgument, final InstanceIdentifier parentPath) {
+            final DataContainer result = read(parent, childArgument.getType());
+            if (result != null) {
+                @SuppressWarnings("unchecked")
+                InstanceIdentifier childPath = parentPath.child(childArgument.getType());
+                return Collections.singletonMap(childPath, result);
+            }
+            return Collections.emptyMap();
+        }
+
+        @Override
+        public DataContainer read(final DataContainer parent, final Class<?> childType) {
+            try {
+                Object potentialData = getGetterMethod().invoke(parent);
+                checkState(potentialData instanceof DataContainer);
+                return (DataContainer) potentialData;
+
+            } catch (IllegalAccessException | InvocationTargetException e) {
+                throw new IllegalArgumentException(e);
+            }
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    private static class ListItemReadingStrategy extends DataObjectReadingStrategy {
+
+        public ListItemReadingStrategy(final Class<? extends DataContainer> parent, final Class child) {
+            super(parent, child);
+            checkArgument(Iterable.class.isAssignableFrom(getGetterMethod().getReturnType()));
+        }
+
+        @Override
+        public DataContainer read(final DataContainer parent, final Class<?> childType) {
+            // This will always fail since we do not have key.
+            return null;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public Map<InstanceIdentifier, DataContainer> readUsingPathArgument(final DataContainer parent,
+                final PathArgument childArgument, final InstanceIdentifier builder) {
+            try {
+                Object potentialList = getGetterMethod().invoke(parent);
+                if (potentialList instanceof Iterable) {
+
+                    final Iterable<Identifiable> dataList = (Iterable<Identifiable>) potentialList;
+                    if (childArgument instanceof IdentifiableItem<?, ?>) {
+                        return readUsingIdentifiableItem(dataList, (IdentifiableItem) childArgument, builder);
+                    } else {
+                        return readAll(dataList, builder);
+                    }
+                }
+            } catch (InvocationTargetException e) {
+                throw new IllegalStateException(e);
+            } catch (IllegalAccessException e) {
+                throw new IllegalStateException(e);
+            } catch (IllegalArgumentException e) {
+                throw new IllegalStateException(e);
+            }
+            return Collections.emptyMap();
+        }
+
+        private Map<InstanceIdentifier, DataContainer> readAll(final Iterable<Identifiable> dataList,
+                final InstanceIdentifier parentPath) {
+            Builder<InstanceIdentifier, DataContainer> result = ImmutableMap
+                    .<InstanceIdentifier, DataContainer> builder();
+            for (Identifiable item : dataList) {
+                @SuppressWarnings("unchecked")
+                InstanceIdentifier childPath = parentPath.child(getChildType(), item.getKey());
+                result.put(childPath, (DataContainer) item);
+            }
+            return result.build();
+        }
+
+        @SuppressWarnings("unchecked")
+        private Map<InstanceIdentifier, DataContainer> readUsingIdentifiableItem(final Iterable<Identifiable> dataList,
+                final IdentifiableItem childArgument, final InstanceIdentifier parentPath) {
+            final Identifier<?> key = childArgument.getKey();
+            for (Identifiable item : dataList) {
+                if (key.equals(item.getKey()) && item instanceof DataContainer) {
+                    checkState(childArgument.getType().isInstance(item),
+                            "Found child is not instance of requested type");
+                    InstanceIdentifier childPath = parentPath
+                            .child(childArgument.getType(), item.getKey());
+                    return Collections.singletonMap(childPath, (DataContainer) item);
+                }
+            }
+            return Collections.emptyMap();
+        }
+
+    }
+
+    private static final DataObjectReadingStrategy REAUSABLE_AUGMENTATION_READING_STRATEGY = new AugmentationReadingStrategy();
+
+    private static final class AugmentationReadingStrategy extends DataObjectReadingStrategy {
+
+        public AugmentationReadingStrategy() {
+            super(Augmentable.class, Augmentation.class, null);
+        }
+
+        @SuppressWarnings("rawtypes")
+        @Override
+        public Map<InstanceIdentifier, DataContainer> readUsingPathArgument(final DataContainer parent,
+                final PathArgument childArgument, final InstanceIdentifier builder) {
+            checkArgument(childArgument instanceof Item<?>, "Path Argument must be Item without keys");
+            DataContainer aug = read(parent, childArgument.getType());
+            if (aug != null) {
+                @SuppressWarnings("unchecked")
+                final InstanceIdentifier childPath = builder.child(childArgument.getType());
+                return Collections.singletonMap(childPath, aug);
+            } else {
+                return Collections.emptyMap();
+            }
+        }
+
+        @Override
+        public DataContainer read(final DataContainer parent, final Class<?> childType) {
+            checkArgument(Augmentation.class.isAssignableFrom(childType), "Parent must be Augmentable.");
+            checkArgument(parent instanceof Augmentable<?>, "Parent must be Augmentable.");
+
+            @SuppressWarnings({ "rawtypes", "unchecked" })
+            Augmentation potential = ((Augmentable) parent).getAugmentation(childType);
+            checkState(potential instanceof DataContainer, "Readed augmention must be data object");
+            return (DataContainer) potential;
+        }
+    }
+
+    /**
+     * Create sublist view of child from element on [size-of-parent] position to
+     * last element.
+     *
+     * @param parent
+     * @param child
+     * @return sublist view of child argument
+     * @throws IllegalArgumentException
+     *             if parent argument is bigger than child
+     */
+    private static <P, C> List<C> subList(final Iterable<P> parent, final Iterable<C> child) {
+        Iterator<P> iParent = parent.iterator();
+        List<C> result = new ArrayList<>();
+        for (C arg : child) {
+            if (iParent.hasNext()) {
+                iParent.next();
+            } else {
+                result.add(arg);
+            }
+        }
+        if (iParent.hasNext()) {
+            throw new IllegalArgumentException("Parent argument is bigger than child.");
+        }
+        return result;
+    }
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/LocalNameRpcServiceInvoker.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/LocalNameRpcServiceInvoker.java
new file mode 100644 (file)
index 0000000..3dbce28
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 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.binding.util;
+
+import com.google.common.base.Preconditions;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+
+final class LocalNameRpcServiceInvoker extends AbstractMappedRpcInvoker<String> {
+    private final QNameModule module;
+
+    private LocalNameRpcServiceInvoker(final QNameModule module, final Map<String, Method> map) {
+        super(map);
+        this.module = Preconditions.checkNotNull(module);
+    }
+
+    static RpcServiceInvoker instanceFor(final QNameModule module, final Map<QName, Method> qnameToMethod) {
+        final Map<String, Method> map = new HashMap<>();
+        for (Entry<QName, Method> e : qnameToMethod.entrySet()) {
+            map.put(e.getKey().getLocalName(), e.getValue());
+        }
+
+        return new LocalNameRpcServiceInvoker(module, map);
+    }
+
+    @Override
+    protected String qnameToKey(final QName qname) {
+        if (module.equals(qname.getModule())) {
+            return qname.getLocalName();
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/NotificationListenerInvoker.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/NotificationListenerInvoker.java
new file mode 100644 (file)
index 0000000..3476d34
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * 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.binding.util;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Method;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.NotificationListener;
+import org.opendaylight.yangtools.yang.common.QName;
+
+/**
+ * Provides single method invocation of notificatoin callbacks on supplied instance.
+ *
+ * Notification Listener invoker provides common invocation interface for any subtype of {@link NotificationListener}.
+ * via {@link #invokeNotification(NotificationListener, QName, DataContainer)} method.
+ *
+ */
+public final class NotificationListenerInvoker {
+
+    private static final Lookup LOOKUP = MethodHandles.publicLookup();
+
+    private static final LoadingCache<Class<? extends NotificationListener>, NotificationListenerInvoker> INVOKERS = CacheBuilder
+            .newBuilder().weakKeys()
+            .build(new CacheLoader<Class<? extends NotificationListener>, NotificationListenerInvoker>() {
+
+                @Override
+                public NotificationListenerInvoker load(final Class<? extends NotificationListener> key) throws Exception {
+                    return createInvoker(key);
+                }
+
+            });
+
+    private final Map<QName, MethodHandle> methodInvokers;
+
+    public NotificationListenerInvoker(final Map<QName, MethodHandle> map) {
+        this.methodInvokers = map;
+    }
+
+    /**
+     *
+     * Creates RPCServiceInvoker for specified RpcService type
+     *
+     * @param type
+     *            RpcService interface, which was generated from model.
+     * @return Cached instance of {@link NotificationListenerInvoker} for
+     *         supplied RPC type.
+     *
+     */
+    public static NotificationListenerInvoker from(final Class<? extends NotificationListener> type) {
+        Preconditions.checkArgument(type.isInterface());
+        Preconditions.checkArgument(BindingReflections.isBindingClass(type));
+        return INVOKERS.getUnchecked(type);
+    }
+
+    /**
+     * Invokes supplied RPC on provided implementation of RPC Service.
+     *
+     * @param impl
+     *            Imlementation on which notifiaction callback should be
+     *            invoked.
+     * @param rpcName
+     *            Name of RPC to be invoked.
+     * @param input
+     *            Input data for RPC.
+     *
+     */
+    public void invokeNotification(@Nonnull final NotificationListener impl, @Nonnull final QName rpcName,
+            @Nullable final DataContainer input) {
+        Preconditions.checkNotNull(impl, "implemetation must be supplied");
+        final MethodHandle invoker = methodInvokers.get(rpcName);
+        Preconditions.checkArgument(invoker != null, "Supplied notification is not valid for implementation %s", impl);
+        try {
+            invoker.invokeExact(impl, input);
+        } catch (final Throwable e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+    private static NotificationListenerInvoker createInvoker(final Class<? extends NotificationListener> key) {
+        return new NotificationListenerInvoker(createInvokerMap(key));
+    }
+
+    private static Map<QName, MethodHandle> createInvokerMap(final Class<? extends NotificationListener> key) {
+        final Builder<QName, MethodHandle> ret = ImmutableMap.<QName, MethodHandle>builder();
+        for (final Method method : key.getMethods()) {
+            if (BindingReflections.isNotificationCallback(method)) {
+
+                final Class<?> notification = method.getParameterTypes()[0];
+                final QName name = BindingReflections.findQName(notification);
+                MethodHandle handle;
+                try {
+                    handle = LOOKUP.unreflect(method).asType(
+                            MethodType.methodType(void.class, NotificationListener.class, DataContainer.class));
+                    ret.put(name, handle);
+                } catch (final IllegalAccessException e) {
+                    throw new IllegalStateException("Can not access public method.", e);
+                }
+            }
+
+        }
+        return ret.build();
+    }
+
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/QNameRpcServiceInvoker.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/QNameRpcServiceInvoker.java
new file mode 100644 (file)
index 0000000..82153d4
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2015 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.binding.util;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import org.opendaylight.yangtools.yang.common.QName;
+
+final class QNameRpcServiceInvoker extends AbstractMappedRpcInvoker<QName> {
+    private QNameRpcServiceInvoker(final Map<QName, Method> qnameToMethod) {
+        super(qnameToMethod);
+    }
+
+    static RpcServiceInvoker instanceFor(final Map<QName, Method> qnameToMethod) {
+        return new QNameRpcServiceInvoker(qnameToMethod);
+    }
+
+    @Override
+    protected QName qnameToKey(final QName qname) {
+        return qname;
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcMethodInvoker.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcMethodInvoker.java
new file mode 100644 (file)
index 0000000..466dfaf
--- /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.binding.util;
+
+import com.google.common.base.Optional;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.reflect.Method;
+import java.util.concurrent.Future;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+abstract class RpcMethodInvoker {
+
+    private static final Lookup LOOKUP = MethodHandles.publicLookup();
+
+    protected abstract Future<RpcResult<?>> invokeOn(RpcService impl, DataObject input);
+
+    protected static RpcMethodInvoker from(final Method method) {
+        Optional<Class<? extends DataContainer>> input = BindingReflections.resolveRpcInputClass(method);
+        try {
+            MethodHandle methodHandle = LOOKUP.unreflect(method);
+            if (input.isPresent()) {
+                return new RpcMethodInvokerWithInput(methodHandle);
+            }
+            return new RpcMethodInvokerWithoutInput(methodHandle);
+        } catch (IllegalAccessException e) {
+            throw new IllegalStateException("Lookup on public method failed.",e);
+        }
+
+    }
+}
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcMethodInvokerWithInput.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcMethodInvokerWithInput.java
new file mode 100644 (file)
index 0000000..a77dd35
--- /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.binding.util;
+
+import com.google.common.base.Throwables;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.util.concurrent.Future;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+class RpcMethodInvokerWithInput extends RpcMethodInvoker {
+
+    private static final MethodType INVOCATION_SIGNATURE = MethodType.methodType(Future.class, RpcService.class,DataObject.class);
+    private final MethodHandle handle;
+
+    RpcMethodInvokerWithInput(MethodHandle methodHandle) {
+        this.handle = methodHandle.asType(INVOCATION_SIGNATURE);
+    }
+
+    @Override
+    public Future<RpcResult<?>> invokeOn(RpcService impl, DataObject input) {
+        try {
+            return (Future<RpcResult<?>>) handle.invokeExact(impl,input);
+        } catch (Throwable e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcMethodInvokerWithoutInput.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcMethodInvokerWithoutInput.java
new file mode 100644 (file)
index 0000000..740b98f
--- /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.binding.util;
+
+import com.google.common.base.Throwables;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.util.concurrent.Future;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+class RpcMethodInvokerWithoutInput extends RpcMethodInvoker {
+
+    private static final MethodType INVOCATION_SIGNATURE = MethodType.methodType(Future.class, RpcService.class);
+    private final MethodHandle handle;
+
+    RpcMethodInvokerWithoutInput(MethodHandle methodHandle) {
+        this.handle = methodHandle.asType(INVOCATION_SIGNATURE);
+    }
+
+    @Override
+    public Future<RpcResult<?>> invokeOn(RpcService impl, DataObject input) {
+        try {
+            return (Future<RpcResult<?>>) handle.invokeExact(impl);
+        } catch (Throwable e) {
+            throw Throwables.propagate(e);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcServiceInvoker.java b/yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/RpcServiceInvoker.java
new file mode 100644 (file)
index 0000000..b6b9b47
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.binding.util;
+
+import com.google.common.base.Preconditions;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.Future;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.RpcService;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides single method invocation of RPCs on supplied instance.
+ *
+ * Rpc Service invoker provides common invocation interface for any subtype of {@link RpcService}.
+ * via {@link #invokeRpc(RpcService, QName, DataObject)} method.
+ */
+public abstract class RpcServiceInvoker {
+    private static final Logger LOG = LoggerFactory.getLogger(RpcServiceInvoker.class);
+
+    /**
+     * Creates RPCServiceInvoker for specified RpcService type
+     *
+     * @param type RpcService interface, which was generated from model.
+     * @return Cached instance of {@link RpcServiceInvoker} for supplied RPC type.
+     *
+     */
+    public static RpcServiceInvoker from(final Class<? extends RpcService> type) {
+        return ClassBasedRpcServiceInvoker.instanceFor(type);
+    }
+
+    /**
+     * Creates an RPCServiceInvoker for specified QName-&lt;Method mapping.
+     *
+     * @param qnameToMethod translation mapping, must not be null nor empty.
+     * @return An {@link RpcMethodInvoker} instance.
+     */
+    public static RpcServiceInvoker from(final Map<QName, Method> qnameToMethod) {
+        Preconditions.checkArgument(!qnameToMethod.isEmpty());
+        QNameModule module = null;
+
+        for (QName qname : qnameToMethod.keySet()) {
+            if (module != null) {
+                if (!module.equals(qname.getModule())) {
+                    LOG.debug("QNames from different modules {} and {}, falling back to QName map", module, qname.getModule());
+                    return QNameRpcServiceInvoker.instanceFor(qnameToMethod);
+                }
+            } else {
+                module = qname.getModule();
+            }
+        }
+
+        // All module are equal, which means we can use localName only
+        return LocalNameRpcServiceInvoker.instanceFor(module, qnameToMethod);
+    }
+
+    /**
+     * Invokes supplied RPC on provided implementation of RPC Service.
+     *
+     * @param impl Imlementation on which RPC should be invoked.
+     * @param rpcName Name of RPC to be invoked.
+     * @param input Input data for RPC.
+     * @return Future which will complete once rpc procesing is finished.
+     */
+    public abstract Future<RpcResult<?>> invokeRpc(@Nonnull final RpcService impl, @Nonnull final QName rpcName, @Nullable final DataObject input);
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierTest.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifierTest.java
new file mode 100644 (file)
index 0000000..97ee4fe
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * 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.binding;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.test.mock.FooChild;
+import org.opendaylight.yangtools.yang.binding.test.mock.InstantiatedFoo;
+import org.opendaylight.yangtools.yang.binding.test.mock.Node;
+import org.opendaylight.yangtools.yang.binding.test.mock.NodeChild;
+import org.opendaylight.yangtools.yang.binding.test.mock.NodeChildKey;
+import org.opendaylight.yangtools.yang.binding.test.mock.NodeKey;
+import org.opendaylight.yangtools.yang.binding.test.mock.Nodes;
+
+public class InstanceIdentifierTest {
+
+    @Test
+    public void constructWithPredicates() {
+
+        InstanceIdentifier<Nodes> nodes = InstanceIdentifier.builder(Nodes.class).build();
+
+        assertNotNull(nodes);
+        assertEquals(Nodes.class, nodes.getTargetType());
+
+
+        InstanceIdentifier<Node> node = nodes.builder().child(Node.class).build();
+
+        assertNotNull(node);
+        assertEquals(Node.class, node.getTargetType());
+
+        assertTrue(nodes.contains(node));
+    }
+
+    @Test
+    public void fluentConstruction() {
+
+        InstanceIdentifier<Nodes> nodes = InstanceIdentifier.builder(Nodes.class).build();
+        InstanceIdentifier<Node> node = InstanceIdentifier.builder(Nodes.class).child(Node.class,new NodeKey(10)).build();
+
+        assertNotNull(node);
+        assertEquals(Node.class, node.getTargetType());
+
+        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)).build();
+        InstanceIdentifier<Node> nodeOne = InstanceIdentifier.builder(Nodes.class) //
+                .child(Node.class,new NodeKey(1)).build();
+        InstanceIdentifier<Nodes> nodes = InstanceIdentifier.builder(Nodes.class).build();
+
+        assertFalse(fooChild.contains(nodeTen));
+        assertFalse(nodeTen.contains(nodes));
+
+        assertFalse(nodeOne.contains(nodes));
+        assertTrue(nodes.contains(nodeOne));
+
+        assertTrue(nodes.containsWildcarded(nodeOne));
+        assertFalse(nodeOne.containsWildcarded(nodes));
+    }
+
+    @Test
+    public void containsWildcarded() {
+        InstanceIdentifier<Nodes> nodes = InstanceIdentifier.builder(Nodes.class).build();
+        InstanceIdentifier<Node> wildcarded = InstanceIdentifier.builder(Nodes.class).child(Node.class).build();
+        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)).build();
+        InstanceIdentifier<Node> nodeOne = InstanceIdentifier.builder(Nodes.class) //
+                .child(Node.class,new NodeKey(1)).build();
+
+        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).build();
+
+        assertTrue(nodeTenChildWildcarded.isWildcarded());
+
+        InstanceIdentifier<NodeChild> nodeTenChild = InstanceIdentifier.builder(Nodes.class) //
+                .child(Node.class,new NodeKey(10)).child(NodeChild.class, new NodeChildKey(10)).build();
+        InstanceIdentifier<NodeChild> nodeOneChild = InstanceIdentifier.builder(Nodes.class) //
+                .child(Node.class,new NodeKey(1)).child(NodeChild.class, new NodeChildKey(1)).build();
+
+
+        assertFalse(nodeTenChildWildcarded.containsWildcarded(nodeOneChild));
+        assertTrue(nodeTenChildWildcarded.containsWildcarded(nodeTenChild));
+
+    }
+
+    void childOfTest() {
+        InstanceIdentifier.builder(Nodes.class).child(InstantiatedFoo.class).child(FooChild.class);
+    }
+
+    @Test
+    public void basicTests() {
+        InstanceIdentifier<DataObject> instanceIdentifier1 = InstanceIdentifier.create(DataObject.class);
+        InstanceIdentifier<DataObject> instanceIdentifier2 = InstanceIdentifier.create(DataObject.class);
+        Object object = new Object();
+
+        assertTrue(instanceIdentifier1.equals(instanceIdentifier1));
+        assertFalse(instanceIdentifier1.equals(null));
+        assertFalse(instanceIdentifier1.equals(object));
+        assertTrue(instanceIdentifier1.equals(instanceIdentifier2));
+
+        assertNotNull(instanceIdentifier1.hashCode());
+
+        assertNotNull(instanceIdentifier1.toString());
+    }
+
+    @Test
+    public void firstIdentifierOfTest() {
+        InstanceIdentifier<Node> instanceIdentifier = InstanceIdentifier.builder(Nodes.class).child(Node.class,new NodeKey(10)).build();
+
+        InstanceIdentifier<Nodes> nodesIdentifier = instanceIdentifier.firstIdentifierOf(Nodes.class);
+        assertNotNull(nodesIdentifier);
+        InstanceIdentifier<DataObject> dataObjectIdentifier = instanceIdentifier.firstIdentifierOf(DataObject.class);
+        assertNull(dataObjectIdentifier);
+    }
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/FooChild.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/FooChild.java
new file mode 100644 (file)
index 0000000..bdcbd0a
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * 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.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+
+public interface FooChild extends ChildOf<GroupingFoo> {
+
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/GroupingFoo.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/GroupingFoo.java
new file mode 100644 (file)
index 0000000..f868446
--- /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
+ */
+package org.opendaylight.yangtools.yang.binding.test.mock;
+
+public interface GroupingFoo {
+
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/InstantiatedFoo.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/InstantiatedFoo.java
new file mode 100644 (file)
index 0000000..2e6348e
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * 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.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+public interface InstantiatedFoo extends DataObject, GroupingFoo, ChildOf<Nodes> {
+
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/Node.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/Node.java
new file mode 100644 (file)
index 0000000..71b78f6
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+
+public interface Node extends //
+    DataObject, //
+    Identifiable<NodeKey>, //
+    ChildOf<Nodes> {
+
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeChild.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeChild.java
new file mode 100644 (file)
index 0000000..3b02176
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * 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.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.Identifiable;
+
+public interface NodeChild extends //
+        DataObject, //
+        Identifiable<NodeChildKey>, //
+        ChildOf<Node> {
+
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeChildKey.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeChildKey.java
new file mode 100644 (file)
index 0000000..4c915fb
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+public class NodeChildKey implements //
+        Identifier<NodeChild> {
+       private static final long serialVersionUID = 1L;
+       private final int id;
+
+    public NodeChildKey(int id) {
+        super();
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + id;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        NodeChildKey other = (NodeChildKey) obj;
+        if (id != other.id)
+            return false;
+        return true;
+    }
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeKey.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/NodeKey.java
new file mode 100644 (file)
index 0000000..7b83790
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.Identifier;
+
+public class NodeKey implements //
+        Identifier<Node> {
+       private static final long serialVersionUID = 1L;
+       private final int id;
+
+    public NodeKey(int id) {
+        super();
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + id;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        NodeKey other = (NodeKey) obj;
+        if (id != other.id)
+            return false;
+        return true;
+    }
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/Nodes.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/test/mock/Nodes.java
new file mode 100644 (file)
index 0000000..1bf7e18
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * 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.binding.test.mock;
+
+import org.opendaylight.yangtools.yang.binding.ChildOf;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.DataRoot;
+
+public interface Nodes extends //
+        ChildOf<DataRoot>, //
+        DataObject {
+
+}
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/util/BindingReflectionsTest.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/util/BindingReflectionsTest.java
new file mode 100644 (file)
index 0000000..694c807
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.binding.util;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class BindingReflectionsTest {
+
+    @Test
+    public void testBindingWithDummyObject() {
+        assertEquals("Package name should be equal to string", "org.opendaylight.yang.gen.v1.test.rev990939",
+                BindingReflections.getModelRootPackageName("org.opendaylight.yang.gen.v1.test.rev990939"));
+        assertEquals("ModuleInfoClassName should be equal to string", "test.$YangModuleInfoImpl",
+                BindingReflections.getModuleInfoClassName("test"));
+        assertEquals("Module info should be empty Set", Collections.EMPTY_SET,
+                BindingReflections.loadModuleInfos());
+        assertFalse("Should not be RpcType", BindingReflections.isRpcType(DataObject.class));
+        assertFalse("Should not be AugmentationChild", BindingReflections.isAugmentationChild(DataObject.class));
+        assertTrue("Should be BindingClass", BindingReflections.isBindingClass(DataObject.class));
+        assertFalse("Should not be Notification", BindingReflections.isNotification(DataObject.class));
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/util/DataObjectReadingUtilTest.java b/yang/yang-binding/src/test/java/org/opendaylight/yangtools/yang/binding/util/DataObjectReadingUtilTest.java
new file mode 100644 (file)
index 0000000..29dc602
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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.binding.util;
+
+import com.google.common.collect.ImmutableMap;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.test.mock.Nodes;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.Assert.assertTrue;
+
+public class DataObjectReadingUtilTest {
+    @Mock private InstanceIdentifier<? extends DataObject> pathNull;
+    @Mock private Map.Entry<InstanceIdentifier<? extends DataObject>, DataObject> entryNull;
+    @Mock private DataObject mockedDataObject;
+    private InstanceIdentifier<? extends DataObject> path;
+    private Map.Entry<InstanceIdentifier<? extends DataObject>, DataObject> entry;
+
+    @Before
+    public void setup() {
+        MockitoAnnotations.initMocks(this);
+
+        path = InstanceIdentifier.builder(Nodes.class).build();
+        ImmutableMap map = ImmutableMap.<InstanceIdentifier<? extends DataObject>,
+                DataObject>builder().put(path, mockedDataObject).build();
+
+        Set entries = map.entrySet();
+        Iterator it = entries.iterator();
+        while(it.hasNext()) {
+            entry = (Map.Entry)it.next();
+        }
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testReadDataParentNull() {
+        DataObjectReadingUtil.readData(entryNull.getValue(), (InstanceIdentifier) entryNull.getKey(), pathNull);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testReadDataParentPathNull() {
+        DataObjectReadingUtil.readData(entry.getValue(), (InstanceIdentifier) entryNull.getKey(), pathNull);
+    }
+
+    @Test
+    public void testReadDataWithThreeParams() {
+        assertTrue("Check if contains key",
+                DataObjectReadingUtil.readData(entry.getValue(),
+                        (InstanceIdentifier) entry.getKey(), path).containsKey(entry.getKey()));
+
+        assertTrue("Check if contains value",
+                DataObjectReadingUtil.readData(entry.getValue(),
+                        (InstanceIdentifier) entry.getKey(), path).containsValue(entry.getValue()));
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testReadDataWithTwoParams() {
+        DataObjectReadingUtil.readData(mockedDataObject, DataObject.class);
+    }
+}
\ No newline at end of file