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 boolean isCompositeKey(final String keyDefinition) {
333 if (keyDefinition.contains(" ")) {
339 private String resolveBasePackageName(final URI moduleNamespace,
340 final String yangVersion) {
341 final StringBuilder packageNameBuilder = new StringBuilder();
343 packageNameBuilder.append("com.cisco.yang.gen.v");
344 packageNameBuilder.append(yangVersion);
345 packageNameBuilder.append(".rev");
346 packageNameBuilder.append(calendar.get(Calendar.YEAR));
347 packageNameBuilder.append((calendar.get(Calendar.MONTH) + 1));
348 packageNameBuilder.append(calendar.get(Calendar.DAY_OF_MONTH));
349 packageNameBuilder.append(".");
351 String namespace = moduleNamespace.toString();
352 namespace = namespace.replace(":", ".");
353 namespace = namespace.replace("-", ".");
355 packageNameBuilder.append(namespace);
357 return packageNameBuilder.toString();
360 private List<Type> listToGenType(final ListSchemaNode list) {
364 final GeneratedTypeBuilder typeBuilder = resolveListTypeBuilder(list);
365 final List<String> listKeys = listKeys(list);
366 GeneratedTOBuilder genTOBuilder = null;
367 if (listKeys.size() > 0) {
368 genTOBuilder = resolveListKey(list);
371 final Set<DataSchemaNode> schemaNodes = list.getChildNodes();
372 for (final DataSchemaNode node : schemaNodes) {
374 if (node instanceof LeafSchemaNode) {
375 final LeafSchemaNode leaf = (LeafSchemaNode) node;
376 if (!isPartOfListKey(leaf, listKeys)) {
377 resolveLeafSchemaNodeAsMethod(typeBuilder, leaf);
379 resolveLeafSchemaNodeAsProperty(genTOBuilder, leaf, true);
381 } else if (node instanceof LeafListSchemaNode) {
382 resolveLeafListSchemaNode(typeBuilder,
383 (LeafListSchemaNode) node);
384 } else if (node instanceof ContainerSchemaNode) {
385 resolveContainerSchemaNode(typeBuilder,
386 (ContainerSchemaNode) node);
387 } else if (node instanceof ListSchemaNode) {
388 resolveListSchemaNode(typeBuilder, (ListSchemaNode) node);
392 final List<Type> genTypes = new ArrayList<Type>();
393 if (genTOBuilder != null) {
394 final GeneratedTransferObject genTO = genTOBuilder.toInstance();
395 constructGetter(typeBuilder, genTO.getName(), "Returns Primary Key of Yang List Type", genTO);
398 genTypes.add(typeBuilder.toInstance());
406 private GeneratedTOBuilder resolveListKey(final ListSchemaNode list) {
407 final String packageName = resolveGeneratedTypePackageName(list
409 final String listName = list.getQName().getLocalName() + "Key";
411 if ((packageName != null) && (list != null) && (listName != null)) {
412 final String genTOName = CodeGeneratorHelper
413 .parseToClassName(listName);
414 final GeneratedTOBuilder newType = new GeneratedTOBuilderImpl(
415 packageName, genTOName);
422 private boolean isPartOfListKey(final LeafSchemaNode leaf,
423 final List<String> keys) {
424 if ((leaf != null) && (keys != null) && (leaf.getQName() != null)) {
425 final String leafName = leaf.getQName().getLocalName();
426 if (keys.contains(leafName)) {
433 private List<String> listKeys(final ListSchemaNode list) {
434 final List<String> listKeys = new ArrayList<String>();
436 if (list.getKeyDefinition() != null) {
437 final List<QName> keyDefinitions = list.getKeyDefinition();
439 for (final QName keyDefinition : keyDefinitions) {
440 listKeys.add(keyDefinition.getLocalName());
446 private GeneratedTypeBuilder resolveListTypeBuilder(
447 final ListSchemaNode list) {
448 final String packageName = resolveGeneratedTypePackageName(list
450 final String schemaNodeName = list.getQName().getLocalName();
451 final String genTypeName = CodeGeneratorHelper
452 .parseToClassName(schemaNodeName);
454 GeneratedTypeBuilder typeBuilder = null;
455 if (genTypeBuilders.containsKey(packageName)) {
456 final Map<String, GeneratedTypeBuilder> builders = new HashMap<String, GeneratedTypeBuilder>();
457 typeBuilder = builders.get(genTypeName);
459 if (null == typeBuilder) {
460 typeBuilder = addRawInterfaceDefinition(list);
466 private void traverseModule(final Module module) {
467 final Set<DataSchemaNode> schemaNodes = module.getChildNodes();
469 for (DataSchemaNode node : schemaNodes) {
470 if (node instanceof ContainerSchemaNode) {
471 schemaContainers.add((ContainerSchemaNode) node);
472 traverse((ContainerSchemaNode) node);
477 private void traverse(final DataNodeContainer dataNode) {
478 if (!containChildDataNodeContainer(dataNode)) {
482 final Set<DataSchemaNode> childs = dataNode.getChildNodes();
483 if (childs != null) {
484 for (DataSchemaNode childNode : childs) {
485 if (childNode instanceof ContainerSchemaNode) {
486 final ContainerSchemaNode container = (ContainerSchemaNode) childNode;
487 schemaContainers.add(container);
491 if (childNode instanceof ListSchemaNode) {
492 final ListSchemaNode list = (ListSchemaNode) childNode;
493 schemaLists.add(list);
501 * Returns <code>true</code> if and only if the child node contain at least
502 * one child container schema node or child list schema node, otherwise will
503 * always returns <code>false</code>
506 * @return <code>true</code> if and only if the child node contain at least
507 * one child container schema node or child list schema node,
508 * otherwise will always returns <code>false</code>
510 private boolean containChildDataNodeContainer(
511 final DataNodeContainer container) {
512 if (container != null) {
513 final Set<DataSchemaNode> childs = container.getChildNodes();
514 if ((childs != null) && (childs.size() > 0)) {
515 for (final DataSchemaNode childNode : childs) {
516 if (childNode instanceof DataNodeContainer) {