2 * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
7 */package org.opendaylight.yangtools.binding.data.codec.gen.impl;
9 import com.google.common.base.Preconditions;
11 import java.util.HashMap;
14 import org.opendaylight.yangtools.binding.data.codec.util.ChoiceDispatchSerializer;
15 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType;
16 import org.opendaylight.yangtools.sal.binding.model.api.MethodSignature;
17 import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
18 import org.opendaylight.yangtools.sal.binding.model.api.Type;
19 import org.opendaylight.yangtools.yang.binding.BindingMapping;
20 import org.opendaylight.yangtools.yang.binding.BindingStreamEventWriter;
21 import org.opendaylight.yangtools.yang.binding.DataObject;
22 import org.opendaylight.yangtools.yang.binding.DataObjectSerializerImplementation;
23 import org.opendaylight.yangtools.yang.binding.DataObjectSerializerRegistry;
24 import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
25 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
26 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
27 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
28 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
33 import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
35 abstract class DataNodeContainerSerializerSource extends DataObjectSerializerSource {
37 protected static final String INPUT = "_input";
38 private static final String CHOICE_PREFIX = "CHOICE_";
40 protected final DataNodeContainer schemaNode;
41 private final GeneratedType dtoType;
43 DataNodeContainerSerializerSource(final AbstractGenerator generator, final GeneratedType type, final DataNodeContainer node) {
45 this.dtoType = Preconditions.checkNotNull(type);
46 this.schemaNode = Preconditions.checkNotNull(node);
50 * Return the character sequence which should be used for start event.
52 * @return Start event character sequence
54 protected abstract CharSequence emitStartEvent();
57 protected CharSequence getSerializerBody() {
58 StringBuilder b = new StringBuilder();
60 b.append(statement(assign(DataObjectSerializerRegistry.class.getName(), REGISTRY, "$1")));
61 b.append(statement(assign(dtoType.getFullyQualifiedName(), INPUT,
62 cast(dtoType.getFullyQualifiedName(), "$2"))));
63 b.append(statement(assign(BindingStreamEventWriter.class.getName(), STREAM, cast(BindingStreamEventWriter.class.getName(), "$3"))));
64 b.append(statement(emitStartEvent()));
68 b.append(statement(endNode()));
69 b.append(statement("return null"));
75 * Allows for customization of emitting code, which is processed after
76 * normal DataNodeContainer body. Ideal for augmentations or others.
78 protected void emitAfterBody(final StringBuilder b) {
82 private static Map<String, Type> collectAllProperties(final GeneratedType type, final Map<String, Type> hashMap) {
83 for (MethodSignature definition : type.getMethodDefinitions()) {
84 hashMap.put(definition.getName(), definition.getReturnType());
86 for (Type parent : type.getImplements()) {
87 if (parent instanceof GeneratedType) {
88 collectAllProperties((GeneratedType) parent, hashMap);
94 private static final String getGetterName(final DataSchemaNode node) {
95 final TypeDefinition<?> type ;
96 if (node instanceof LeafSchemaNode) {
97 type = ((LeafSchemaNode) node).getType();
98 } else if(node instanceof LeafListSchemaNode) {
99 type = ((LeafListSchemaNode) node).getType();
103 String prefix = "get";
105 TypeDefinition<?> rootType = type;
106 while (rootType.getBaseType() != null) {
107 rootType = rootType.getBaseType();
109 if(rootType instanceof BooleanTypeDefinition) {
114 return prefix + BindingMapping.getClassName(node.getQName().getLocalName());
117 private void emitBody(final StringBuilder b) {
118 Map<String, Type> getterToType = collectAllProperties(dtoType, new HashMap<String, Type>());
119 for (DataSchemaNode schemaChild : schemaNode.getChildNodes()) {
120 if (!schemaChild.isAugmenting()) {
121 String getter = getGetterName(schemaChild);
122 Type childType = getterToType.get(getter);
123 emitChild(b, getter, childType, schemaChild);
128 private void emitChild(final StringBuilder b, final String getterName, final Type childType,
129 final DataSchemaNode schemaChild) {
130 b.append(statement(assign(childType, getterName, cast(childType, invoke(INPUT, getterName)))));
132 b.append("if (").append(getterName).append(" != null) {\n");
133 emitChildInner(b, getterName, childType, schemaChild);
137 private void emitChildInner(final StringBuilder b, final String getterName, final Type childType,
138 final DataSchemaNode child) {
139 if (child instanceof LeafSchemaNode) {
140 b.append(statement(leafNode(child.getQName().getLocalName(), getterName)));
141 } else if (child instanceof AnyXmlSchemaNode) {
142 b.append(statement(anyxmlNode(child.getQName().getLocalName(), getterName)));
143 } else if (child instanceof LeafListSchemaNode) {
144 b.append(statement(startLeafSet(child.getQName().getLocalName(),invoke(getterName, "size"))));
145 Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0];
146 b.append(forEach(getterName, valueType, statement(leafSetEntryNode(CURRENT))));
147 b.append(statement(endNode()));
148 } else if (child instanceof ListSchemaNode) {
149 Type valueType = ((ParameterizedType) childType).getActualTypeArguments()[0];
150 ListSchemaNode casted = (ListSchemaNode) child;
151 emitList(b, getterName, valueType, casted);
152 } else if (child instanceof ContainerSchemaNode) {
153 b.append(statement(staticInvokeEmitter(childType, getterName)));
154 } else if (child instanceof ChoiceNode) {
155 String propertyName = CHOICE_PREFIX + childType.getName();
156 staticConstant(propertyName, DataObjectSerializerImplementation.class, ChoiceDispatchSerializer.from(loadClass(childType)));
157 b.append(statement(invoke(propertyName, StreamWriterGenerator.SERIALIZE_METHOD_NAME, REGISTRY, cast(DataObject.class.getName(),getterName), STREAM)));
161 private void emitList(final StringBuilder b, final String getterName, final Type valueType,
162 final ListSchemaNode child) {
163 final CharSequence startEvent;
165 b.append(statement(assign("int", "_count", invoke(getterName, "size"))));
166 if (child.getKeyDefinition().isEmpty()) {
167 startEvent = startUnkeyedList(classReference(valueType), "_count");
168 } else if (child.isUserOrdered()) {
169 startEvent = startOrderedMapNode(classReference(valueType), "_count");
171 startEvent = startMapNode(classReference(valueType), "_count");
173 b.append(statement(startEvent));
174 b.append(forEach(getterName, valueType, statement(staticInvokeEmitter(valueType, CURRENT))));
175 b.append(statement(endNode()));