Share RpcResult Type
[mdsal.git] / binding / mdsal-binding-generator-impl / src / main / java / org / opendaylight / mdsal / binding / generator / impl / AbstractTypeGenerator.java
index 9ae1749e1ca73660be2d3df520fbf97048334876..691e541597c3bed516598a1ca948e573e65d18c1 100644 (file)
@@ -14,12 +14,19 @@ import static java.util.Objects.requireNonNull;
 import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.computeDefaultSUID;
 import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.packageNameForAugmentedGeneratedType;
 import static org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil.packageNameForGeneratedType;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.BASE_IDENTITY;
 import static org.opendaylight.mdsal.binding.model.util.BindingTypes.DATA_OBJECT;
 import static org.opendaylight.mdsal.binding.model.util.BindingTypes.DATA_ROOT;
-import static org.opendaylight.mdsal.binding.model.util.BindingTypes.IDENTIFIABLE;
-import static org.opendaylight.mdsal.binding.model.util.BindingTypes.IDENTIFIER;
 import static org.opendaylight.mdsal.binding.model.util.BindingTypes.NOTIFICATION;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.NOTIFICATION_LISTENER;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.ROUTING_CONTEXT;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.RPC_SERVICE;
 import static org.opendaylight.mdsal.binding.model.util.BindingTypes.augmentable;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.childOf;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.choiceIn;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.identifiable;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.identifier;
+import static org.opendaylight.mdsal.binding.model.util.BindingTypes.rpcResult;
 import static org.opendaylight.mdsal.binding.model.util.Types.BOOLEAN;
 import static org.opendaylight.mdsal.binding.model.util.Types.FUTURE;
 import static org.opendaylight.mdsal.binding.model.util.Types.typeForClass;
@@ -48,6 +55,7 @@ import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
 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.mdsal.binding.model.api.type.builder.AnnotableTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.AnnotationTypeBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.EnumBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedPropertyBuilder;
@@ -57,7 +65,6 @@ import org.opendaylight.mdsal.binding.model.api.type.builder.GeneratedTypeBuilde
 import org.opendaylight.mdsal.binding.model.api.type.builder.MethodSignatureBuilder;
 import org.opendaylight.mdsal.binding.model.api.type.builder.TypeMemberBuilder;
 import org.opendaylight.mdsal.binding.model.util.BindingGeneratorUtil;
-import org.opendaylight.mdsal.binding.model.util.BindingTypes;
 import org.opendaylight.mdsal.binding.model.util.ReferencedTypeImpl;
 import org.opendaylight.mdsal.binding.model.util.TypeConstants;
 import org.opendaylight.mdsal.binding.model.util.Types;
@@ -65,14 +72,9 @@ import org.opendaylight.mdsal.binding.model.util.generated.type.builder.Generate
 import org.opendaylight.mdsal.binding.yang.types.AbstractTypeProvider;
 import org.opendaylight.mdsal.binding.yang.types.BaseYangTypes;
 import org.opendaylight.mdsal.binding.yang.types.GroupingDefinitionDependencySort;
-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.QNameModule;
-import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.CaseSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
@@ -111,6 +113,8 @@ import org.slf4j.LoggerFactory;
 abstract class AbstractTypeGenerator {
     private static final Logger LOG = LoggerFactory.getLogger(BindingGeneratorImpl.class);
     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);
 
     /**
      * Comparator based on augment target path.
@@ -285,8 +289,8 @@ abstract class AbstractTypeGenerator {
             final List<String> listKeys = listKeys(node);
             final GeneratedTOBuilder genTOBuilder = resolveListKeyTOBuilder(context, node);
             if (genTOBuilder != null) {
-                final Type identifierMarker = Types.parameterizedTypeFor(IDENTIFIER, genType);
-                final Type identifiableMarker = Types.parameterizedTypeFor(IDENTIFIABLE, genTOBuilder);
+                final Type identifierMarker = identifier(genType);
+                final Type identifiableMarker = identifiable(genTOBuilder);
                 genTOBuilder.addImplementsType(identifierMarker);
                 genType.addImplementsType(identifiableMarker);
             }
@@ -414,7 +418,7 @@ abstract class AbstractTypeGenerator {
         }
 
         final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(context, "Service");
-        interfaceBuilder.addImplementsType(Types.typeForClass(RpcService.class));
+        interfaceBuilder.addImplementsType(RPC_SERVICE);
 
         addCodegenInformation(interfaceBuilder, module, "RPCs", rpcDefinitions);
 
@@ -430,8 +434,7 @@ abstract class AbstractTypeGenerator {
                 method.addParameter(
                     createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getInput())), "input");
                 method.setReturnType(Types.parameterizedTypeFor(FUTURE,
-                    Types.parameterizedTypeFor(Types.typeForClass(RpcResult.class),
-                    createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getOutput())))));
+                    rpcResult(createRpcContainer(context, rpcName, rpc, verifyNotNull(rpc.getOutput())))));
             }
         }
 
@@ -478,7 +481,7 @@ abstract class AbstractTypeGenerator {
         }
 
         final GeneratedTypeBuilder listenerInterface = moduleTypeBuilder(context, "Listener");
-        listenerInterface.addImplementsType(BindingTypes.NOTIFICATION_LISTENER);
+        listenerInterface.addImplementsType(NOTIFICATION_LISTENER);
 
         for (final NotificationDefinition notification : notifications) {
             if (notification != null) {
@@ -549,16 +552,15 @@ abstract class AbstractTypeGenerator {
             packageNameForGeneratedType(context.modulePackageName(), identity.getPath()),
             BindingMapping.getClassName(identity.getQName())));
         final Set<IdentitySchemaNode> baseIdentities = identity.getBaseIdentities();
-        if (baseIdentities.isEmpty()) {
-            final GeneratedTOBuilder gto = typeProvider.newGeneratedTOBuilder(JavaTypeName.create(BaseIdentity.class));
-            newType.addImplementsType(gto.build());
-        } else {
+        if (!baseIdentities.isEmpty()) {
             for (IdentitySchemaNode baseIdentity : baseIdentities) {
                 final QName qname = baseIdentity.getQName();
                 final GeneratedTransferObject gto = typeProvider.newGeneratedTOBuilder(JavaTypeName.create(
                     BindingMapping.getRootPackageName(qname.getModule()), BindingMapping.getClassName(qname))).build();
                 newType.addImplementsType(gto);
             }
+        } else {
+            newType.addImplementsType(BASE_IDENTITY);
         }
 
         final Module module = context.module();
@@ -1049,11 +1051,14 @@ abstract class AbstractTypeGenerator {
             final GeneratedTypeBuilder choiceTypeBuilder = addRawInterfaceDefinition(
                 JavaTypeName.create(packageNameForGeneratedType(context.modulePackageName(), choiceNode.getPath()),
                 BindingMapping.getClassName(choiceNode.getQName())), choiceNode);
-            constructGetter(parent, choiceTypeBuilder, choiceNode);
-            choiceTypeBuilder.addImplementsType(typeForClass(DataContainer.class));
+            choiceTypeBuilder.addImplementsType(choiceIn(parent));
             annotateDeprecatedIfNecessary(choiceNode.getStatus(), choiceTypeBuilder);
             context.addChildNodeType(choiceNode, choiceTypeBuilder);
-            generateTypesFromChoiceCases(context, choiceTypeBuilder.build(), choiceNode);
+
+            final GeneratedType choiceType = choiceTypeBuilder.build();
+            generateTypesFromChoiceCases(context, choiceType, choiceNode);
+
+            constructGetter(parent, choiceType, choiceNode);
         }
     }
 
@@ -1166,25 +1171,7 @@ abstract class AbstractTypeGenerator {
                 final GeneratedTypeBuilder caseTypeBuilder = addDefaultInterfaceDefinition(context, caseNode);
                 caseTypeBuilder.addImplementsType(targetType);
 
-                SchemaNode parent;
-                final SchemaPath nodeSp = targetNode.getPath();
-                parent = findDataSchemaNode(schemaContext, nodeSp.getParent());
-
-                GeneratedTypeBuilder childOfType = null;
-                if (parent instanceof Module) {
-                    childOfType = moduleContext(((Module) parent).getQNameModule()).getModuleNode();
-                } else if (parent instanceof CaseSchemaNode) {
-                    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);
-                }
-
+                GeneratedTypeBuilder childOfType = findChildOfType(targetNode);
                 CaseSchemaNode node = null;
                 final String caseLocalName = caseNode.getQName().getLocalName();
                 if (caseNode instanceof CaseSchemaNode) {
@@ -1211,6 +1198,30 @@ abstract class AbstractTypeGenerator {
         }
     }
 
+    private GeneratedTypeBuilder findChildOfType(final ChoiceSchemaNode targetNode) {
+        final SchemaPath nodePath = targetNode.getPath();
+        final SchemaPath parentSp = nodePath.getParent();
+        if (parentSp.getParent() == null) {
+            return moduleContext(nodePath.getLastComponent().getModule()).getModuleNode();
+        }
+
+        final SchemaNode parent = findDataSchemaNode(schemaContext, parentSp);
+        GeneratedTypeBuilder childOfType = null;
+        if (parent instanceof CaseSchemaNode) {
+            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);
+        }
+
+        return childOfType;
+    }
+
     private static CaseSchemaNode findNamedCase(final ChoiceSchemaNode choice, final String caseName) {
         final List<CaseSchemaNode> cases = choice.findCaseNodes(caseName);
         return cases.isEmpty() ? null : cases.get(0);
@@ -1360,7 +1371,7 @@ abstract class AbstractTypeGenerator {
                             + nodeParam);
                 }
 
-                final AnnotationTypeBuilder rc = getter.addAnnotation(JavaTypeName.create(RoutingContext.class));
+                final AnnotationTypeBuilder rc = getter.addAnnotation(ROUTING_CONTEXT);
                 final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
                 final String genTypeName = BindingMapping.getClassName(identity.getQName().getLocalName());
                 rc.addParameter("value", packageName + "." + genTypeName + ".class");
@@ -1597,18 +1608,15 @@ abstract class AbstractTypeGenerator {
             final Type parent, final ModuleContext context) {
         final GeneratedTypeBuilder it = addRawInterfaceDefinition(
             JavaTypeName.create(packageName, BindingMapping.getClassName(schemaNode.getQName())), schemaNode);
-        if (parent == null) {
-            it.addImplementsType(DATA_OBJECT);
-        } else {
-            it.addImplementsType(BindingTypes.childOf(parent));
-        }
+
+        it.addImplementsType(parent == null ? DATA_OBJECT : childOf(parent));
         if (!(schemaNode instanceof GroupingDefinition)) {
             it.addImplementsType(augmentable(it));
         }
-
         if (schemaNode instanceof DataNodeContainer) {
-            groupingsToGenTypes(context, ((DataNodeContainer) schemaNode).getGroupings());
-            addImplementedInterfaceFromUses((DataNodeContainer) schemaNode, it);
+            final DataNodeContainer containerSchema = (DataNodeContainer) schemaNode;
+            groupingsToGenTypes(context, containerSchema.getGroupings());
+            addImplementedInterfaceFromUses(containerSchema, it);
         }
 
         return it;
@@ -1728,9 +1736,7 @@ abstract class AbstractTypeGenerator {
             getterMethodName(node.getQName().getLocalName(), returnType));
         getMethod.setReturnType(returnType);
 
-        if (node.getStatus() == Status.DEPRECATED) {
-            getMethod.addAnnotation("java.lang", "Deprecated");
-        }
+        annotateDeprecatedIfNecessary(node.getStatus(), getMethod);
         if (!returnType.getPackageName().isEmpty()) {
             // The return type has a package, so it's not a primitive type
             getMethod.addAnnotation("javax.annotation", "Nullable");
@@ -1800,11 +1806,9 @@ abstract class AbstractTypeGenerator {
 
         if (genTOBuilder != null) {
             final GeneratedTransferObject genTO = genTOBuilder.build();
-
-            // Fake the 'getKey()' for items, this is equivalent to constructGetter()
-            final MethodSignatureBuilder getMethod = typeBuilder.addMethod(getterMethodName("key", genTO));
-            getMethod.setReturnType(genTO);
-            getMethod.setComment("Returns Primary Key of Yang List Type");
+            // Add Identifiable.getKey() for items
+            typeBuilder.addMethod(BindingMapping.IDENTIFIABLE_KEY_NAME).setReturnType(genTO)
+                .addAnnotation(OVERRIDE_ANNOTATION);
             context.addGeneratedTOBuilder(genTOBuilder);
         }
     }
@@ -1991,9 +1995,9 @@ abstract class AbstractTypeGenerator {
         return null;
     }
 
-    private static void annotateDeprecatedIfNecessary(final Status status, final GeneratedTypeBuilder builder) {
+    private static void annotateDeprecatedIfNecessary(final Status status, final AnnotableTypeBuilder builder) {
         if (status == Status.DEPRECATED) {
-            builder.addAnnotation("java.lang", "Deprecated");
+            builder.addAnnotation(DEPRECATED_ANNOTATION);
         }
     }
 }