*/
package org.opendaylight.mdsal.binding.yang.types;
+import static java.util.Objects.requireNonNull;
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 java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
-import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.opendaylight.mdsal.binding.generator.spi.TypeProvider;
import org.opendaylight.mdsal.binding.model.api.AccessModifier;
import org.opendaylight.mdsal.binding.model.util.Types;
import org.opendaylight.mdsal.binding.model.util.generated.type.builder.AbstractEnumerationBuilder;
import org.opendaylight.mdsal.binding.model.util.generated.type.builder.GeneratedPropertyBuilderImpl;
-import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.Revision;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
public abstract class AbstractTypeProvider implements TypeProvider {
private static final Logger LOG = LoggerFactory.getLogger(AbstractTypeProvider.class);
private static final Pattern GROUPS_PATTERN = Pattern.compile("\\[(.*?)\\]");
- private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
// Backwards compatibility: Union types used to be instantiated in YANG namespace, which is no longer
// the case, as unions are emitted to their correct schema path.
*/
private final Map<SchemaPath, Type> referencedTypes = new HashMap<>();
private final Map<Module, Set<Type>> additionalTypes = new HashMap<>();
+ private final Map<SchemaNode, JavaTypeName> renames;
/**
* Creates new instance of class <code>TypeProviderImpl</code>.
*
* @param schemaContext
* contains the schema data red from YANG files
+ * @param renames
* @throws IllegalArgumentException
* if <code>schemaContext</code> equal null.
*/
- AbstractTypeProvider(final SchemaContext schemaContext) {
+ AbstractTypeProvider(final SchemaContext schemaContext, final Map<SchemaNode, JavaTypeName> renames) {
Preconditions.checkArgument(schemaContext != null, "Schema Context cannot be null!");
this.schemaContext = schemaContext;
+ this.renames = requireNonNull(renames);
resolveTypeDefsFromContext();
}
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);
}
// FIXME: it looks as though we could be using the same codepath as above...
- ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(typeDefinition.getQName().getLocalName());
+ ret = BaseYangTypes.javaTypeForYangType(typeDefinition.getQName().getLocalName());
if (ret == null) {
LOG.debug("Failed to resolve Java type for {}", typeDefinition);
}
final String basePackageName = BindingMapping.getRootPackageName(module.getQNameModule());
final JavaTypeName identifier = JavaTypeName.create(BindingGeneratorUtil.packageNameForGeneratedType(basePackageName,
identity.getPath()), BindingMapping.getClassName(identity.getQName()));
- final Type paramType = Types.wildcardTypeFor(identifier);
- return Types.parameterizedTypeFor(Types.typeForClass(Class.class), paramType);
+ return Types.classType(Types.wildcardTypeFor(identifier));
}
/**
Preconditions.checkArgument(dataNode != null, "Failed to find leafref target: %s in module %s (%s)",
strXPath, this.getParentModule(parentNode).getName(), parentNode.getQName().getModule());
+ // FIXME: this block seems to be some weird magic hack. Analyze and refactor it.
if (leafContainsEnumDefinition(dataNode)) {
returnType = referencedTypes.get(dataNode.getPath());
} else if (leafListContainsEnumDefinition(dataNode)) {
returnType = Types.listTypeFor(referencedTypes.get(dataNode.getPath()));
- } else {
+ }
+ if (returnType == null) {
returnType = resolveTypeFromDataSchemaNode(dataNode);
}
} else {
- returnType = Types.typeForClass(Object.class);
+ returnType = Types.objectType();
}
}
Preconditions.checkArgument(returnType != null, "Failed to find leafref target: %s in module %s (%s)",
* 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)
+ * type definition of the node for which should be created 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
*/
private Type typedefToGeneratedType(final String basePackageName, final Module module,
final TypeDefinition<?> typedef) {
- final TypeDefinition<?> innerTypedef = typedef.getBaseType();
+ final TypeDefinition<?> baseTypedef = typedef.getBaseType();
// See generatedTypeForExtendedDefinitionType() above for rationale behind this special case.
- if (innerTypedef instanceof LeafrefTypeDefinition || innerTypedef instanceof IdentityrefTypeDefinition) {
+ if (baseTypedef instanceof LeafrefTypeDefinition || baseTypedef instanceof IdentityrefTypeDefinition) {
return null;
}
final String typedefName = typedef.getQName().getLocalName();
final Type returnType;
- if (innerTypedef.getBaseType() != null) {
- returnType = provideGeneratedTOFromExtendedType(typedef, innerTypedef, basePackageName,
+ if (baseTypedef.getBaseType() != null) {
+ returnType = provideGeneratedTOFromExtendedType(typedef, baseTypedef, basePackageName,
module.getName());
- } else if (innerTypedef instanceof UnionTypeDefinition) {
+ } else if (baseTypedef instanceof UnionTypeDefinition) {
final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(
JavaTypeName.create(basePackageName, BindingMapping.getClassName(typedef.getQName())),
- (UnionTypeDefinition) innerTypedef, typedef);
+ (UnionTypeDefinition) baseTypedef, typedef);
genTOBuilder.setTypedef(true);
genTOBuilder.setIsUnion(true);
addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null));
} else {
types.add(unionBuilder.build());
}
- } else if (innerTypedef instanceof EnumTypeDefinition) {
+ } else if (baseTypedef instanceof EnumTypeDefinition) {
// enums are automatically Serializable
- final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypedef;
+ final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypedef;
// TODO units for typedef enum
returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef);
- } else if (innerTypedef instanceof BitsTypeDefinition) {
+ } else if (baseTypedef instanceof BitsTypeDefinition) {
final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForBitsTypeDefinition(
JavaTypeName.create(basePackageName, BindingMapping.getClassName(typedef.getQName())),
- (BitsTypeDefinition) innerTypedef, module.getName());
+ (BitsTypeDefinition) baseTypedef, module.getName());
genTOBuilder.setTypedef(true);
addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null));
makeSerializable(genTOBuilder);
returnType = genTOBuilder.build();
} else {
- final Type javaType = javaTypeForSchemaDefinitionType(innerTypedef, typedef);
+ final Type javaType = javaTypeForSchemaDefinitionType(baseTypedef, typedef);
returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName());
}
if (returnType != null) {
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);
+ final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty("value");
genPropBuilder.setReturnType(javaType);
genTOBuilder.addEqualsIdentity(genPropBuilder);
genTOBuilder.addHashIdentity(genPropBuilder);
final GeneratedTOBuilder resultTOBuilder = builders.remove(0);
builders.forEach(resultTOBuilder::addEnclosingTransferObject);
-
- resultTOBuilder.addProperty("value").setReturnType(Types.CHAR_ARRAY);
return resultTOBuilder;
}
final Module module = findParentModule(schemaContext, parentNode);
final GeneratedTOBuilder unionGenTOBuilder = newGeneratedTOBuilder(typeName);
+ unionGenTOBuilder.setIsUnion(true);
unionGenTOBuilder.setSchemaPath(typedef.getPath());
unionGenTOBuilder.setModuleName(module.getName());
addCodegenInformation(unionGenTOBuilder, typedef);
-
generatedTOBuilders.add(unionGenTOBuilder);
- unionGenTOBuilder.setIsUnion(true);
// Pattern string is the key, XSD regex is the value. The reason for this choice is that the pattern carries
// also negation information and hence guarantees uniqueness.
}
/**
- * Wraps code which handle case when union subtype is also of the type
- * <code>UnionType</code>.
+ * Wraps code which handles the 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.
+ * 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
final GeneratedPropertyBuilder propertyBuilder;
propertyBuilder = parentUnionGenTOBuilder.addProperty(BindingMapping.getPropertyName(
newTOBuilderName.simpleName()));
- propertyBuilder.setReturnType(subUnionGenTOBUilders.get(0));
+ propertyBuilder.setReturnType(subUnionGenTOBUilders.get(0).build());
parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder);
parentUnionGenTOBuilder.addToStringProperty(propertyBuilder);
final TypeDefinition<?> baseType = baseTypeDefForExtendedType(unionSubtype);
if (unionTypeName.equals(baseType.getQName().getLocalName())) {
final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType,
- parentNode);
+ parentNode, BindingGeneratorUtil.getRestrictions(unionSubtype));
if (javaType != null) {
updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
}
*/
private GeneratedTOBuilder typedefToTransferObject(final String basePackageName,
final TypeDefinition<?> typedef, final String moduleName) {
- final GeneratedTOBuilder newType = newGeneratedTOBuilder(JavaTypeName.create(
- BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typedef.getPath()),
- BindingMapping.getClassName(typedef.getQName().getLocalName())));
+ JavaTypeName name = renames.get(typedef);
+ if (name == null) {
+ name = JavaTypeName.create(
+ BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typedef.getPath()),
+ BindingMapping.getClassName(typedef.getQName().getLocalName()));
+ }
+
+ final GeneratedTOBuilder newType = newGeneratedTOBuilder(name);
newType.setSchemaPath(typedef.getPath());
newType.setModuleName(moduleName);
addCodegenInformation(newType, typedef);
final Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
genTOBuilder.setRestrictions(r);
+ addStringRegExAsConstant(genTOBuilder, resolveRegExpressionsFromTypedef(typedef));
+
if (typedef.getStatus() == Status.DEPRECATED) {
genTOBuilder.addAnnotation("java.lang", "Deprecated");
}
* transfer object which needs to be serializable
*/
private static void makeSerializable(final GeneratedTOBuilder gto) {
- gto.addImplementsType(Types.typeForClass(Serializable.class));
+ gto.addImplementsType(Types.serializableType());
final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("serialVersionUID");
prop.setValue(Long.toString(BindingGeneratorUtil.computeDefaultSUID(gto)));
gto.setSUID(prop);
final Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();
for (TypeDefinition<?> unsortedTypeDefinition : unsortedTypeDefinitions) {
final Integer depth = getTypeDefinitionDepth(unsortedTypeDefinition);
- List<TypeDefinition<?>> typeDefinitionsConcreteDepth = typeDefinitionsDepths.get(depth);
- if (typeDefinitionsConcreteDepth == null) {
- typeDefinitionsConcreteDepth = new ArrayList<>();
- typeDefinitionsDepths.put(depth, typeDefinitionsConcreteDepth);
- }
+ List<TypeDefinition<?>> typeDefinitionsConcreteDepth =
+ typeDefinitionsDepths.computeIfAbsent(depth, k -> new ArrayList<>());
typeDefinitionsConcreteDepth.add(unsortedTypeDefinition);
}
}
/**
- * 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.
+ * 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, a new suffix initialized at 1 is added. A suffix is actually
+ * composed of a '$' marker, which is safe, as no YANG identifier can contain '$', and a unsigned decimal integer.
*
* @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) {
- final Matcher mtch = NUMBERS_PATTERN.matcher(name);
- if (mtch.find()) {
- final int newSuffix = Integer.parseInt(name.substring(mtch.start())) + 1;
- return name.substring(0, mtch.start()) + newSuffix;
+ final int dollar = name.indexOf('$');
+ if (dollar == -1) {
+ return name + "$1";
}
- return name + 1;
+ final int newSuffix = Integer.parseUnsignedInt(name.substring(dollar + 1)) + 1;
+ Preconditions.checkState(newSuffix > 0, "Suffix counter overflow");
+ return name.substring(0, dollar + 1) + newSuffix;
}
public static void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) {
return sb.toString();
}
- private static final Comparator<Bit> BIT_NAME_COMPARATOR = (o1, o2) -> o1.getName().compareTo(o2.getName());
+ private static final Comparator<Bit> BIT_NAME_COMPARATOR = Comparator.comparing(Bit::getName);
private static String bitsToDef(final BitsTypeDefinition type, final String className, final String defaultValue, final boolean isExt) {
final List<Bit> bits = new ArrayList<>(type.getBits());
- Collections.sort(bits, BIT_NAME_COMPARATOR);
+ bits.sort(BIT_NAME_COMPARATOR);
final StringBuilder sb = new StringBuilder();
if (!isExt) {
sb.append("new ");
}
if (module == null) {
final List<Module> modulesList = new ArrayList<>(modules);
- Collections.sort(modulesList, (o1, o2) -> Revision.compare(o1.getRevision(), o2.getRevision()));
+ modulesList.sort((o1, o2) -> Revision.compare(o1.getRevision(), o2.getRevision()));
module = modulesList.get(0);
}
} else {