Fix license header violations in binding-data-codec
[yangtools.git] / code-generator / binding-data-codec / src / main / java / org / opendaylight / yangtools / binding / data / codec / gen / impl / DataNodeContainerSerializerSource.java
index 9b8faba4cb67a2a3bf36215dbc9796937ed9b48d..d9094acc31cbab5624f5332e937f63570d67f546 100644 (file)
@@ -1,10 +1,12 @@
 /*
- * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others.  All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
  * and is available at http://www.eclipse.org/legal/epl-v10.html
- */package org.opendaylight.yangtools.binding.data.codec.gen.impl;
+ */
+
+package org.opendaylight.yangtools.binding.data.codec.gen.impl;
 
 import com.google.common.base.Preconditions;
 import java.util.HashMap;
@@ -15,12 +17,13 @@ import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
+import org.opendaylight.yangtools.yang.binding.BindingSerializer;
 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
 import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
@@ -30,9 +33,13 @@ import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSource {
 
+    private static final Logger LOG = LoggerFactory.getLogger(DataNodeContainerSerializerSource.class);
+
     protected static final String INPUT = "_input";
     private static final String CHOICE_PREFIX = "CHOICE_";
 
@@ -54,12 +61,20 @@ abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSou
 
     @Override
     protected CharSequence getSerializerBody() {
-        StringBuilder b = new StringBuilder();
+        final StringBuilder b = new StringBuilder();
         b.append("{\n");
         b.append(statement(assign(DataObjectSerializerRegistry.class.getName(), REGISTRY, "$1")));
         b.append(statement(assign(dtoType.getFullyQualifiedName(), INPUT,
                 cast(dtoType.getFullyQualifiedName(), "$2"))));
         b.append(statement(assign(BindingStreamEventWriter.class.getName(), STREAM, cast(BindingStreamEventWriter.class.getName(), "$3"))));
+        b.append(statement(assign(BindingSerializer.class.getName(), SERIALIZER, null)));
+        b.append("if (");
+        b.append(STREAM);
+        b.append(" instanceof ");
+        b.append(BindingSerializer.class.getName());
+        b.append(") {");
+        b.append(statement(assign(SERIALIZER, cast(BindingSerializer.class.getName(), STREAM))));
+        b.append('}');
         b.append(statement(emitStartEvent()));
 
         emitBody(b);
@@ -79,10 +94,10 @@ abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSou
     }
 
     private static Map<String, Type> collectAllProperties(final GeneratedType type, final Map<String, Type> hashMap) {
-        for (MethodSignature definition : type.getMethodDefinitions()) {
+        for (final MethodSignature definition : type.getMethodDefinitions()) {
             hashMap.put(definition.getName(), definition.getReturnType());
         }
-        for (Type parent : type.getImplements()) {
+        for (final Type parent : type.getImplements()) {
             if (parent instanceof GeneratedType) {
                 collectAllProperties((GeneratedType) parent, hashMap);
             }
@@ -90,7 +105,7 @@ abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSou
         return hashMap;
     }
 
-    private static final String getGetterName(final DataSchemaNode node) {
+    private static String getGetterName(final DataSchemaNode node) {
         final TypeDefinition<?> type ;
         if (node instanceof LeafSchemaNode) {
             type = ((LeafSchemaNode) node).getType();
@@ -114,11 +129,24 @@ abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSou
     }
 
     private void emitBody(final StringBuilder b) {
-        Map<String, Type> getterToType = collectAllProperties(dtoType, new HashMap<String, Type>());
-        for (DataSchemaNode schemaChild : schemaNode.getChildNodes()) {
+        final Map<String, Type> getterToType = collectAllProperties(dtoType, new HashMap<String, Type>());
+        for (final DataSchemaNode schemaChild : schemaNode.getChildNodes()) {
             if (!schemaChild.isAugmenting()) {
-                String getter = getGetterName(schemaChild);
-                Type childType = getterToType.get(getter);
+                final String getter = getGetterName(schemaChild);
+                final Type childType = getterToType.get(getter);
+                if (childType == null) {
+                    // FIXME AnyXml nodes are ignored, since their type cannot be found in generated bindnig
+                    // Bug-706 https://bugs.opendaylight.org/show_bug.cgi?id=706
+                    if (schemaChild instanceof AnyXmlSchemaNode) {
+                        LOG.warn("Node {} will be ignored. AnyXml is not yet supported from binding aware code." +
+                                "Binding Independent code can be used to serialize anyXml nodes.", schemaChild.getPath());
+                        continue;
+                    } else {
+                        throw new IllegalStateException(
+                                String.format("Unable to find type for child node %s. Expected child nodes: %s",
+                                        schemaChild.getPath(), getterToType));
+                    }
+                }
                 emitChild(b, getter, childType, schemaChild);
             }
         }
@@ -141,22 +169,34 @@ abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSou
             b.append(statement(anyxmlNode(child.getQName().getLocalName(), getterName)));
         } else if (child instanceof LeafListSchemaNode) {
             b.append(statement(startLeafSet(child.getQName().getLocalName(),invoke(getterName, "size"))));
-            Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0];
+            final Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0];
             b.append(forEach(getterName, valueType, statement(leafSetEntryNode(CURRENT))));
             b.append(statement(endNode()));
         } else if (child instanceof ListSchemaNode) {
-            Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0];
-            ListSchemaNode casted = (ListSchemaNode) child;
+            final Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0];
+            final ListSchemaNode casted = (ListSchemaNode) child;
             emitList(b, getterName, valueType, casted);
         } else if (child instanceof ContainerSchemaNode) {
-            b.append(statement(staticInvokeEmitter(childType, getterName)));
-        } else if (child instanceof ChoiceNode) {
-            String propertyName = CHOICE_PREFIX + childType.getName();
+            b.append(tryToUseCacheElse(getterName,statement(staticInvokeEmitter(childType, getterName))));
+        } else if (child instanceof ChoiceSchemaNode) {
+            final String propertyName = CHOICE_PREFIX + childType.getName();
             staticConstant(propertyName, DataObjectSerializerImplementation.class, ChoiceDispatchSerializer.from(loadClass(childType)));
-            b.append(statement(invoke(propertyName, StreamWriterGenerator.SERIALIZE_METHOD_NAME, REGISTRY, cast(DataObject.class.getName(),getterName), STREAM)));
+            b.append(tryToUseCacheElse(getterName,statement(invoke(propertyName, StreamWriterGenerator.SERIALIZE_METHOD_NAME, REGISTRY, cast(DataObject.class.getName(),getterName), STREAM))));
         }
     }
 
+    private StringBuilder tryToUseCacheElse(final String getterName, final CharSequence statement) {
+        final StringBuilder b = new StringBuilder();
+
+        b.append("if ( ");
+        b.append(SERIALIZER).append("== null || ");
+        b.append(invoke(SERIALIZER, "serialize", getterName)).append("== null");
+        b.append(") {");
+        b.append(statement);
+        b.append("}");
+        return b;
+    }
+
     private void emitList(final StringBuilder b, final String getterName, final Type valueType,
             final ListSchemaNode child) {
         final CharSequence startEvent;
@@ -170,7 +210,7 @@ abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSou
             startEvent = startMapNode(classReference(valueType), "_count");
         }
         b.append(statement(startEvent));
-        b.append(forEach(getterName, valueType, statement(staticInvokeEmitter(valueType, CURRENT))));
+        b.append(forEach(getterName, valueType, tryToUseCacheElse(CURRENT,statement(staticInvokeEmitter(valueType, CURRENT)))));
         b.append(statement(endNode()));
     }
 }
\ No newline at end of file