/*
- * 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;
+ */
-import com.google.common.base.Preconditions;
+package org.opendaylight.yangtools.binding.data.codec.gen.impl;
+import com.google.common.base.Preconditions;
import java.util.HashMap;
import java.util.Map;
-
import org.opendaylight.yangtools.binding.data.codec.util.ChoiceDispatchSerializer;
import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
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;
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_";
@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);
}
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);
}
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();
while (rootType.getBaseType() != null) {
rootType = rootType.getBaseType();
}
- if(rootType instanceof BooleanTypeDefinition) {
+ if(rootType instanceof BooleanTypeDefinition || rootType instanceof EmptyTypeDefinition) {
prefix = "is";
}
}
}
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);
}
}
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;
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