Binding generator v2 - fix action #1
[mdsal.git] / binding2 / mdsal-binding2-generator-impl / src / main / java / org / opendaylight / mdsal / binding / javav2 / generator / impl / RpcActionGenHelper.java
index cf65e3fabfc48907d5c3e62cc8e37f4b1829775c..3a3812b9caf75b088b2235e667e00759078e8b0f 100644 (file)
@@ -12,10 +12,11 @@ import static com.google.common.base.Preconditions.checkState;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.annotateDeprecatedIfNecessary;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.checkModuleAndModuleName;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.createDescription;
-import static org.opendaylight.mdsal.binding.javav2.generator.impl.AuxiliaryGenUtils.resolveListKeyTOBuilder;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.addImplementedInterfaceFromUses;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.addRawInterfaceDefinition;
 import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.moduleTypeBuilder;
+import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.processUsesImplements;
+import static org.opendaylight.mdsal.binding.javav2.generator.impl.GenHelperUtil.resolveDataSchemaNodesCheck;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.ACTION;
 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes.INPUT;
@@ -34,13 +35,15 @@ import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.paramet
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import java.util.Collection;
 import java.util.Map;
 import java.util.Set;
+import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
-import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
+import org.opendaylight.mdsal.binding.javav2.generator.util.BindingTypes;
+import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedType;
-import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.MethodSignatureBuilder;
 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
@@ -48,14 +51,15 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
 import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.OperationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
-import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 
 /**
  *
@@ -64,7 +68,7 @@ import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
  *
  */
 @Beta
-public final class RpcActionGenHelper {
+final class RpcActionGenHelper {
 
     private static final QName CONTEXT_REFERENCE =
             QName.create("urn:opendaylight:yang:extension:yang-ext", "2013-07-09", "context-reference").intern();
@@ -92,6 +96,38 @@ public final class RpcActionGenHelper {
         return Optional.absent();
     }
 
+    private static void resolveActions(final DataNodeContainer parent, final Module module,
+            final SchemaContext schemaContext, final boolean verboseClassComments,
+            Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final Map<Module, ModuleContext> genCtx,
+            TypeProvider typeProvider, final BindingNamespaceType namespaceType) {
+        Preconditions.checkNotNull(parent, "Parent should not be NULL.");
+        final Collection<DataSchemaNode> potentials = parent.getChildNodes();
+        for (DataSchemaNode potential : potentials) {
+            if (resolveDataSchemaNodesCheck(module, schemaContext,potential)) {
+                BindingNamespaceType namespaceType1 = namespaceType;
+                if (namespaceType.equals(BindingNamespaceType.Data)) {
+                    if (potential instanceof GroupingDefinition) {
+                        namespaceType1 = BindingNamespaceType.Grouping;
+                    }
+                }
+
+                if (potential instanceof ActionNodeContainer) {
+                    final Set<ActionDefinition> actions = ((ActionNodeContainer) potential).getActions();
+                    for (ActionDefinition action : actions) {
+                        genCtx.get(module).addTopLevelNodeType(resolveOperation(potential, action, module,
+                            schemaContext, verboseClassComments, genTypeBuilders, genCtx, typeProvider, true,
+                            namespaceType1));
+                    }
+                }
+
+                if (potential instanceof DataNodeContainer) {
+                    resolveActions((DataNodeContainer) potential, module, schemaContext, verboseClassComments,
+                        genTypeBuilders, genCtx, typeProvider, namespaceType1);
+                }
+            }
+        }
+    }
+
     /**
      * Converts Yang 1.1 <b>Actions</b> to list of <code>Type</code> objects.
      * @param module  module from which is obtained set of all Action objects to
@@ -101,20 +137,12 @@ public final class RpcActionGenHelper {
      * @return generated context
      */
     static Map<Module, ModuleContext> actionMethodsToGenType(final Module module, Map<Module, ModuleContext> genCtx,
-            final SchemaContext schemaContext, final boolean verboseClassComments, Map<String, Map<String,
-            GeneratedTypeBuilder>> genTypeBuilders, TypeProvider typeProvider) {
+            final SchemaContext schemaContext, final boolean verboseClassComments,
+            Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, TypeProvider typeProvider) {
 
         checkModuleAndModuleName(module);
-        final Collection<DataSchemaNode> potentials = module.getChildNodes();
-        for (DataSchemaNode potential : potentials) {
-            if (potential instanceof ActionNodeContainer) {
-                final Set<ActionDefinition> actions = ((ActionNodeContainer) potential).getActions();
-                for (ActionDefinition action: actions) {
-                    genCtx.get(module).addChildNodeType(potential, resolveOperation(potential, action, module,
-                            schemaContext, verboseClassComments, genTypeBuilders, genCtx, typeProvider, true));
-                }
-            }
-        }
+        resolveActions(module, module, schemaContext, verboseClassComments, genTypeBuilders, genCtx, typeProvider,
+            BindingNamespaceType.Data);
         return genCtx;
     }
 
@@ -152,21 +180,37 @@ public final class RpcActionGenHelper {
         }
 
         for (final RpcDefinition rpc : rpcDefinitions) {
-            DataSchemaNode parent = (DataSchemaNode) SchemaContextUtil.findDataSchemaNode(schemaContext, rpc.getPath().getParent());
+            //FIXME: get correct parent for routed RPCs only
+            DataSchemaNode parent = null;
+
+            ContainerSchemaNode input = rpc.getInput();
+            boolean isAction = false;
+            if (input != null) {
+                for (DataSchemaNode schemaNode : input.getChildNodes()) {
+                    if (getRoutingContext(schemaNode).isPresent()) {
+                        isAction = true;
+                        break;
+                    }
+                }
+            }
+
             //routedRPC?
-            if (getRoutingContext(parent).isPresent()) {
-                genCtx.get(module).addChildNodeType(parent, resolveOperation(parent, rpc, module, schemaContext,
-                        verboseClassComments, genTypeBuilders, genCtx, typeProvider, true));
+            if (isAction) {
+                genCtx.get(module).addTopLevelNodeType(resolveOperation(parent, rpc, module, schemaContext,
+                        verboseClassComments, genTypeBuilders, genCtx, typeProvider, true,
+                        BindingNamespaceType.Data));
             } else {
                 //global RPC only
                 genCtx.get(module).addTopLevelNodeType(resolveOperation(parent, rpc, module, schemaContext,
-                        verboseClassComments, genTypeBuilders, genCtx, typeProvider, false));
+                        verboseClassComments, genTypeBuilders, genCtx, typeProvider, false,
+                        BindingNamespaceType.Data));
 
             }
         }
         return genCtx;
     }
 
+    //TODO: This method should be reusable for convertion of action that is in grouping.
     /**
      * Converts RPC, Action or routed RPC into generated type
      * @return generated type
@@ -174,7 +218,7 @@ public final class RpcActionGenHelper {
     private static GeneratedTypeBuilder resolveOperation(final DataSchemaNode parent, final OperationDefinition operation,
             final Module module, final SchemaContext schemaContext, final boolean verboseClassComments,
             Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders, final Map<Module, ModuleContext> genCtx,
-            TypeProvider typeProvider, final boolean isAction) {
+            TypeProvider typeProvider, final boolean isAction, final BindingNamespaceType namespaceType) {
 
         //operation name
         final String operationName = operation.getQName().getLocalName();
@@ -186,27 +230,31 @@ public final class RpcActionGenHelper {
             sb.append("Rpc");
         }
         final GeneratedTypeBuilder interfaceBuilder = moduleTypeBuilder(module, sb.toString(),
-                verboseClassComments);
+                verboseClassComments, genCtx.get(module));
 
         final String basePackageName = interfaceBuilder.getPackageName();
 
         interfaceBuilder.setDescription(createDescription(operation, interfaceBuilder.getFullyQualifiedName(),
-                schemaContext, verboseClassComments));
+                schemaContext, verboseClassComments, namespaceType));
         final String operationComment = encodeAngleBrackets(operation.getDescription());
         final MethodSignatureBuilder operationMethod = interfaceBuilder.addMethod("invoke");
 
         //input
         final ContainerSchemaNode input = operation.getInput();
-        final GeneratedTypeBuilder inType = resolveOperationNode(module, operation.getInput(), basePackageName,
-                schemaContext, operationName, verboseClassComments, typeProvider, genTypeBuilders, genCtx, true);
+        final GeneratedTypeBuilder inType = resolveOperationNode(interfaceBuilder, module, operation.getInput(),
+                basePackageName, schemaContext, operationName, verboseClassComments, typeProvider, genTypeBuilders,
+                genCtx, true, namespaceType);
         annotateDeprecatedIfNecessary(operation.getStatus(), inType);
+        inType.setParentTypeForBuilder(interfaceBuilder);
         genCtx.get(module).addChildNodeType(input, inType);
 
         //output
         final ContainerSchemaNode output = operation.getOutput();
-        final GeneratedTypeBuilder outType = resolveOperationNode(module, operation.getOutput(), basePackageName,
-                schemaContext, operationName, verboseClassComments, typeProvider, genTypeBuilders, genCtx, false);
+        final GeneratedTypeBuilder outType = resolveOperationNode(interfaceBuilder, module, operation.getOutput(),
+                basePackageName, schemaContext, operationName, verboseClassComments, typeProvider, genTypeBuilders,
+                genCtx, false, namespaceType);
         annotateDeprecatedIfNecessary(operation.getStatus(), outType);
+        outType.setParentTypeForBuilder(interfaceBuilder);
         genCtx.get(module).addChildNodeType(output, outType);
 
         final GeneratedType inTypeInstance = inType.toInstance();
@@ -214,28 +262,29 @@ public final class RpcActionGenHelper {
 
         if (isAction) {
             //action, routed RPC
-            String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, parent.getPath(),
-                    BindingNamespaceType.Data);
-            GeneratedTypeBuilder parentType = addRawInterfaceDefinition(packageName, parent, schemaContext,
-                    parent.getQName().getLocalName(), verboseClassComments, genTypeBuilders);
-            parentType.addImplementsType(TREE_NODE);
-            parentType.addImplementsType(augmentable(parentType));
+            checkState(parent != null, "Parent node of " + operation.getQName().getLocalName() + " can't be NULL");
+            GeneratedTypeBuilder parentType = genCtx.get(module).getChildNode(parent.getPath());
+            checkState(parentType != null, "Parent generated type for " + parent
+                    + " data schema node must have been generated already");
             annotateDeprecatedIfNecessary(parent.getStatus(), parentType);
 
-            operationMethod.addParameter(parameterizedTypeFor(INSTANCE_IDENTIFIER, parentType), "ii");
-
             if (parent instanceof ListSchemaNode) {
                 //ListAction
-                final GeneratedTOBuilder keyType = resolveListKeyTOBuilder(basePackageName, (ListSchemaNode) parent);
+                GeneratedTransferObject keyType = null;
+                for (MethodSignatureBuilder method : parentType.getMethodDefinitions()) {
+                    if (method.getName().equals("getKey")) {
+                        keyType = (GeneratedTransferObject) method.toInstance(parentType).getReturnType();
+                    }
+                }
+
                 operationMethod.addParameter(
                         parameterizedTypeFor(KEYED_INSTANCE_IDENTIFIER, parentType, keyType), "kii");
-                operationMethod.setReturnType(keyType);
                 interfaceBuilder.addImplementsType(parameterizedTypeFor(LIST_ACTION, parentType, inType, outType));
             } else {
                 //Action
                 GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, parentType, parentType,
                         ((ContainerSchemaNode) parent).getChildNodes(), genCtx, schemaContext, verboseClassComments,
-                        genTypeBuilders, typeProvider);
+                        genTypeBuilders, typeProvider, namespaceType);
                 operationMethod.addParameter(parameterizedTypeFor(INSTANCE_IDENTIFIER, parentType), "ii");
                 interfaceBuilder.addImplementsType(parameterizedTypeFor(ACTION, parentType, inType, outType));
             }
@@ -244,6 +293,7 @@ public final class RpcActionGenHelper {
             interfaceBuilder.addImplementsType(parameterizedTypeFor(RPC, inType, outType));
         }
 
+        interfaceBuilder.addImplementsType(TREE_NODE);
         operationMethod.addParameter(parameterizedTypeFor(RPC_CALLBACK, outType), "callback");
 
         operationMethod.setComment(operationComment);
@@ -252,15 +302,16 @@ public final class RpcActionGenHelper {
         return interfaceBuilder;
     }
 
-    private static GeneratedTypeBuilder resolveOperationNode(final Module module, final ContainerSchemaNode
-            operationNode, final String basePackageName, final SchemaContext schemaContext, final String
+    private static GeneratedTypeBuilder resolveOperationNode(GeneratedTypeBuilder parent, final Module module, final
+            ContainerSchemaNode operationNode, final String basePackageName, final SchemaContext schemaContext, final String
             operationName, final boolean verboseClassComments, TypeProvider typeProvider, Map<String, Map<String,
-            GeneratedTypeBuilder>> genTypeBuilders, final Map<Module, ModuleContext> genCtx, final boolean isInput) {
-
+            GeneratedTypeBuilder>> genTypeBuilders, final Map<Module, ModuleContext> genCtx, final boolean isInput,
+            final BindingNamespaceType namespaceType) {
         final GeneratedTypeBuilder nodeType = addRawInterfaceDefinition(basePackageName, operationNode, schemaContext,
-                operationName, verboseClassComments, genTypeBuilders);
+                operationName, "", verboseClassComments, genTypeBuilders, namespaceType, genCtx.get(module));
         addImplementedInterfaceFromUses(operationNode, nodeType, genCtx);
-        nodeType.addImplementsType(TREE_NODE);
+        nodeType.addImplementsType(parameterizedTypeFor(BindingTypes.TREE_CHILD_NODE, parent, parameterizedTypeFor
+                (BindingTypes.ITEM, parent)));
         if (isInput) {
             nodeType.addImplementsType(parameterizedTypeFor(INPUT, nodeType));
         } else {
@@ -269,12 +320,14 @@ public final class RpcActionGenHelper {
         nodeType.addImplementsType(parameterizedTypeFor(INSTANTIABLE, nodeType));
         nodeType.addImplementsType(augmentable(nodeType));
         GenHelperUtil.resolveDataSchemaNodes(module, basePackageName, nodeType, nodeType, operationNode.getChildNodes(), genCtx,
-                schemaContext, verboseClassComments, genTypeBuilders, typeProvider);
+                schemaContext, verboseClassComments, genTypeBuilders, typeProvider, namespaceType);
 
         final MethodSignatureBuilder nodeMethod = nodeType.addMethod("implementedInterface");
         nodeMethod.setReturnType(parameterizedTypeFor(CLASS, nodeType));
         nodeMethod.addAnnotation("", "Override");
 
+        processUsesImplements(operationNode, module, schemaContext, genCtx, namespaceType);
+
         return nodeType;
     }
 }