import static org.opendaylight.mdsal.binding.model.util.Types.listTypeFor;
import static org.opendaylight.mdsal.binding.model.util.Types.listenableFutureTypeFor;
import static org.opendaylight.mdsal.binding.model.util.Types.mapTypeFor;
+import static org.opendaylight.mdsal.binding.model.util.Types.primitiveBooleanType;
+import static org.opendaylight.mdsal.binding.model.util.Types.primitiveIntType;
import static org.opendaylight.mdsal.binding.model.util.Types.primitiveVoidType;
import static org.opendaylight.mdsal.binding.model.util.Types.wildcardTypeFor;
import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
import org.opendaylight.mdsal.binding.model.api.AccessModifier;
import org.opendaylight.mdsal.binding.model.api.Constant;
import org.opendaylight.mdsal.binding.model.api.DefaultType;
+import org.opendaylight.mdsal.binding.model.api.Enumeration;
import org.opendaylight.mdsal.binding.model.api.GeneratedTransferObject;
import org.opendaylight.mdsal.binding.model.api.GeneratedType;
import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
+import org.opendaylight.mdsal.binding.model.api.MethodSignature.ValueMechanics;
import org.opendaylight.mdsal.binding.model.api.ParameterizedType;
import org.opendaylight.mdsal.binding.model.api.Restrictions;
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
import org.opendaylight.yangtools.yang.model.api.DocumentedNode;
import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
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.NotificationDefinition;
import org.opendaylight.yangtools.yang.model.api.NotificationNodeContainer;
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.TypedDataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
import org.opendaylight.yangtools.yang.model.api.UsesNode;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
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.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.ModuleDependencySort;
private static final Splitter COLON_SPLITTER = Splitter.on(':');
private static final JavaTypeName DEPRECATED_ANNOTATION = JavaTypeName.create(Deprecated.class);
private static final JavaTypeName OVERRIDE_ANNOTATION = JavaTypeName.create(Override.class);
+ private static final JavaTypeName CHECK_RETURN_VALUE_ANNOTATION =
+ // Do not refer to annotation class, as it may not be available at runtime
+ JavaTypeName.create("edu.umd.cs.findbugs.annotations", "CheckReturnValue");
private static final Type LIST_STRING_TYPE = listTypeFor(BaseYangTypes.STRING_TYPE);
/**
/**
* Holds reference to schema context to resolve data of augmented element when creating augmentation builder.
*/
- private final @NonNull SchemaContext schemaContext;
+ private final @NonNull EffectiveModelContext schemaContext;
/**
* Holds renamed elements.
*/
private final Map<SchemaNode, JavaTypeName> renames;
- AbstractTypeGenerator(final SchemaContext context, final AbstractTypeProvider typeProvider,
+ AbstractTypeGenerator(final EffectiveModelContext context, final AbstractTypeProvider typeProvider,
final Map<SchemaNode, JavaTypeName> renames) {
this.schemaContext = requireNonNull(context);
this.typeProvider = requireNonNull(typeProvider);
contexts.forEach(this::allAugmentsToGenTypes);
}
- final @NonNull SchemaContext schemaContext() {
+ final @NonNull EffectiveModelContext schemaContext() {
return schemaContext;
}
genCtx.put(module.getQNameModule(), context);
allTypeDefinitionsToGenTypes(context);
groupingsToGenTypes(context, module.getGroupings());
- rpcMethodsToGenType(context);
allIdentitiesToGenTypes(context);
- notificationsToGenType(context);
if (!module.getChildNodes().isEmpty()) {
final GeneratedTypeBuilder moduleType = moduleToDataType(context);
context.addModuleNode(moduleType);
resolveDataSchemaNodes(context, moduleType, moduleType, module.getChildNodes(), false);
}
+
+ // Resolve RPCs and notifications only after we have created instantiated tree
+ rpcMethodsToGenType(context);
+ notificationsToGenType(context);
return context;
}
return null;
}
final GeneratedTypeBuilder genType = addDefaultInterfaceDefinition(context, node, baseInterface);
- defaultImplementedInterace(genType);
+ addConcreteInterfaceMethods(genType);
annotateDeprecatedIfNecessary(node, genType);
final Module module = context.module();
listType = listTypeFor(genType);
}
- constructGetter(parent, listType, node);
+ constructGetter(parent, listType, node).setMechanics(ValueMechanics.NULLIFY_EMPTY);
constructNonnull(parent, listType, node);
actionsToGenType(context, genType, node, keyTypeBuilder, inGrouping);
final Module module = context.module();
addImplementedInterfaceFromUses(module, moduleDataTypeBuilder);
moduleDataTypeBuilder.addImplementsType(DATA_ROOT);
+ // if we have more than 2 top level uses statements we need to define getImplementedInterface() on the
+ // top level DataRoot object
+ if (module.getUses().size() > 1) {
+ narrowImplementedInterface(moduleDataTypeBuilder);
+ }
addCodegenInformation(moduleDataTypeBuilder, module);
return moduleDataTypeBuilder;
final MethodSignatureBuilder method = interfaceBuilder.addMethod(rpcMethodName);
// Do not refer to annotation class, as it may not be available at runtime
- method.addAnnotation("edu.umd.cs.findbugs.annotations", "CheckReturnValue");
+ method.addAnnotation(CHECK_RETURN_VALUE_ANNOTATION);
addComment(method, rpc);
method.addParameter(
createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getInput()), RPC_INPUT), "input");
addImplementedInterfaceFromUses(schema, outType);
outType.addImplementsType(type);
outType.addImplementsType(augmentable(outType));
- defaultImplementedInterace(outType);
+ addConcreteInterfaceMethods(outType);
annotateDeprecatedIfNecessary(rpc, outType);
resolveDataSchemaNodes(context, outType, outType, schema.getChildNodes(), false);
context.addChildNodeType(schema, outType);
final GeneratedTypeBuilder notificationInterface = addDefaultInterfaceDefinition(
context.modulePackageName(), notification, DATA_OBJECT, context);
- defaultImplementedInterace(notificationInterface);
+ addConcreteInterfaceMethods(notificationInterface);
annotateDeprecatedIfNecessary(notification, notificationInterface);
notificationInterface.addImplementsType(NOTIFICATION);
context.addChildNodeType(notification, notificationInterface);
final GeneratedTypeBuilder notifInterface = addDefaultInterfaceDefinition(
packageNameForGeneratedType(context.modulePackageName(), notif.getPath()), notif, DATA_OBJECT, context);
- defaultImplementedInterace(notifInterface);
+ addConcreteInterfaceMethods(notifInterface);
annotateDeprecatedIfNecessary(notif, notifInterface);
notifInterface.addImplementsType(keyType != null ? keyedListNotification(notifInterface, parent, keyType)
* @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,
+ private Enumeration resolveInnerEnumFromTypeDefinition(final EnumTypeDefinition enumTypeDef, final QName enumName,
final GeneratedTypeBuilder typeBuilder, final ModuleContext context) {
- if (enumTypeDef != null && typeBuilder != null && enumTypeDef.getQName().getLocalName() != null) {
- final EnumBuilder enumBuilder = typeBuilder.addEnumeration(BindingMapping.getClassName(enumName));
- typeProvider.addEnumDescription(enumBuilder, enumTypeDef);
- enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
- context.addInnerTypedefType(enumTypeDef.getPath(), enumBuilder);
- return enumBuilder;
- }
- return null;
+ final EnumBuilder enumBuilder = typeBuilder.addEnumeration(BindingMapping.getClassName(enumName));
+ typeProvider.addEnumDescription(enumBuilder, enumTypeDef);
+ enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
+ final Enumeration ret = enumBuilder.toInstance(typeBuilder);
+ context.addTypeToSchema(ret, enumTypeDef);
+ context.addInnerTypedefType(enumTypeDef.getPath(), ret);
+ return ret;
}
/**
final GeneratedTypeBuilder augTypeBuilder = typeProvider.newGeneratedTypeBuilder(
JavaTypeName.create(augmentPackageName, augTypeName));
- augTypeBuilder.addImplementsType(DATA_OBJECT);
- defaultImplementedInterace(augTypeBuilder);
-
augTypeBuilder.addImplementsType(augmentation(targetTypeRef));
+ addConcreteInterfaceMethods(augTypeBuilder);
+
annotateDeprecatedIfNecessary(augSchema, augTypeBuilder);
addImplementedInterfaceFromUses(augSchema, augTypeBuilder);
if (caseNode != null && !caseNode.isAddedByUses() && !caseNode.isAugmenting()) {
final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(context, caseNode);
caseTypeBuilder.addImplementsType(refChoiceType);
- defaultImplementedInterace(caseTypeBuilder);
+ addConcreteInterfaceMethods(caseTypeBuilder);
annotateDeprecatedIfNecessary(caseNode, caseTypeBuilder);
context.addCaseType(caseNode.getPath(), caseTypeBuilder);
context.addChoiceToCaseMapping(refChoiceType, caseTypeBuilder, caseNode);
if (caseNode != null) {
final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(context, caseNode);
caseTypeBuilder.addImplementsType(targetType);
- defaultImplementedInterace(caseTypeBuilder);
+ addConcreteInterfaceMethods(caseTypeBuilder);
CaseSchemaNode node = null;
final String caseLocalName = caseNode.getQName().getLocalName();
final TypeDefinition<?> typeDef = CompatUtils.compatType(leaf);
if (isInnerType(leaf, typeDef)) {
if (typeDef instanceof EnumTypeDefinition) {
- returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, leaf, inGrouping);
final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
- final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(),
- typeBuilder, context);
- if (enumBuilder != null) {
- returnType = enumBuilder.toInstance(typeBuilder);
- }
+ returnType = resolveInnerEnumFromTypeDefinition(enumTypeDef, leaf.getQName(), typeBuilder, context);
typeProvider.putReferencedType(leaf.getPath(), returnType);
} else if (typeDef instanceof UnionTypeDefinition) {
final UnionTypeDefinition unionDef = (UnionTypeDefinition)typeDef;
returnType = genTOBuilder.build();
}
} 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
+ // It is constrained version of already declared type (inner declared type exists, only for 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, inGrouping);
+ final TypeDefinition<?> baseOrDeclaredType = getBaseOrDeclaredType(typeDef);
+ // we need to try to lookup an already generated type in case the leafref is targetting a generated type
+ if (baseOrDeclaredType instanceof LeafrefTypeDefinition) {
+ final SchemaNode leafrefTarget =
+ typeProvider.getTargetForLeafref((LeafrefTypeDefinition) baseOrDeclaredType, leaf);
+ if (leafrefTarget instanceof TypedDataSchemaNode) {
+ returnType = context.getInnerType(((TypedDataSchemaNode) leafrefTarget).getType().getPath());
+ }
+ }
+ if (returnType == null) {
+ returnType = typeProvider.javaTypeForSchemaDefinitionType(baseOrDeclaredType, leaf,
+ restrictions, inGrouping);
+ }
+
addPatternConstant(typeBuilder, leaf.getQName().getLocalName(), restrictions.getPatternConstraints());
}
} else {
Type returnType = null;
if (typeDef.getBaseType() == null) {
if (typeDef instanceof EnumTypeDefinition) {
- returnType = typeProvider.javaTypeForSchemaDefinitionType(typeDef, node, inGrouping);
final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) typeDef;
- final EnumBuilder enumBuilder = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName,
- typeBuilder, context);
- returnType = DefaultType.of(enumBuilder);
+ returnType = resolveInnerEnumFromTypeDefinition(enumTypeDef, nodeName, typeBuilder, context);
typeProvider.putReferencedType(node.getPath(), returnType);
} else if (typeDef instanceof UnionTypeDefinition) {
final UnionTypeDefinition unionDef = (UnionTypeDefinition)typeDef;
}
}
+ private static void addConcreteInterfaceMethods(final GeneratedTypeBuilder typeBuilder) {
+ defaultImplementedInterace(typeBuilder);
+
+ typeBuilder.addMethod(BindingMapping.BINDING_HASHCODE_NAME)
+ .setAccessModifier(AccessModifier.PUBLIC)
+ .setStatic(true)
+ .setReturnType(primitiveIntType());
+ typeBuilder.addMethod(BindingMapping.BINDING_EQUALS_NAME)
+ .setAccessModifier(AccessModifier.PUBLIC)
+ .setStatic(true)
+ .setReturnType(primitiveBooleanType());
+ typeBuilder.addMethod(BindingMapping.BINDING_TO_STRING_NAME)
+ .setAccessModifier(AccessModifier.PUBLIC)
+ .setStatic(true)
+ .setReturnType(STRING);
+ }
+
private static void narrowImplementedInterface(final GeneratedTypeBuilder typeBuilder) {
defineImplementedInterfaceMethod(typeBuilder, wildcardTypeFor(typeBuilder.getIdentifier()));
}