2 * Copyright (c) 2013 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
8 package org.opendaylight.controller.sal.binding.generator.impl;
11 import java.util.ArrayList;
12 import java.util.Calendar;
13 import java.util.GregorianCalendar;
14 import java.util.HashMap;
15 import java.util.List;
19 import org.opendaylight.controller.binding.generator.util.CodeGeneratorHelper;
20 import org.opendaylight.controller.binding.generator.util.Types;
21 import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
22 import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider;
23 import org.opendaylight.controller.sal.binding.model.api.GeneratedTransferObject;
24 import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
25 import org.opendaylight.controller.sal.binding.model.api.Type;
26 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
27 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTOBuilder;
28 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
29 import org.opendaylight.controller.sal.binding.model.api.type.builder.MethodSignatureBuilder;
30 import org.opendaylight.controller.sal.binding.yang.types.TypeProviderImpl;
31 import org.opendaylight.controller.yang.common.QName;
32 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
33 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
34 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
35 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
36 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
37 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
38 import org.opendaylight.controller.yang.model.api.Module;
39 import org.opendaylight.controller.yang.model.api.SchemaContext;
40 import org.opendaylight.controller.yang.model.api.SchemaPath;
41 import org.opendaylight.controller.yang.model.api.TypeDefinition;
43 public class BindingGeneratorImpl implements BindingGenerator {
45 private static Calendar calendar = new GregorianCalendar();
46 private final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders;
47 private final List<ContainerSchemaNode> schemaContainers;
48 private final List<ListSchemaNode> schemaLists;
50 private final TypeProvider typeProvider;
52 private String basePackageName;
54 public BindingGeneratorImpl() {
56 genTypeBuilders = new HashMap<String, Map<String, GeneratedTypeBuilder>>();
57 schemaContainers = new ArrayList<ContainerSchemaNode>();
58 schemaLists = new ArrayList<ListSchemaNode>();
60 // TODO: reimplement in better way
61 typeProvider = new TypeProviderImpl();
65 public List<Type> generateTypes(final SchemaContext context) {
66 final List<Type> genTypes = new ArrayList<Type>();
68 if (context != null) {
69 final Set<Module> modules = context.getModules();
71 if (modules != null) {
72 for (final Module module : modules) {
73 basePackageName = resolveBasePackageName(module.getNamespace(),
74 module.getYangVersion());
76 traverseModule(module);
77 if (schemaContainers.size() > 0) {
78 for (final ContainerSchemaNode container : schemaContainers) {
79 genTypes.add(containerToGenType(container));
83 if (schemaLists.size() > 0) {
84 for (final ListSchemaNode list : schemaLists) {
85 genTypes.addAll(listToGenType(list));
95 private String resolveGeneratedTypePackageName(final SchemaPath schemaPath) {
96 final StringBuilder builder = new StringBuilder();
97 builder.append(basePackageName);
98 if ((schemaPath != null) && (schemaPath.getPath() != null)) {
99 final List<QName> pathToNode = schemaPath.getPath();
100 for (int i = 0; i < pathToNode.size(); ++i) {
102 String nodeLocalName = pathToNode.get(i).getLocalName();
104 // TODO: create method
105 nodeLocalName = nodeLocalName.replace(":", ".");
106 nodeLocalName = nodeLocalName.replace("-", ".");
107 builder.append(nodeLocalName);
109 return builder.toString();
114 private GeneratedType containerToGenType(ContainerSchemaNode container) {
115 if (container == null) {
118 final Set<DataSchemaNode> schemaNodes = container.getChildNodes();
119 final GeneratedTypeBuilder typeBuilder = addRawInterfaceDefinition(container);
121 for (final DataSchemaNode node : schemaNodes) {
122 if (node instanceof LeafSchemaNode) {
123 resolveLeafSchemaNodeAsMethod(typeBuilder,
124 (LeafSchemaNode) node);
125 } else if (node instanceof LeafListSchemaNode) {
126 resolveLeafListSchemaNode(typeBuilder,
127 (LeafListSchemaNode) node);
129 } else if (node instanceof ContainerSchemaNode) {
130 resolveContainerSchemaNode(typeBuilder,
131 (ContainerSchemaNode) node);
132 } else if (node instanceof ListSchemaNode) {
133 resolveListSchemaNode(typeBuilder, (ListSchemaNode) node);
136 return typeBuilder.toInstance();
139 private boolean resolveLeafSchemaNodeAsMethod(
140 final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode leaf) {
141 if ((leaf != null) && (typeBuilder != null)) {
142 final String leafName = leaf.getQName().getLocalName();
143 String leafDesc = leaf.getDescription();
144 if (leafDesc == null) {
148 if (leafName != null) {
149 final TypeDefinition<?> typeDef = leaf.getType();
150 final Type javaType = typeProvider
151 .javaTypeForSchemaDefinitionType(typeDef);
153 constructGetter(typeBuilder, leafName, leafDesc, javaType);
154 if (!leaf.isConfiguration()) {
155 constructSetter(typeBuilder, leafName, leafDesc, javaType);
163 private boolean resolveLeafSchemaNodeAsProperty(
164 final GeneratedTOBuilder toBuilder, final LeafSchemaNode leaf,
165 boolean isReadOnly) {
166 if ((leaf != null) && (toBuilder != null)) {
167 final String leafName = leaf.getQName().getLocalName();
168 String leafDesc = leaf.getDescription();
169 if (leafDesc == null) {
173 if (leafName != null) {
174 final TypeDefinition<?> typeDef = leaf.getType();
175 final Type javaType = typeProvider
176 .javaTypeForSchemaDefinitionType(typeDef);
178 final GeneratedPropertyBuilder propBuilder = toBuilder
179 .addProperty(CodeGeneratorHelper
180 .parseToClassName(leafName));
182 propBuilder.setReadOnly(isReadOnly);
183 propBuilder.addReturnType(javaType);
184 propBuilder.addComment(leafDesc);
186 toBuilder.addEqualsIdentity(propBuilder);
187 toBuilder.addHashIdentity(propBuilder);
188 toBuilder.addToStringProperty(propBuilder);
196 private boolean resolveLeafListSchemaNode(
197 final GeneratedTypeBuilder typeBuilder,
198 final LeafListSchemaNode node) {
199 if ((node != null) && (typeBuilder != null)) {
200 final String nodeName = node.getQName().getLocalName();
201 String nodeDesc = node.getDescription();
202 if (nodeDesc == null) {
206 if (nodeName != null) {
207 final TypeDefinition<?> type = node.getType();
208 final Type listType = Types.listTypeFor(typeProvider
209 .javaTypeForSchemaDefinitionType(type));
211 constructGetter(typeBuilder, nodeName, nodeDesc, listType);
212 if (!node.isConfiguration()) {
213 constructSetter(typeBuilder, nodeName, nodeDesc, listType);
221 private boolean resolveContainerSchemaNode(
222 final GeneratedTypeBuilder typeBuilder,
223 final ContainerSchemaNode node) {
224 if ((node != null) && (typeBuilder != null)) {
225 final String nodeName = node.getQName().getLocalName();
227 if (nodeName != null) {
228 final GeneratedTypeBuilder rawGenType = addRawInterfaceDefinition(node);
229 constructGetter(typeBuilder, nodeName, "", rawGenType);
237 private boolean resolveListSchemaNode(
238 final GeneratedTypeBuilder typeBuilder, final ListSchemaNode node) {
239 if ((node != null) && (typeBuilder != null)) {
240 final String nodeName = node.getQName().getLocalName();
242 if (nodeName != null) {
243 final GeneratedTypeBuilder rawGenType = addRawInterfaceDefinition(node);
244 constructGetter(typeBuilder, nodeName, "",
245 Types.listTypeFor(rawGenType));
246 if (!node.isConfiguration()) {
247 constructSetter(typeBuilder, nodeName, "",
248 Types.listTypeFor(rawGenType));
256 private GeneratedTypeBuilder addRawInterfaceDefinition(
257 final DataSchemaNode schemaNode) {
258 if (schemaNode == null) {
262 final String packageName = resolveGeneratedTypePackageName(schemaNode
264 final String schemaNodeName = schemaNode.getQName().getLocalName();
266 if ((packageName != null) && (schemaNode != null)
267 && (schemaNodeName != null)) {
268 final String genTypeName = CodeGeneratorHelper
269 .parseToClassName(schemaNodeName);
270 final GeneratedTypeBuilder newType = new GeneratedTypeBuilderImpl(
271 packageName, genTypeName);
273 if (!genTypeBuilders.containsKey(packageName)) {
274 final Map<String, GeneratedTypeBuilder> builders = new HashMap<String, GeneratedTypeBuilder>();
275 builders.put(genTypeName, newType);
276 genTypeBuilders.put(packageName, builders);
278 final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders
280 if (!builders.containsKey(genTypeName)) {
281 builders.put(genTypeName, newType);
290 private String getterMethodName(final String methodName) {
291 final StringBuilder method = new StringBuilder();
292 method.append("get");
293 method.append(CodeGeneratorHelper.parseToClassName(methodName));
294 return method.toString();
297 private String setterMethodName(final String methodName) {
298 final StringBuilder method = new StringBuilder();
299 method.append("set");
300 method.append(CodeGeneratorHelper.parseToClassName(methodName));
301 return method.toString();
304 private MethodSignatureBuilder constructGetter(
305 final GeneratedTypeBuilder interfaceBuilder,
306 final String schemaNodeName, final String comment,
307 final Type returnType) {
308 final MethodSignatureBuilder getMethod = interfaceBuilder
309 .addMethod(getterMethodName(schemaNodeName));
311 getMethod.addComment(comment);
312 getMethod.addReturnType(returnType);
317 private MethodSignatureBuilder constructSetter(
318 final GeneratedTypeBuilder interfaceBuilder,
319 final String schemaNodeName, final String comment,
320 final Type parameterType) {
321 final MethodSignatureBuilder setMethod = interfaceBuilder
322 .addMethod(setterMethodName(schemaNodeName));
324 setMethod.addComment(comment);
325 setMethod.addParameter(parameterType,
326 CodeGeneratorHelper.parseToParamName(schemaNodeName));
327 setMethod.addReturnType(Types.voidType());
332 private String resolveBasePackageName(final URI moduleNamespace,
333 final String yangVersion) {
334 final StringBuilder packageNameBuilder = new StringBuilder();
336 packageNameBuilder.append("com.cisco.yang.gen.v");
337 packageNameBuilder.append(yangVersion);
338 packageNameBuilder.append(".rev");
339 packageNameBuilder.append(calendar.get(Calendar.YEAR));
340 packageNameBuilder.append((calendar.get(Calendar.MONTH) + 1));
341 packageNameBuilder.append(calendar.get(Calendar.DAY_OF_MONTH));
342 packageNameBuilder.append(".");
344 String namespace = moduleNamespace.toString();
345 namespace = namespace.replace(":", ".");
346 namespace = namespace.replace("-", ".");
348 packageNameBuilder.append(namespace);
350 return packageNameBuilder.toString();
353 private List<Type> listToGenType(final ListSchemaNode list) {
357 final GeneratedTypeBuilder typeBuilder = resolveListTypeBuilder(list);
358 final List<String> listKeys = listKeys(list);
359 GeneratedTOBuilder genTOBuilder = null;
360 if (listKeys.size() > 0) {
361 genTOBuilder = resolveListKey(list);
364 final Set<DataSchemaNode> schemaNodes = list.getChildNodes();
365 for (final DataSchemaNode node : schemaNodes) {
367 if (node instanceof LeafSchemaNode) {
368 final LeafSchemaNode leaf = (LeafSchemaNode) node;
369 if (!isPartOfListKey(leaf, listKeys)) {
370 resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
372 resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true);
374 } else if (node instanceof LeafListSchemaNode) {
375 resolveLeafListSchemaNode(typeBuilder,
376 (LeafListSchemaNode) node);
377 } else if (node instanceof ContainerSchemaNode) {
378 resolveContainerSchemaNode(typeBuilder,
379 (ContainerSchemaNode) node);
380 } else if (node instanceof ListSchemaNode) {
381 resolveListSchemaNode(typeBuilder, (ListSchemaNode) node);
385 final List<Type> genTypes = new ArrayList<Type>();
386 if (genTOBuilder != null) {
387 final GeneratedTransferObject genTO = genTOBuilder.toInstance();
388 constructGetter(typeBuilder, genTO.getName(), "Returns Primary Key of Yang List Type", genTO);
391 genTypes.add(typeBuilder.toInstance());
399 private GeneratedTOBuilder resolveListKey(final ListSchemaNode list) {
400 final String packageName = resolveGeneratedTypePackageName(list
402 final String listName = list.getQName().getLocalName() + "Key";
404 if ((packageName != null) && (list != null) && (listName != null)) {
405 final String genTOName = CodeGeneratorHelper
406 .parseToClassName(listName);
407 final GeneratedTOBuilder newType = new GeneratedTOBuilderImpl(
408 packageName, genTOName);
415 private boolean isPartOfListKey(final LeafSchemaNode leaf,
416 final List<String> keys) {
417 if ((leaf != null) && (keys != null) && (leaf.getQName() != null)) {
418 final String leafName = leaf.getQName().getLocalName();
419 if (keys.contains(leafName)) {
426 private List<String> listKeys(final ListSchemaNode list) {
427 final List<String> listKeys = new ArrayList<String>();
429 if (list.getKeyDefinition() != null) {
430 final List<QName> keyDefinitions = list.getKeyDefinition();
432 for (final QName keyDefinition : keyDefinitions) {
433 listKeys.add(keyDefinition.getLocalName());
439 private GeneratedTypeBuilder resolveListTypeBuilder(
440 final ListSchemaNode list) {
441 final String packageName = resolveGeneratedTypePackageName(list
443 final String schemaNodeName = list.getQName().getLocalName();
444 final String genTypeName = CodeGeneratorHelper
445 .parseToClassName(schemaNodeName);
447 GeneratedTypeBuilder typeBuilder = null;
448 if (genTypeBuilders.containsKey(packageName)) {
449 final Map<String, GeneratedTypeBuilder> builders = new HashMap<String, GeneratedTypeBuilder>();
450 typeBuilder = builders.get(genTypeName);
452 if (null == typeBuilder) {
453 typeBuilder = addRawInterfaceDefinition(list);
459 private void traverseModule(final Module module) {
460 final Set<DataSchemaNode> schemaNodes = module.getChildNodes();
462 for (DataSchemaNode node : schemaNodes) {
463 if (node instanceof ContainerSchemaNode) {
464 schemaContainers.add((ContainerSchemaNode) node);
465 traverse((ContainerSchemaNode) node);
470 private void traverse(final DataNodeContainer dataNode) {
471 if (!containChildDataNodeContainer(dataNode)) {
475 final Set<DataSchemaNode> childs = dataNode.getChildNodes();
476 if (childs != null) {
477 for (DataSchemaNode childNode : childs) {
478 if (childNode instanceof ContainerSchemaNode) {
479 final ContainerSchemaNode container = (ContainerSchemaNode) childNode;
480 schemaContainers.add(container);
484 if (childNode instanceof ListSchemaNode) {
485 final ListSchemaNode list = (ListSchemaNode) childNode;
486 schemaLists.add(list);
494 * Returns <code>true</code> if and only if the child node contain at least
495 * one child container schema node or child list schema node, otherwise will
496 * always returns <code>false</code>
499 * @return <code>true</code> if and only if the child node contain at least
500 * one child container schema node or child list schema node,
501 * otherwise will always returns <code>false</code>
503 private boolean containChildDataNodeContainer(
504 final DataNodeContainer container) {
505 if (container != null) {
506 final Set<DataSchemaNode> childs = container.getChildNodes();
507 if ((childs != null) && (childs.size() > 0)) {
508 for (final DataSchemaNode childNode : childs) {
509 if (childNode instanceof DataNodeContainer) {