+ private static void typeBuildersToGenTypes(final Module module, final GeneratedTypeBuilder typeBuilder,
+ final Type keyType, final Map<Module, ModuleContext> genCtx,
+ final BindingNamespaceType namespaceType) {
+ checkArgument(typeBuilder != null, "Generated Type Builder cannot be NULL.");
+ if (keyType != null) {
+ Type returnKeyType = keyType;
+ if (namespaceType.equals(BindingNamespaceType.Grouping)) {
+ returnKeyType = wildcardTypeFor(keyType.getPackageName(), keyType.getName(),
+ true, true, null);
+ }
+ constructGetter(typeBuilder, "identifier", "Returns Primary Key of Yang List Type", returnKeyType, Status.CURRENT);
+
+ }
+ }
+
+ private static void addPatternConstant(final GeneratedTypeBuilder typeBuilder, final String leafName,
+ final List<PatternConstraint> patternConstraints) {
+ if (!patternConstraints.isEmpty()) {
+ final StringBuilder field = new StringBuilder();
+ field.append(BindingMapping.PATTERN_CONSTANT_NAME).append("_")
+ .append(JavaIdentifierNormalizer.normalizeSpecificIdentifier(leafName, JavaIdentifier.METHOD));
+ typeBuilder.addConstant(Types.listTypeFor(BaseYangTypes.STRING_TYPE), field.toString(),
+ resolveRegExpressions(patternConstraints));
+ }
+ }
+
+ /**
+ * 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 static Type resolveLeafSchemaNodeAsMethod(final String nodeName, final SchemaContext schemaContext,
+ final GeneratedTypeBuilder typeBuilder, final Map<Module, ModuleContext> genCtx, final LeafSchemaNode leaf,
+ final Module module, final TypeProvider typeProvider, final boolean verboseClassComments) {
+ if (leaf == null || typeBuilder == null) {
+ return null;
+ }
+
+ final String leafName = leaf.getQName().getLocalName();
+ if (leafName == null) {
+ return null;
+ }
+
+ final Module parentModule = findParentModule(schemaContext, leaf);
+ Type returnType = null;
+
+ final TypeDefinition<?> typeDef = leaf.getType();
+
+ if (leaf.isAddedByUses()) {
+ Preconditions.checkState(leaf instanceof DerivableSchemaNode);
+ if (isInnerType(leaf, typeDef)) {
+ final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
+ restrictions, genCtx.get(module));
+ } else {
+ if (typeDef.getBaseType() == null && (typeDef instanceof EnumTypeDefinition
+ || typeDef instanceof UnionTypeDefinition || typeDef instanceof BitsTypeDefinition)) {
+ LeafSchemaNode originalLeaf = (LeafSchemaNode) ((DerivableSchemaNode) leaf).getOriginal().orElse(null);
+ Preconditions.checkNotNull(originalLeaf);
+ returnType = genCtx.get(findParentModule(schemaContext, originalLeaf)).getInnerType(typeDef.getPath());
+ } else {
+ final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions, genCtx.get(module));
+ }
+ }
+ } else if (isInnerType(leaf, typeDef)) {
+ if (typeDef instanceof EnumTypeDefinition) {
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, genCtx.get(module));
+ final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
+ final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(),
+ genCtx, typeBuilder, module);
+ if (enumBuilder != null) {
+ returnType = enumBuilder.toInstance(typeBuilder);
+ }
+ ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
+ } else if (typeDef instanceof UnionTypeDefinition) {
+ final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule,
+ typeProvider, schemaContext, genCtx.get(module), genCtx);
+ if (genTOBuilder != null) {
+ //TODO: https://bugs.opendaylight.org/show_bug.cgi?id=2289
+ returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule,
+ typeProvider, verboseClassComments);
+ }
+ } else if (typeDef instanceof BitsTypeDefinition) {
+ final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, leaf, parentModule,
+ typeProvider, schemaContext, genCtx.get(module), genCtx);
+ if (genTOBuilder != null) {
+ returnType = genTOBuilder.toInstance();
+ }
+ } else {
+ // It is constrained version of already declared type (inner declared type exists,
+ // onlyfor special cases (Enum, Union, Bits), which were already checked.
+ // In order to get proper class we need to look up closest derived type
+ // and apply restrictions from leaf type
+ final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(getBaseOrDeclaredType(typeDef), leaf,
+ restrictions, genCtx.get(module));
+ addPatternConstant(typeBuilder, leafName, restrictions.getPatternConstraints());
+ }
+ } else {
+ final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, restrictions, genCtx.get(module));
+ addPatternConstant(typeBuilder, leafName, restrictions.getPatternConstraints());
+ }
+
+ if (returnType == null) {
+ return null;
+ }
+
+ if (typeDef instanceof EnumTypeDefinition) {
+ ((TypeProviderImpl) typeProvider).putReferencedType(leaf.getPath(), returnType);
+ }
+
+ final String leafGetterName;
+ if ("key".equals(leafName.toLowerCase())) {
+ StringBuilder sb = new StringBuilder(leafName)
+ .append('_').append("RESERVED_WORD");
+ leafGetterName = sb.toString();
+ } else {
+ leafGetterName = leafName;
+ }
+ constructGetter(typeBuilder, leafGetterName, leaf.getDescription().orElse(""), returnType, leaf.getStatus());
+ return returnType;
+ }
+
+ /**
+ * 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 module
+ * @param typeProvider type provider instance
+ * @param genCtx actual generated context
+ * @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 static boolean resolveLeafListSchemaNode(final SchemaContext schemaContext, final GeneratedTypeBuilder
+ typeBuilder, final LeafListSchemaNode node, final Module module, final TypeProvider typeProvider,
+ final Map<Module, ModuleContext> genCtx, final boolean verboseClassComments) {
+ if (node == null || typeBuilder == null) {
+ return false;
+ }
+
+ final QName nodeName = node.getQName();
+
+ final TypeDefinition<?> typeDef = node.getType();
+ final Module parentModule = findParentModule(schemaContext, node);
+
+ Type returnType = null;
+ if (typeDef.getBaseType() == null) {
+ if (typeDef instanceof EnumTypeDefinition) {
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, genCtx.get(module));
+ final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
+ final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName,
+ genCtx, typeBuilder, module);
+ returnType = new ReferencedTypeImpl(enumBuilder.getPackageName(), enumBuilder.getName(), true,
+ null);
+ ((TypeProviderImpl) typeProvider).putReferencedType(node.getPath(), returnType);
+ } else if (typeDef instanceof UnionTypeDefinition) {
+ final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule,
+ typeProvider, schemaContext, genCtx.get(module), genCtx);
+ if (genTOBuilder != null) {
+ returnType = createReturnTypeForUnion(genTOBuilder, typeDef, typeBuilder, parentModule,
+ typeProvider, verboseClassComments);
+ }
+ } else if (typeDef instanceof BitsTypeDefinition) {
+ final GeneratedTOBuilder genTOBuilder = addTOToTypeBuilder(typeDef, typeBuilder, node, parentModule,
+ typeProvider, schemaContext, genCtx.get(module), genCtx);
+ returnType = genTOBuilder.toInstance();
+ } else {
+ final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions, genCtx.get(module));
+
+ addPatternConstant(typeBuilder, nodeName.getLocalName(), restrictions.getPatternConstraints());
+ }
+ } else {
+ final Restrictions restrictions = BindingGeneratorUtil.getRestrictions(typeDef);
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, restrictions, genCtx.get(module));
+
+ addPatternConstant(typeBuilder, nodeName.getLocalName(), restrictions.getPatternConstraints());
+ }
+
+ final ParameterizedType listType = Types.listTypeFor(returnType);
+ constructGetter(typeBuilder, nodeName.getLocalName(), node.getDescription().orElse(null), listType, node.getStatus());
+ return true;
+ }
+
+ /**
+ * 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 schemaContext
+ * current schema context
+ * @param genCtx
+ * actual generated context
+ * @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
+ * @param verboseClassComments
+ * Javadoc verbosity switch
+ * @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 static void generateTypesFromChoiceCases(final Module module, final SchemaContext schemaContext,
+ final Map<Module, ModuleContext> genCtx, final String basePackageName, final GeneratedType refChoiceType,
+ final ChoiceSchemaNode choiceNode, final boolean verboseClassComments,
+ final TypeProvider typeProvider, final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders,
+ final BindingNamespaceType namespaceType) {
+ 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.");
+
+ for (final CaseSchemaNode caseNode : choiceNode.getCases().values()) {
+ if (caseNode != null && resolveDataSchemaNodesCheck(module, schemaContext, caseNode)) {
+ final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(basePackageName, caseNode,
+ null, module, genCtx, schemaContext, verboseClassComments,
+ genTypeBuilders, typeProvider, namespaceType);
+ caseTypeBuilder.addImplementsType(refChoiceType);
+ caseTypeBuilder.setParentTypeForBuilder(refChoiceType.getParentTypeForBuilder());
+ annotateDeprecatedIfNecessary(caseNode.getStatus(), caseTypeBuilder);
+ genCtx.get(module).addCaseType(caseNode.getPath(), caseTypeBuilder);
+ if (namespaceType.equals(BindingNamespaceType.Data)) {
+ genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
+ }
+
+ resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder,
+ (GeneratedTypeBuilder) refChoiceType.getParentTypeForBuilder(), caseNode.getChildNodes(),
+ genCtx, schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
+ processUsesImplements(caseNode, module, schemaContext, genCtx, namespaceType);
+ }
+ }
+ }
+
+ private static Type resolveAnyNodeAsMethod(final SchemaContext schemaContext, final GeneratedTypeBuilder
+ typeBuilder, final Map<Module, ModuleContext> genCtx, final DataSchemaNode node, final Module module,
+ final TypeProvider typeProvider) {
+
+ final String anyName = node.getQName().getLocalName();
+ if (anyName == null) {
+ return null;
+ }
+
+ Type returnType = Types.DOCUMENT;
+ constructGetter(typeBuilder, anyName, node.getDescription().orElse(""), returnType, node.getStatus());
+ return returnType;
+ }
+
+ /**
+ * Adds <code>schemaNode</code> to <code>typeBuilder</code> as getter method
+ * or to <code>genTOBuilder</code> as property.
+ *
+ * @param nodeName
+ * string contains the name of list
+ * @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 QNames of the list keys
+ * @param module
+ * current module
+ * @param typeProvider
+ * provider that defines contract for generated types
+ * @param schemaContext
+ * schema context
+ * @param genCtx
+ * map of generated entities in context of YANG modules
+ * @param genTypeBuilders
+ * map of generated type builders
+ * @param verboseClassComments
+ * generate verbose comments
+ * @throws IllegalArgumentException
+ * <ul>
+ * <li>if <code>schemaNode</code> equals null</li>
+ * <li>if <code>typeBuilder</code> equals null</li>
+ * </ul>
+ */
+ private static void addSchemaNodeToListBuilders(final String nodeName, final String basePackageName,
+ final DataSchemaNode schemaNode, final GeneratedTypeBuilder typeBuilder,
+ final GeneratedTOBuilder genTOBuilder, final List<QName> listKeys, final Module module,
+ final TypeProvider typeProvider, final SchemaContext schemaContext, final Map<Module, ModuleContext> genCtx,
+ final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final boolean verboseClassComments,
+ final BindingNamespaceType namespaceType) {
+ 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 QName leafQName = leaf.getQName();
+
+ final Type type = resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, typeBuilder, genCtx, leaf, module,
+ typeProvider, verboseClassComments);
+ if (listKeys.contains(leafQName)) {
+ if (type == null) {
+ resolveLeafSchemaNodeAsProperty(nodeName, schemaContext, typeProvider, genCtx, genTOBuilder, leaf, true,
+ module);
+ } else {
+ AuxiliaryGenUtils.resolveLeafSchemaNodeAsProperty(nodeName, genTOBuilder, leaf, type, true);
+ }
+ }
+ } else {
+ if (schemaNode instanceof LeafListSchemaNode) {
+ resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) schemaNode, module,
+ typeProvider, genCtx, verboseClassComments);
+ } else if (schemaNode instanceof ContainerSchemaNode) {
+ containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode,
+ schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
+ } else if (schemaNode instanceof ListSchemaNode) {
+ listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode,
+ schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
+ } else if (schemaNode instanceof ChoiceSchemaNode) {
+ choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder, typeBuilder,
+ (ChoiceSchemaNode) schemaNode, genTypeBuilders, genCtx, typeProvider, namespaceType);
+ }
+ }
+ }
+
+ private static void addSchemaNodeToListTypeBuilders(final String nodeName, final String basePackageName,
+ final DataSchemaNode schemaNode, final GeneratedTypeBuilder typeBuilder,
+ final GeneratedTypeBuilder genTypeBuilder, final List<QName> listKeys, final Module module,
+ final TypeProvider typeProvider, final SchemaContext schemaContext, final Map<Module, ModuleContext> genCtx,
+ final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final boolean verboseClassComments,
+ final BindingNamespaceType namespaceType) {
+ 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 QName leafQName = leaf.getQName();
+ final Type type = resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, typeBuilder, genCtx, leaf, module,
+ typeProvider, verboseClassComments);
+ if (listKeys.contains(leafQName)) {
+ resolveLeafSchemaNodeAsMethod(nodeName, schemaContext, genTypeBuilder, genCtx, leaf, module,
+ typeProvider, verboseClassComments);
+ }
+ } else {
+ if (schemaNode instanceof LeafListSchemaNode) {
+ resolveLeafListSchemaNode(schemaContext, typeBuilder, (LeafListSchemaNode) schemaNode, module,
+ typeProvider, genCtx, verboseClassComments);
+ } else if (schemaNode instanceof ContainerSchemaNode) {
+ containerToGenType(module, basePackageName, typeBuilder, typeBuilder, (ContainerSchemaNode) schemaNode,
+ schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
+ } else if (schemaNode instanceof ListSchemaNode) {
+ listToGenType(module, basePackageName, typeBuilder, typeBuilder, (ListSchemaNode) schemaNode,
+ schemaContext, verboseClassComments, genCtx, genTypeBuilders, typeProvider, namespaceType);
+ } else if (schemaNode instanceof ChoiceSchemaNode) {
+ choiceToGenType(module, schemaContext, verboseClassComments, basePackageName, typeBuilder, typeBuilder,
+ (ChoiceSchemaNode) schemaNode, genTypeBuilders, genCtx, typeProvider, namespaceType);
+ }
+ }
+ }
+
+ private static boolean resolveLeafSchemaNodeAsProperty(final String nodeName, final SchemaContext schemaContext, final TypeProvider
+ typeProvider, final Map<Module, ModuleContext> genCtx, final GeneratedTOBuilder
+ toBuilder, final LeafSchemaNode leaf, final boolean isReadOnly, final Module module) {
+
+ if (leaf != null && toBuilder != null) {
+ Type returnType;
+ 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.findModule(qname.getModule()).get();
+ final ModuleContext mc = genCtx.get(unionModule);
+ returnType = mc.getTypedefs().get(typeDef.getPath());
+ } else if (typeDef instanceof EnumTypeDefinition && typeDef.getBaseType() == null) {
+ // Annonymous enumeration (already generated, since it is inherited via uses).
+ LeafSchemaNode originalLeaf = (LeafSchemaNode) SchemaNodeUtils.getRootOriginalIfPossible(leaf);
+ QName qname = originalLeaf.getQName();
+ final Module enumModule = schemaContext.findModule(qname.getModule()).orElse(null);
+ returnType = genCtx.get(enumModule).getInnerType(originalLeaf.getType().getPath());
+ } else {
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, genCtx.get(module));
+ }
+ return AuxiliaryGenUtils.resolveLeafSchemaNodeAsProperty(nodeName, toBuilder, leaf, returnType, isReadOnly);
+ }
+ return false;
+ }
+
+ private static TypeDefinition<?> getBaseOrDeclaredType(final TypeDefinition<?> typeDef) {
+ final TypeDefinition<?> baseType = typeDef.getBaseType();
+ return baseType != null && baseType.getBaseType() != null ? baseType : typeDef;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })