Move BindingReflections to mdsal-binding-spec-util
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / impl / BindingCodecContext.java
index afd20911688eff6e9577fc145452045fa40d1044..d0bc62deead2c15f7ac328814f1c623bd09e4646 100644 (file)
@@ -27,9 +27,11 @@ import org.opendaylight.mdsal.binding.dom.codec.api.BindingCodecTreeNode;
 import org.opendaylight.mdsal.binding.dom.codec.impl.NodeCodecContext.CodecContextFactory;
 import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.mdsal.binding.model.api.GeneratedType;
+import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
 import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.util.ClassLoaderUtils;
+import org.opendaylight.yangtools.yang.binding.Action;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
 import org.opendaylight.yangtools.yang.binding.DataContainer;
@@ -40,19 +42,20 @@ import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
 import org.opendaylight.yangtools.yang.binding.Notification;
-import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+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.TypedSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypedDataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
@@ -125,7 +128,7 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
         DataContainerCodecContext<?,?> currentNode = root;
         for (final InstanceIdentifier.PathArgument bindingArg : binding.getPathArguments()) {
             currentNode = currentNode.bindingPathArgumentChild(bindingArg, builder);
-            Preconditions.checkArgument(currentNode != null, "Supplied Instance Identifier %s is not valid.",binding);
+            Preconditions.checkArgument(currentNode != null, "Supplied Instance Identifier %s is not valid.", binding);
         }
         return currentNode;
     }
@@ -148,7 +151,8 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
         ListNodeCodecContext<?> currentList = null;
 
         for (final YangInstanceIdentifier.PathArgument domArg : dom.getPathArguments()) {
-            Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?,?>, "Unexpected child of non-container node %s", currentNode);
+            Preconditions.checkArgument(currentNode instanceof DataContainerCodecContext<?,?>,
+                "Unexpected child of non-container node %s", currentNode);
             final DataContainerCodecContext<?,?> previous = (DataContainerCodecContext<?,?>) currentNode;
             final NodeCodecContext<?> nextNode = previous.yangPathArgumentChild(domArg);
 
@@ -161,7 +165,8 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
              * Identifier as Item or IdentifiableItem
              */
             if (currentList != null) {
-                Preconditions.checkArgument(currentList == nextNode, "List should be referenced two times in YANG Instance Identifier %s", dom);
+                Preconditions.checkArgument(currentList == nextNode,
+                        "List should be referenced two times in YANG Instance Identifier %s", dom);
 
                 // We entered list, so now we have all information to emit
                 // list path using second list argument.
@@ -217,21 +222,28 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
         return root.getRpc(path);
     }
 
+    ActionCodecContext getActionCodec(final Class<? extends Action<?, ?, ?>> action) {
+        return root.getAction(action);
+    }
+
     @Override
     public ImmutableMap<String, LeafNodeCodecContext<?>> getLeafNodes(final Class<?> parentClass,
             final DataNodeContainer childSchema) {
         final Map<String, DataSchemaNode> getterToLeafSchema = new HashMap<>();
         for (final DataSchemaNode leaf : childSchema.getChildNodes()) {
-            if (leaf instanceof TypedSchemaNode) {
-                getterToLeafSchema.put(getGetterName(leaf.getQName(), ((TypedSchemaNode) leaf).getType()), leaf);
+            if (leaf instanceof TypedDataSchemaNode) {
+                getterToLeafSchema.put(getGetterName(leaf, ((TypedDataSchemaNode) leaf).getType()), leaf);
             }
         }
         return getLeafNodesUsingReflection(parentClass, getterToLeafSchema);
     }
 
-    private static String getGetterName(final QName qName, final TypeDefinition<?> typeDef) {
-        final String suffix = BindingMapping.getGetterSuffix(qName);
-        if (typeDef instanceof BooleanTypeDefinition || typeDef instanceof EmptyTypeDefinition) {
+    private static String getGetterName(final SchemaNode node, final TypeDefinition<?> typeDef) {
+        final String suffix = BindingMapping.getGetterSuffix(node.getQName());
+        // Bug 8903: If it is a derived type of boolean or empty, not an inner type, then the return type
+        // of method would be the generated type of typedef not build-in types, so here it should be 'get'.
+        if ((typeDef instanceof BooleanTypeDefinition || typeDef instanceof EmptyTypeDefinition)
+                && (typeDef.getPath().equals(node.getPath()) || typeDef.getBaseType() == null)) {
             return "is" + suffix;
         }
         return "get" + suffix;
@@ -257,7 +269,8 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
                         throw new IllegalStateException("Unexpected return type " + genericType);
                     }
                 } else {
-                    continue; // We do not have schema for leaf, so we will ignore it (eg. getClass, getImplementedInterface).
+                    // We do not have schema for leaf, so we will ignore it (eg. getClass, getImplementedInterface).
+                    continue;
                 }
                 final Codec<Object, Object> codec = getCodec(valueType, schema);
                 final LeafNodeCodecContext<?> leafNode = new LeafNodeCodecContext<>(schema, codec, method,
@@ -269,9 +282,9 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
     }
 
     private Codec<Object, Object> getCodec(final Class<?> valueType, final DataSchemaNode schema) {
-        Preconditions.checkArgument(schema instanceof TypedSchemaNode, "Unsupported leaf node type %s", schema);
+        Preconditions.checkArgument(schema instanceof TypedDataSchemaNode, "Unsupported leaf node type %s", schema);
 
-        return getCodec(valueType, ((TypedSchemaNode)schema).getType());
+        return getCodec(valueType, ((TypedDataSchemaNode)schema).getType());
     }
 
     Codec<Object, Object> getCodec(final Class<?> valueType, final TypeDefinition<?> instantiatedType) {
@@ -293,21 +306,23 @@ final class BindingCodecContext implements CodecContextFactory, BindingCodecTree
         return ValueTypeCodec.NOOP_CODEC;
     }
 
+    @SuppressWarnings("checkstyle:illegalCatch")
     private Codec<Object, Object> getCodecForBindingClass(final Class<?> valueType, final TypeDefinition<?> typeDef) {
         if (typeDef instanceof IdentityrefTypeDefinition) {
-            return ValueTypeCodec.encapsulatedValueCodecFor(valueType, identityCodec);
+            return ValueTypeCodec.encapsulatedValueCodecFor(valueType, typeDef, identityCodec);
         } else if (typeDef instanceof InstanceIdentifierTypeDefinition) {
-            return ValueTypeCodec.encapsulatedValueCodecFor(valueType, instanceIdentifierCodec);
+            return ValueTypeCodec.encapsulatedValueCodecFor(valueType, typeDef, instanceIdentifierCodec);
         } else if (typeDef instanceof UnionTypeDefinition) {
-            final Callable<UnionTypeCodec> loader = UnionTypeCodec.loader(valueType, (UnionTypeDefinition) typeDef, this);
+            final Callable<UnionTypeCodec> loader = UnionTypeCodec.loader(valueType, (UnionTypeDefinition) typeDef,
+                this);
             try {
                 return loader.call();
             } catch (final Exception e) {
                 throw new IllegalStateException("Unable to load codec for " + valueType, e);
             }
         } else if (typeDef instanceof LeafrefTypeDefinition) {
-            final Entry<GeneratedType, Object> typeWithSchema = context.getTypeWithSchema(valueType);
-            final Object schema = typeWithSchema.getValue();
+            final Entry<GeneratedType, WithStatus> typeWithSchema = context.getTypeWithSchema(valueType);
+            final WithStatus schema = typeWithSchema.getValue();
             Preconditions.checkState(schema instanceof TypeDefinition<?>);
             return getCodec(valueType, (TypeDefinition<?>) schema);
         }