X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fsal%2Fyang-prototype%2Fcode-generator%2Fbinding-generator-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Fbinding%2Fyang%2Ftypes%2FTypeProviderImpl.java;h=7e6f93f9fb250473f1b7dd7ae57e32916abec837;hp=30207cc776cec82d22e829b0933e5c023d11665a;hb=e0e2b9f77ecf0bf2353dba9a448e1901194648d3;hpb=b571c5f3e6e9b2dcf2cff2314537c7b1c61533b4 diff --git a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/TypeProviderImpl.java b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/TypeProviderImpl.java index 30207cc776..7e6f93f9fb 100644 --- a/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/TypeProviderImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/binding-generator-impl/src/main/java/org/opendaylight/controller/sal/binding/yang/types/TypeProviderImpl.java @@ -7,17 +7,19 @@ */ package org.opendaylight.controller.sal.binding.yang.types; -import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findDataSchemaNode; -import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath; -import static org.opendaylight.controller.yang.model.util.SchemaContextUtil.resolveModuleFromSchemaPath; +import static org.opendaylight.controller.binding.generator.util.BindingGeneratorUtil.*; +import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.*; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.TreeMap; -import org.opendaylight.controller.binding.generator.util.BindingGeneratorUtil; +import org.apache.commons.lang.StringEscapeUtils; +import org.opendaylight.controller.binding.generator.util.ReferencedTypeImpl; +import org.opendaylight.controller.binding.generator.util.TypeConstants; import org.opendaylight.controller.binding.generator.util.Types; import org.opendaylight.controller.binding.generator.util.generated.type.builder.EnumerationBuilderImpl; import org.opendaylight.controller.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl; @@ -29,25 +31,33 @@ import org.opendaylight.controller.sal.binding.model.api.type.builder.EnumBuilde import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedPropertyBuilder; import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTOBuilder; import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTypeBuilder; -import org.opendaylight.controller.yang.model.api.DataSchemaNode; -import org.opendaylight.controller.yang.model.api.LeafListSchemaNode; -import org.opendaylight.controller.yang.model.api.LeafSchemaNode; -import org.opendaylight.controller.yang.model.api.Module; -import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; -import org.opendaylight.controller.yang.model.api.SchemaContext; -import org.opendaylight.controller.yang.model.api.TypeDefinition; -import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair; -import org.opendaylight.controller.yang.model.api.type.IdentityrefTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition; -import org.opendaylight.controller.yang.model.api.type.UnionTypeDefinition; -import org.opendaylight.controller.yang.model.util.ExtendedType; - -public class TypeProviderImpl implements TypeProvider { +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.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.SchemaPath; +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.BitsTypeDefinition.Bit; +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.api.type.IdentityrefTypeDefinition; +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.UnionTypeDefinition; +import org.opendaylight.yangtools.yang.model.util.ExtendedType; +import org.opendaylight.yangtools.yang.model.util.StringType; +import org.opendaylight.yangtools.yang.model.util.UnionType; + +public final class TypeProviderImpl implements TypeProvider { private final SchemaContext schemaContext; - private Map> genTypeDefsContextMap; - private final List allTypeDefinitions; + private Map> genTypeDefsContextMap; + private final Map referencedTypes; public TypeProviderImpl(final SchemaContext schemaContext) { if (schemaContext == null) { @@ -55,128 +65,191 @@ public class TypeProviderImpl implements TypeProvider { } this.schemaContext = schemaContext; - this.genTypeDefsContextMap = new HashMap>(); - allTypeDefinitions = resolveTypeDefsFromContext(); + this.genTypeDefsContextMap = new HashMap<>(); + this.referencedTypes = new HashMap<>(); + resolveTypeDefsFromContext(); } - public List getGeneratedTypeDefs() { - return allTypeDefinitions; + public void putReferencedType(final SchemaPath refTypePath, final Type refType) { + if (refTypePath == null) { + throw new IllegalArgumentException("Path reference of " + "Enumeration Type Definition cannot be NULL!"); + } + + if (refType == null) { + throw new IllegalArgumentException("Reference to Enumeration " + "Type cannot be NULL!"); + } + referencedTypes.put(refTypePath, refType); } /* * (non-Javadoc) - * + * * @see org.opendaylight.controller.yang.model.type.provider.TypeProvider# * javaTypeForYangType(java.lang.String) */ @Override public Type javaTypeForYangType(String type) { - Type t = BaseYangTypes.BASE_YANG_TYPES_PROVIDER - .javaTypeForYangType(type); + Type t = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(type); return t; } @Override - public Type javaTypeForSchemaDefinitionType( - final TypeDefinition typeDefinition) { + public Type javaTypeForSchemaDefinitionType(final TypeDefinition typeDefinition) { Type returnType = null; - if (typeDefinition != null) { - final String typedefName = typeDefinition.getQName().getLocalName(); - if (typeDefinition instanceof ExtendedType) { - final TypeDefinition baseTypeDef = baseTypeDefForExtendedType(typeDefinition); - - if (baseTypeDef instanceof LeafrefTypeDefinition) { - final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) baseTypeDef; - returnType = provideTypeForLeafref(leafref); - } else if (baseTypeDef instanceof IdentityrefTypeDefinition) { - - } else if (baseTypeDef instanceof EnumTypeDefinition) { - final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDef; - returnType = resolveEnumFromTypeDefinition(enumTypeDef, - typedefName); - } else { - final Module module = resolveModuleFromSchemaPath(schemaContext, typeDefinition - .getPath()); - - if (module != null) { - final Map genTOs = genTypeDefsContextMap - .get(module.getName()); - if (genTOs != null) { - returnType = genTOs.get(typedefName); - } + if (typeDefinition == null) { + throw new IllegalArgumentException("Type Definition cannot be NULL!"); + } + if (typeDefinition.getQName() == null) { + throw new IllegalArgumentException( + "Type Definition cannot have non specified QName (QName cannot be NULL!)"); + } + if (typeDefinition.getQName().getLocalName() == null) { + throw new IllegalArgumentException("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) { + final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) baseTypeDef; + returnType = provideTypeForLeafref(leafref); + } else if (baseTypeDef instanceof IdentityrefTypeDefinition) { + final IdentityrefTypeDefinition idref = (IdentityrefTypeDefinition) baseTypeDef; + returnType = returnTypeForIdentityref(idref); + } else if (baseTypeDef instanceof EnumTypeDefinition) { + final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDef; + returnType = resolveEnumFromTypeDefinition(enumTypeDef, typedefName); + } else { + final Module module = findParentModuleForTypeDefinition(schemaContext, typeDefinition); + if (module != null) { + final Map genTOs = genTypeDefsContextMap.get(module.getName()); + if (genTOs != null) { + returnType = genTOs.get(typedefName); + } + if (returnType == null) { + returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER + .javaTypeForSchemaDefinitionType(baseTypeDef); } } + } + } else { + if (typeDefinition instanceof LeafrefTypeDefinition) { + final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition; + returnType = provideTypeForLeafref(leafref); + } else if (typeDefinition instanceof IdentityrefTypeDefinition) { + final IdentityrefTypeDefinition idref = (IdentityrefTypeDefinition) typeDefinition; + returnType = returnTypeForIdentityref(idref); } else { - if (typeDefinition instanceof LeafrefTypeDefinition) { - final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition; - returnType = provideTypeForLeafref(leafref); - } else if (typeDefinition instanceof EnumTypeDefinition) { - final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDefinition; - returnType = resolveEnumFromTypeDefinition(enumTypeDef, - typedefName); - } else if (typeDefinition instanceof IdentityrefTypeDefinition) { - - } else { - returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER - .javaTypeForSchemaDefinitionType(typeDefinition); - } + returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition); } } + // TODO: add throw exception when we will be able to resolve ALL yang + // types! + // if (returnType == null) { + // throw new IllegalArgumentException("Type Provider can't resolve " + + // "type for specified Type Definition " + typedefName); + // } return returnType; } - private TypeDefinition baseTypeDefForExtendedType( - final TypeDefinition extendTypeDef) { - if (extendTypeDef != null) { - final TypeDefinition baseTypeDef = extendTypeDef.getBaseType(); - if (baseTypeDef instanceof ExtendedType) { - return baseTypeDefForExtendedType(baseTypeDef); - } else { - return baseTypeDef; + private Type returnTypeForIdentityref(IdentityrefTypeDefinition idref) { + QName baseIdQName = idref.getIdentity(); + Module module = schemaContext.findModuleByNamespace(baseIdQName.getNamespace()); + IdentitySchemaNode identity = null; + for (IdentitySchemaNode id : module.getIdentities()) { + if (id.getQName().equals(baseIdQName)) { + identity = id; } } - return null; + if (identity == null) { + throw new IllegalArgumentException("Target identity '" + baseIdQName + "' do not exists"); + } + + final String basePackageName = moduleNamespaceToPackageName(module); + final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath()); + final String genTypeName = parseToClassName(identity.getQName().getLocalName()); + + Type baseType = Types.typeForClass(Class.class); + Type paramType = Types.wildcardTypeFor(packageName, genTypeName); + Type returnType = Types.parameterizedTypeFor(baseType, paramType); + return returnType; } - public Type baseTypeForExtendedType(final TypeDefinition typeDefinition) { + public Type generatedTypeForExtendedDefinitionType(final TypeDefinition typeDefinition) { Type returnType = null; - if (typeDefinition != null) { - final TypeDefinition baseTypeDefinition = baseTypeDefForExtendedType(typeDefinition); + if (typeDefinition == null) { + throw new IllegalArgumentException("Type Definition cannot be NULL!"); + } + if (typeDefinition.getQName() == null) { + throw new IllegalArgumentException( + "Type Definition cannot have non specified QName (QName cannot be NULL!)"); + } + if (typeDefinition.getQName() == null) { + throw new IllegalArgumentException("Type Definitions Local Name cannot be NULL!"); + } - if (baseTypeDefinition instanceof EnumTypeDefinition) { - final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDefinition; - final String enumName = enumTypeDef.getQName().getLocalName(); - return resolveEnumFromTypeDefinition(enumTypeDef, enumName); - } else { - returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER - .javaTypeForSchemaDefinitionType(typeDefinition); + 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 = findParentModuleForTypeDefinition(schemaContext, typeDefinition); + + if (module != null) { + final Map genTOs = genTypeDefsContextMap.get(module.getName()); + if (genTOs != null) { + returnType = genTOs.get(typedefName); + } + } } } return returnType; } + private TypeDefinition baseTypeDefForExtendedType(final TypeDefinition extendTypeDef) { + if (extendTypeDef == null) { + throw new IllegalArgumentException("Type Definiition reference cannot be NULL!"); + } + final TypeDefinition baseTypeDef = extendTypeDef.getBaseType(); + if (baseTypeDef instanceof ExtendedType) { + return baseTypeDefForExtendedType(baseTypeDef); + } else { + return baseTypeDef; + } + + } + public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType) { Type returnType = null; - if ((leafrefType != null) && (leafrefType.getPathStatement() != null) - && (leafrefType.getPath() != null)) { + if (leafrefType == null) { + throw new IllegalArgumentException("Leafref Type Definition reference cannot be NULL!"); + } - final RevisionAwareXPath xpath = leafrefType.getPathStatement(); - final String strXPath = xpath.toString(); + if (leafrefType.getPathStatement() == null) { + throw new IllegalArgumentException("The Path Statement for Leafref Type Definition cannot be NULL!"); + } - if (strXPath != null) { - if (strXPath.matches(".*//[.* | .*//].*")) { - returnType = Types.typeForClass(Object.class); - } else { - final Module module = resolveModuleFromSchemaPath(schemaContext, leafrefType.getPath()); - if (module != null) { - final DataSchemaNode dataNode; - if (xpath.isAbsolute()) { - dataNode = findDataSchemaNode(schemaContext, - module, xpath); - } else { - dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, - leafrefType, xpath); - } + final RevisionAwareXPath xpath = leafrefType.getPathStatement(); + final String strXPath = xpath.toString(); + + if (strXPath != null) { + if (strXPath.contains("[")) { + returnType = Types.typeForClass(Object.class); + } else { + final Module module = findParentModuleForTypeDefinition(schemaContext, leafrefType); + if (module != null) { + final DataSchemaNode dataNode; + if (xpath.isAbsolute()) { + dataNode = findDataSchemaNode(schemaContext, module, xpath); + } else { + dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, leafrefType, xpath); + } + + if (leafContainsEnumDefinition(dataNode)) { + returnType = referencedTypes.get(dataNode.getPath()); + } else if (leafListContainsEnumDefinition(dataNode)) { + returnType = Types.listTypeFor(referencedTypes.get(dataNode.getPath())); + } else { returnType = resolveTypeFromDataSchemaNode(dataNode); } } @@ -185,82 +258,95 @@ public class TypeProviderImpl implements TypeProvider { return returnType; } - private EnumBuilder resolveEnumFromTypeDefinition( - final EnumTypeDefinition enumTypeDef, final String enumName, - final GeneratedTypeBuilder typeBuilder) { - if ((enumTypeDef != null) && (typeBuilder != null) - && (enumTypeDef.getQName() != null) - && (enumTypeDef.getQName().getLocalName() != null)) { - - final String enumerationName = BindingGeneratorUtil - .parseToClassName(enumName); - final EnumBuilder enumBuilder = typeBuilder - .addEnumeration(enumerationName); - - if (enumBuilder != null) { - final List enums = enumTypeDef.getValues(); - if (enums != null) { - int listIndex = 0; - for (final EnumPair enumPair : enums) { - if (enumPair != null) { - final String enumPairName = BindingGeneratorUtil - .parseToClassName(enumPair.getName()); - Integer enumPairValue = enumPair.getValue(); - - if (enumPairValue == null) { - enumPairValue = listIndex; - } - enumBuilder.addValue(enumPairName, enumPairValue); - listIndex++; - } - } - } - return enumBuilder; + private boolean leafContainsEnumDefinition(final DataSchemaNode dataNode) { + if (dataNode instanceof LeafSchemaNode) { + final LeafSchemaNode leaf = (LeafSchemaNode) dataNode; + if (leaf.getType() instanceof EnumTypeDefinition) { + return true; } } - return null; + return false; } - private Enumeration resolveEnumFromTypeDefinition( - final EnumTypeDefinition enumTypeDef, final String enumName) { - if ((enumTypeDef != null) && (enumTypeDef.getQName() != null) - && (enumTypeDef.getQName().getLocalName() != null)) { - - final String enumerationName = BindingGeneratorUtil - .parseToClassName(enumName); - - Module module = resolveModuleFromSchemaPath(schemaContext, enumTypeDef.getPath()); - final String basePackageName = BindingGeneratorUtil - .moduleNamespaceToPackageName(module); - final String packageName = BindingGeneratorUtil - .packageNameForGeneratedType(basePackageName, - enumTypeDef.getPath()); - - final EnumBuilder enumBuilder = new EnumerationBuilderImpl( - packageName, enumerationName); - - if (enumBuilder != null) { - final List enums = enumTypeDef.getValues(); - if (enums != null) { - int listIndex = 0; - for (final EnumPair enumPair : enums) { - if (enumPair != null) { - final String enumPairName = BindingGeneratorUtil - .parseToClassName(enumPair.getName()); - Integer enumPairValue = enumPair.getValue(); - - if (enumPairValue == null) { - enumPairValue = listIndex; - } - enumBuilder.addValue(enumPairName, enumPairValue); - listIndex++; + private boolean leafListContainsEnumDefinition(final DataSchemaNode dataNode) { + if (dataNode instanceof LeafListSchemaNode) { + final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode; + if (leafList.getType() instanceof EnumTypeDefinition) { + return true; + } + } + return false; + } + + private Enumeration resolveEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final String enumName) { + if (enumTypeDef == null) { + throw new IllegalArgumentException("EnumTypeDefinition reference cannot be NULL!"); + } + if (enumTypeDef.getValues() == null) { + throw new IllegalArgumentException("EnumTypeDefinition MUST contain at least ONE value definition!"); + } + if (enumTypeDef.getQName() == null) { + throw new IllegalArgumentException("EnumTypeDefinition MUST contain NON-NULL QName!"); + } + if (enumTypeDef.getQName().getLocalName() == null) { + throw new IllegalArgumentException("Local Name in EnumTypeDefinition QName cannot be NULL!"); + } + + final String enumerationName = parseToClassName(enumName); + + Module module = findParentModuleForTypeDefinition(schemaContext, enumTypeDef); + final String basePackageName = moduleNamespaceToPackageName(module); + + final EnumBuilder enumBuilder = new EnumerationBuilderImpl(basePackageName, enumerationName); + updateEnumPairsFromEnumTypeDef(enumTypeDef, enumBuilder); + return enumBuilder.toInstance(null); + } + + private EnumBuilder resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final String enumName, + final GeneratedTypeBuilder typeBuilder) { + if (enumTypeDef == null) { + throw new IllegalArgumentException("EnumTypeDefinition reference cannot be NULL!"); + } + if (enumTypeDef.getValues() == null) { + throw new IllegalArgumentException("EnumTypeDefinition MUST contain at least ONE value definition!"); + } + if (enumTypeDef.getQName() == null) { + throw new IllegalArgumentException("EnumTypeDefinition MUST contain NON-NULL QName!"); + } + if (enumTypeDef.getQName().getLocalName() == null) { + throw new IllegalArgumentException("Local Name in EnumTypeDefinition QName cannot be NULL!"); + } + if (typeBuilder == null) { + throw new IllegalArgumentException("Generated Type Builder reference cannot be NULL!"); + } + + final String enumerationName = parseToClassName(enumName); + final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName); + + updateEnumPairsFromEnumTypeDef(enumTypeDef, enumBuilder); + + return enumBuilder; + } + + private void updateEnumPairsFromEnumTypeDef(final EnumTypeDefinition enumTypeDef, final EnumBuilder enumBuilder) { + if (enumBuilder != null) { + final List enums = enumTypeDef.getValues(); + if (enums != null) { + int listIndex = 0; + for (final EnumPair enumPair : enums) { + if (enumPair != null) { + final String enumPairName = parseToClassName(enumPair.getName()); + Integer enumPairValue = enumPair.getValue(); + + if (enumPairValue == null) { + enumPairValue = listIndex; } + enumBuilder.addValue(enumPairName, enumPairValue); + listIndex++; } } - return enumBuilder.toInstance(null); } } - return null; } private Type resolveTypeFromDataSchemaNode(final DataSchemaNode dataNode) { @@ -277,149 +363,381 @@ public class TypeProviderImpl implements TypeProvider { return returnType; } - private List resolveTypeDefsFromContext() { - final List genTypeDefs = new ArrayList(); + private void resolveTypeDefsFromContext() { final Set modules = schemaContext.getModules(); - if (modules != null) { - for (final Module module : modules) { - if (module != null) { - final String moduleName = module.getName(); - final String basePackageName = BindingGeneratorUtil - .moduleNamespaceToPackageName(module); - - final Set> typeDefinitions = module - .getTypeDefinitions(); - - if ((typeDefinitions != null) && (basePackageName != null)) { - for (final TypeDefinition typedef : typeDefinitions) { - final GeneratedTransferObject genTransObj = toGeneratedTransferObject( - basePackageName, moduleName, typedef); - if (genTransObj != null) { - genTypeDefs.add(genTransObj); - } - } - // for (final TypeDefinition typedef : - // typeDefinitions) { - // addUnionGeneratedTypeDefinition(basePackageName, - // module.getName(), typedef); - // } - } + if (modules == null) { + throw new IllegalArgumentException("Sef of Modules cannot be NULL!"); + } + for (final Module module : modules) { + if (module == null) { + continue; + } + final String moduleName = module.getName(); + final String basePackageName = moduleNamespaceToPackageName(module); + + final Set> typeDefinitions = module.getTypeDefinitions(); + final List> listTypeDefinitions = sortTypeDefinitionAccordingDepth(typeDefinitions); + + final Map typeMap = new HashMap<>(); + genTypeDefsContextMap.put(moduleName, typeMap); + + if ((listTypeDefinitions != null) && (basePackageName != null)) { + for (final TypeDefinition typedef : listTypeDefinitions) { + typedefToGeneratedType(basePackageName, moduleName, typedef); } } } - return genTypeDefs; } - private GeneratedTransferObject toGeneratedTransferObject( - final String basePackageName, final String moduleName, + private Type typedefToGeneratedType(final String basePackageName, final String moduleName, final TypeDefinition typedef) { - if ((basePackageName != null) && (moduleName != null) - && (typedef != null) && (typedef.getQName() != null)) { - final GeneratedTOBuilder genTOBuilder = typedefToTransferObject( - basePackageName, typedef); + if ((basePackageName != null) && (moduleName != null) && (typedef != null) && (typedef.getQName() != null)) { final String typedefName = typedef.getQName().getLocalName(); - final String propertyName = BindingGeneratorUtil - .parseToValidParamName(typedefName); - - final TypeDefinition baseTypeDefinition = baseTypeDefForExtendedType(typedef); - if (!(baseTypeDefinition instanceof LeafrefTypeDefinition) - && !(baseTypeDefinition instanceof IdentityrefTypeDefinition)) { + final TypeDefinition innerTypeDefinition = typedef.getBaseType(); + if (!(innerTypeDefinition instanceof LeafrefTypeDefinition) + && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) { Type returnType = null; - if (baseTypeDefinition instanceof EnumTypeDefinition) { - final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDefinition; - returnType = resolveEnumFromTypeDefinition(enumTypeDef, + if (innerTypeDefinition instanceof ExtendedType) { + ExtendedType extendedTypeDef = (ExtendedType) innerTypeDefinition; + returnType = resolveExtendedTypeFromTypeDef(extendedTypeDef, basePackageName, typedefName, + moduleName); + } else if (innerTypeDefinition instanceof UnionTypeDefinition) { + final GeneratedTOBuilder genTOBuilder = addUnionGeneratedTypeDefinition(basePackageName, typedef, typedefName); + returnType = genTOBuilder.toInstance(); + } else if (innerTypeDefinition instanceof EnumTypeDefinition) { + final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypeDefinition; + returnType = resolveEnumFromTypeDefinition(enumTypeDef, typedefName); + + } else if (innerTypeDefinition instanceof BitsTypeDefinition) { + final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition; + final GeneratedTOBuilder genTOBuilder = bitsTypedefToTransferObject(basePackageName, + bitsTypeDefinition, typedefName); + returnType = genTOBuilder.toInstance(); + } else { - returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER - .javaTypeForSchemaDefinitionType(baseTypeDefinition); - } + final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER + .javaTypeForSchemaDefinitionType(innerTypeDefinition); + returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType); + } if (returnType != null) { - final GeneratedPropertyBuilder genPropBuilder = genTOBuilder - .addProperty(propertyName); - - genPropBuilder.addReturnType(returnType); - genTOBuilder.addEqualsIdentity(genPropBuilder); - genTOBuilder.addHashIdentity(genPropBuilder); - genTOBuilder.addToStringProperty(genPropBuilder); - - Map transferObjectsMap = genTypeDefsContextMap - .get(moduleName); - if (transferObjectsMap == null) { - transferObjectsMap = new HashMap(); - genTypeDefsContextMap.put(moduleName, - transferObjectsMap); + final Map typeMap = genTypeDefsContextMap.get(moduleName); + if (typeMap != null) { + typeMap.put(typedefName, returnType); } + return returnType; + } + } + } + return null; + } - final GeneratedTransferObject transferObject = genTOBuilder - .toInstance(); - if (transferObject != null) { - transferObjectsMap.put(typedefName, transferObject); - return transferObject; - } + private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition typedef, + final Type javaType) { + if (javaType != null) { + final String typedefName = typedef.getQName().getLocalName(); + final String propertyName = parseToValidParamName(typedefName); + + final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef); + + final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(propertyName); + + genPropBuilder.setReturnType(javaType); + genTOBuilder.addEqualsIdentity(genPropBuilder); + genTOBuilder.addHashIdentity(genPropBuilder); + genTOBuilder.addToStringProperty(genPropBuilder); + if (javaType == BaseYangTypes.STRING_TYPE) { + if (typedef instanceof ExtendedType) { + final List regExps = resolveRegExpressionsFromTypedef((ExtendedType) typedef); + addStringRegExAsConstant(genTOBuilder, regExps); } } + return genTOBuilder.toInstance(); } return null; } - private void addUnionGeneratedTypeDefinition(final String basePackageName, - final String moduleName, final TypeDefinition typedef) { - if ((basePackageName != null) && (moduleName != null) - && (typedef != null) && (typedef.getQName() != null)) { - final TypeDefinition baseTypeDefinition = baseTypeDefForExtendedType(typedef); - - if ((baseTypeDefinition != null) - && (baseTypeDefinition instanceof UnionTypeDefinition)) { - final UnionTypeDefinition unionTypeDef = (UnionTypeDefinition) baseTypeDefinition; - - final List> unionTypes = unionTypeDef - .getTypes(); - final Map genTOsMap = genTypeDefsContextMap - .get(moduleName); - final GeneratedTOBuilder unionGenTransObject = typedefToTransferObject( - basePackageName, typedef); - if ((unionTypes != null) && (genTOsMap != null) - && (unionGenTransObject != null)) { - for (final TypeDefinition unionType : unionTypes) { - final String typeName = unionType.getQName() - .getLocalName(); - final GeneratedTransferObject genTransferObject = genTOsMap - .get(typeName); + public GeneratedTOBuilder addUnionGeneratedTypeDefinition(final String basePackageName, + final TypeDefinition typedef, String typeDefName) { + if (basePackageName == null) { + throw new IllegalArgumentException("Base Package Name cannot be NULL!"); + } + if (typedef == null) { + throw new IllegalArgumentException("Type Definition cannot be NULL!"); + } + if (typedef.getQName() == null) { + throw new IllegalArgumentException( + "Type Definition cannot have non specified QName (QName cannot be NULL!)"); + } + + final TypeDefinition baseTypeDefinition = typedef.getBaseType(); + if ((baseTypeDefinition != null) && (baseTypeDefinition instanceof UnionTypeDefinition)) { + final Module parentModule = findParentModuleForTypeDefinition(schemaContext, typedef); + final UnionTypeDefinition unionTypeDef = (UnionTypeDefinition) baseTypeDefinition; + final List> unionTypes = unionTypeDef.getTypes(); + Map genTOsMap = null; + if (parentModule != null && parentModule.getName() != null) { + genTOsMap = genTypeDefsContextMap.get(parentModule.getName()); + } + + final GeneratedTOBuilder unionGenTransObject; + if (typeDefName != null && !typeDefName.isEmpty()) { + final String typeName = parseToClassName(typeDefName); + unionGenTransObject = new GeneratedTOBuilderImpl(basePackageName, typeName); + } else { + unionGenTransObject = typedefToTransferObject(basePackageName, typedef); + } + unionGenTransObject.setIsUnion(true); + + final List regularExpressions = new ArrayList(); + for (final TypeDefinition unionType : unionTypes) { + final String typeName = unionType.getQName().getLocalName(); + if (unionType instanceof ExtendedType) { + final Module unionTypeModule = findParentModuleForTypeDefinition(schemaContext, unionType); + if (unionTypeModule != null && unionTypeModule.getName() != null) { + final Map innerGenTOs = genTypeDefsContextMap.get(unionTypeModule.getName()); + Type genTransferObject = null; + if (innerGenTOs != null) { + genTransferObject = innerGenTOs.get(typeName); + } if (genTransferObject != null) { - unionGenTransObject - .addProperty( - BindingGeneratorUtil - .parseToValidParamName(genTransferObject - .getName())) - .addReturnType(genTransferObject); + updateUnionTypeAsProperty(unionGenTransObject, genTransferObject, + genTransferObject.getName()); + } else { + final TypeDefinition baseType = baseTypeDefForExtendedType(unionType); + if (typeName.equals(baseType.getQName().getLocalName())) { + final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER + .javaTypeForSchemaDefinitionType(baseType); + if (javaType != null) { + updateUnionTypeAsProperty(unionGenTransObject, javaType, typeName); + } + } + if (baseType instanceof StringType) { + regularExpressions.addAll(resolveRegExpressionsFromTypedef((ExtendedType) unionType)); + } } } - genTOsMap.put(unionTypeDef.getQName().getLocalName(), - unionGenTransObject.toInstance()); + } else if (unionType instanceof EnumTypeDefinition) { + final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition((EnumTypeDefinition) unionType, + typeName, unionGenTransObject); + final Type enumRefType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName()); + updateUnionTypeAsProperty(unionGenTransObject, enumRefType, typeName); + } else { + final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER + .javaTypeForSchemaDefinitionType(unionType); + if (javaType != null) { + updateUnionTypeAsProperty(unionGenTransObject, javaType, typeName); + } + } + } + if (!regularExpressions.isEmpty()) { + addStringRegExAsConstant(unionGenTransObject, regularExpressions); + } + + genTOsMap.put(typedef.getQName().getLocalName(), unionGenTransObject.toInstance()); + return unionGenTransObject; + } + return null; + } + + private void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type, + final String propertyName) { + if (unionGenTransObject != null && type != null) { + if (!unionGenTransObject.containsProperty(propertyName)) { + final GeneratedPropertyBuilder propBuilder = unionGenTransObject + .addProperty(parseToValidParamName(propertyName)); + propBuilder.setReturnType(type); + + if (!(type instanceof Enumeration)) { + unionGenTransObject.addEqualsIdentity(propBuilder); + unionGenTransObject.addHashIdentity(propBuilder); + unionGenTransObject.addToStringProperty(propBuilder); } } } } - private GeneratedTOBuilder typedefToTransferObject( - final String basePackageName, final TypeDefinition typedef) { + private GeneratedTOBuilder typedefToTransferObject(final String basePackageName, final TypeDefinition typedef) { - final String packageName = BindingGeneratorUtil - .packageNameForGeneratedType(basePackageName, typedef.getPath()); + final String packageName = packageNameForGeneratedType(basePackageName, typedef.getPath()); final String typeDefTOName = typedef.getQName().getLocalName(); - if ((packageName != null) && (typedef != null) - && (typeDefTOName != null)) { - final String genTOName = BindingGeneratorUtil - .parseToClassName(typeDefTOName); - final GeneratedTOBuilder newType = new GeneratedTOBuilderImpl( - packageName, genTOName); + if ((packageName != null) && (typedef != null) && (typeDefTOName != null)) { + final String genTOName = parseToClassName(typeDefTOName); + final GeneratedTOBuilder newType = new GeneratedTOBuilderImpl(packageName, genTOName); return newType; } return null; } + + public GeneratedTOBuilder bitsTypedefToTransferObject(final String basePackageName, + final TypeDefinition typeDef, String typeDefName) { + + if (typeDef == null) { + throw new IllegalArgumentException("typeDef cannot be NULL!"); + } + if (basePackageName == null) { + throw new IllegalArgumentException("Base Package Name cannot be NULL!"); + } + + if (typeDef instanceof BitsTypeDefinition) { + BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef; + + final String typeName = parseToClassName(typeDefName); + final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName); + + final List bitList = bitsTypeDefinition.getBits(); + GeneratedPropertyBuilder genPropertyBuilder; + for (final Bit bit : bitList) { + String name = bit.getName(); + genPropertyBuilder = genTOBuilder.addProperty(parseToValidParamName(name)); + genPropertyBuilder.setReadOnly(false); + genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE); + + genTOBuilder.addEqualsIdentity(genPropertyBuilder); + genTOBuilder.addHashIdentity(genPropertyBuilder); + genTOBuilder.addToStringProperty(genPropertyBuilder); + } + + return genTOBuilder; + } + return null; + } + + private List resolveRegExpressionsFromTypedef(ExtendedType typedef) { + final List regExps = new ArrayList(); + if (typedef == null) { + throw new IllegalArgumentException("typedef can't be null"); + } + final TypeDefinition strTypeDef = baseTypeDefForExtendedType(typedef); + if (strTypeDef instanceof StringType) { + final List patternConstraints = typedef.getPatterns(); + if (!patternConstraints.isEmpty()) { + String regEx; + String modifiedRegEx; + for (PatternConstraint patternConstraint : patternConstraints) { + regEx = patternConstraint.getRegularExpression(); + modifiedRegEx = StringEscapeUtils.escapeJava(regEx); + regExps.add(modifiedRegEx); + } + } + } + return regExps; + } + + private void addStringRegExAsConstant(GeneratedTOBuilder genTOBuilder, List regularExpressions) { + if (genTOBuilder == null) + throw new IllegalArgumentException("genTOBuilder can't be null"); + if (regularExpressions == null) + throw new IllegalArgumentException("regularExpressions can't be null"); + + if (!regularExpressions.isEmpty()) { + genTOBuilder.addConstant(Types.listTypeFor(BaseYangTypes.STRING_TYPE), TypeConstants.PATTERN_CONSTANT_NAME, + regularExpressions); + } + } + + private GeneratedTransferObject resolveExtendedTypeFromTypeDef(final ExtendedType extendedType, + final String basePackageName, final String typedefName, final String moduleName) { + + if (extendedType == null) { + throw new IllegalArgumentException("Extended type cannot be NULL!"); + } + if (basePackageName == null) { + throw new IllegalArgumentException("String with base package name cannot be NULL!"); + } + if (typedefName == null) { + throw new IllegalArgumentException("String with type definition name cannot be NULL!"); + } + + final String typeDefName = parseToClassName(typedefName); + final String lowTypeDef = extendedType.getQName().getLocalName(); + final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName); + + final Map typeMap = genTypeDefsContextMap.get(moduleName); + if (typeMap != null) { + Type type = typeMap.get(lowTypeDef); + if (type instanceof GeneratedTransferObject) { + genTOBuilder.setExtendsType((GeneratedTransferObject) type); + } + } + + return genTOBuilder.toInstance(); + } + + /** + * The method find 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 + * represents list of type definitions + * @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> sortTypeDefinitionAccordingDepth( + final Set> unsortedTypeDefinitions) { + List> sortedTypeDefinition = new ArrayList<>(); + + Map>> typeDefinitionsDepths = new TreeMap<>(); + for (TypeDefinition unsortedTypeDefinition : unsortedTypeDefinitions) { + final int depth = getTypeDefinitionDepth(unsortedTypeDefinition); + List> typeDefinitionsConcreteDepth = typeDefinitionsDepths.get(depth); + if (typeDefinitionsConcreteDepth == null) { + typeDefinitionsConcreteDepth = new ArrayList>(); + typeDefinitionsDepths.put(depth, typeDefinitionsConcreteDepth); + } + typeDefinitionsConcreteDepth.add(unsortedTypeDefinition); + } + + Set depths = typeDefinitionsDepths.keySet(); // keys are in + // ascending order + for (Integer depth : depths) { + sortedTypeDefinition.addAll(typeDefinitionsDepths.get(depth)); + } + + return sortedTypeDefinition; + } + + /** + * The method return how many immersion is necessary to get from type + * definition to base type. + * + * @param typeDefinition + * is type definition for which is depth looked for. + * @return how many immersion is necessary to get from type definition to + * base type + */ + private int getTypeDefinitionDepth(final TypeDefinition typeDefinition) { + if (typeDefinition == null) { + throw new IllegalArgumentException("Type definition can't be null"); + } + int depth = 1; + TypeDefinition baseType = typeDefinition.getBaseType(); + + if (baseType instanceof ExtendedType) { + depth = depth + getTypeDefinitionDepth(typeDefinition.getBaseType()); + } else if (baseType instanceof UnionType) { + List> childTypeDefinitions = ((UnionType) baseType).getTypes(); + int maxChildDepth = 0; + int childDepth = 1; + for (TypeDefinition childTypeDefinition : childTypeDefinitions) { + childDepth = childDepth + getTypeDefinitionDepth(childTypeDefinition.getBaseType()); + if (childDepth > maxChildDepth) { + maxChildDepth = childDepth; + } + } + return maxChildDepth; + } + return depth; + } + }