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.text.DateFormat;
12 import java.text.SimpleDateFormat;
13 import java.util.ArrayList;
14 import java.util.Calendar;
15 import java.util.GregorianCalendar;
16 import java.util.HashMap;
17 import java.util.List;
21 import org.opendaylight.controller.binding.generator.util.CodeGeneratorHelper;
22 import org.opendaylight.controller.binding.generator.util.Types;
23 import org.opendaylight.controller.sal.binding.generator.api.BindingGenerator;
24 import org.opendaylight.controller.sal.binding.generator.spi.TypeProvider;
25 import org.opendaylight.controller.sal.binding.model.api.GeneratedType;
26 import org.opendaylight.controller.sal.binding.model.api.Type;
27 import org.opendaylight.controller.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
28 import org.opendaylight.controller.sal.binding.model.api.type.builder.MethodSignatureBuilder;
29 import org.opendaylight.controller.sal.binding.yang.types.TypeProviderImpl;
30 import org.opendaylight.controller.yang.common.QName;
31 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
32 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
33 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
34 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
35 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
36 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
37 import org.opendaylight.controller.yang.model.api.Module;
38 import org.opendaylight.controller.yang.model.api.SchemaPath;
39 import org.opendaylight.controller.yang.model.api.TypeDefinition;
41 public class BindingGeneratorImpl implements BindingGenerator {
43 private static DateFormat simpleDateFormat = new SimpleDateFormat(
45 private static Calendar calendar = new GregorianCalendar();
47 private final Map<String, Map<String, GeneratedTypeBuilder>> genTypeBuilders;
48 private final List<ContainerSchemaNode> schemaContainers;
49 private final List<ListSchemaNode> schemaLists;
51 private final TypeProvider typeProvider;
53 private String basePackageName;
55 public BindingGeneratorImpl() {
57 genTypeBuilders = new HashMap<String, Map<String, GeneratedTypeBuilder>>();
58 schemaContainers = new ArrayList<ContainerSchemaNode>();
59 schemaLists = new ArrayList<ListSchemaNode>();
61 // TODO: reimplement in better way
62 typeProvider = new TypeProviderImpl();
66 public List<GeneratedType> generateTypes(final Module module) {
67 final List<GeneratedType> genTypes = new ArrayList<GeneratedType>();
69 basePackageName = resolveBasePackageName(module.getNamespace(),
70 module.getYangVersion());
72 traverseModule(module);
73 if (schemaContainers.size() > 0) {
74 for (final ContainerSchemaNode container : schemaContainers) {
75 genTypes.add(containerToGenType(container));
79 if (schemaLists.size() > 0) {
80 for (final ListSchemaNode list : schemaLists) {
81 genTypes.add(listToGenType(list));
88 private String resolveGeneratedTypePackageName(final SchemaPath schemaPath) {
89 final StringBuilder builder = new StringBuilder();
90 builder.append(basePackageName);
91 if ((schemaPath != null) && (schemaPath.getPath() != null)) {
92 final List<QName> pathToNode = schemaPath.getPath();
93 for (int i = 0; i < pathToNode.size(); ++i) {
95 String nodeLocalName = pathToNode.get(i).getLocalName();
97 // TODO: create method
98 nodeLocalName = nodeLocalName.replace(":", ".");
99 nodeLocalName = nodeLocalName.replace("-", ".");
100 builder.append(nodeLocalName);
102 return builder.toString();
107 private GeneratedType containerToGenType(ContainerSchemaNode container) {
108 if (container == null) {
111 final Set<DataSchemaNode> schemaNodes = container.getChildNodes();
112 final GeneratedTypeBuilder typeBuilder = addRawInterfaceDefinition(container);
114 for (final DataSchemaNode node : schemaNodes) {
115 if (node instanceof LeafSchemaNode) {
116 resolveLeafSchemaNode(typeBuilder, (LeafSchemaNode) node);
117 } else if (node instanceof LeafListSchemaNode) {
118 resolveLeafListSchemaNode(typeBuilder,
119 (LeafListSchemaNode) node);
121 } else if (node instanceof ContainerSchemaNode) {
122 resolveContainerSchemaNode(typeBuilder,
123 (ContainerSchemaNode) node);
124 } else if (node instanceof ListSchemaNode) {
125 resolveListSchemaNode(typeBuilder, (ListSchemaNode) node);
128 return typeBuilder.toInstance();
131 private boolean resolveLeafSchemaNode(
132 final GeneratedTypeBuilder typeBuilder, final LeafSchemaNode node) {
133 if ((node != null) && (typeBuilder != null)) {
134 final String nodeName = node.getQName().getLocalName();
135 String nodeDesc = node.getDescription();
136 if (nodeDesc == null) {
140 if (nodeName != null) {
141 final TypeDefinition<?> typeDef = node.getType();
142 final Type javaType = typeProvider
143 .javaTypeForSchemaDefinitionType(typeDef);
145 constructGetter(typeBuilder, nodeName, nodeDesc, javaType);
146 if (!node.isConfiguration()) {
147 constructSetter(typeBuilder, nodeName, nodeDesc, javaType);
155 private boolean resolveLeafListSchemaNode(
156 final GeneratedTypeBuilder typeBuilder,
157 final LeafListSchemaNode node) {
158 if ((node != null) && (typeBuilder != null)) {
159 final String nodeName = node.getQName().getLocalName();
160 String nodeDesc = node.getDescription();
161 if (nodeDesc == null) {
165 if (nodeName != null) {
166 final TypeDefinition<?> type = node.getType();
167 final Type listType = Types.listTypeFor(typeProvider
168 .javaTypeForSchemaDefinitionType(type));
170 constructGetter(typeBuilder, nodeName, nodeDesc, listType);
171 if (!node.isConfiguration()) {
172 constructSetter(typeBuilder, nodeName, nodeDesc, listType);
180 private boolean resolveContainerSchemaNode(
181 final GeneratedTypeBuilder typeBuilder,
182 final ContainerSchemaNode node) {
183 if ((node != null) && (typeBuilder != null)) {
184 final String nodeName = node.getQName().getLocalName();
186 if (nodeName != null) {
187 final GeneratedTypeBuilder rawGenType = addRawInterfaceDefinition(node);
188 constructGetter(typeBuilder, nodeName, "", rawGenType);
196 private boolean resolveListSchemaNode(
197 final GeneratedTypeBuilder typeBuilder, final ListSchemaNode node) {
198 if ((node != null) && (typeBuilder != null)) {
199 final String nodeName = node.getQName().getLocalName();
201 if (nodeName != null) {
202 final GeneratedTypeBuilder rawGenType = addRawInterfaceDefinition(node);
203 constructGetter(typeBuilder, nodeName, "",
204 Types.listTypeFor(rawGenType));
205 if (!node.isConfiguration()) {
206 constructSetter(typeBuilder, nodeName, "",
207 Types.listTypeFor(rawGenType));
215 private GeneratedTypeBuilder addRawInterfaceDefinition(
216 final DataSchemaNode schemaNode) {
217 if (schemaNode == null) {
221 final String packageName = resolveGeneratedTypePackageName(schemaNode
223 final String schemaNodeName = schemaNode.getQName().getLocalName();
225 if ((packageName != null) && (schemaNode != null)
226 && (schemaNodeName != null)) {
227 final String genTypeName = CodeGeneratorHelper
228 .parseToClassName(schemaNodeName);
229 final GeneratedTypeBuilder newType = new GeneratedTypeBuilderImpl(
230 packageName, genTypeName);
232 if (!genTypeBuilders.containsKey(packageName)) {
233 final Map<String, GeneratedTypeBuilder> builders = new HashMap<String, GeneratedTypeBuilder>();
234 builders.put(genTypeName, newType);
235 genTypeBuilders.put(packageName, builders);
237 final Map<String, GeneratedTypeBuilder> builders = genTypeBuilders
239 if (!builders.containsKey(genTypeName)) {
240 builders.put(genTypeName, newType);
249 private String getterMethodName(final String methodName) {
250 final StringBuilder method = new StringBuilder();
251 method.append("get");
252 method.append(CodeGeneratorHelper.parseToClassName(methodName));
253 return method.toString();
256 private String setterMethodName(final String methodName) {
257 final StringBuilder method = new StringBuilder();
258 method.append("set");
259 method.append(CodeGeneratorHelper.parseToClassName(methodName));
260 return method.toString();
263 private MethodSignatureBuilder constructGetter(
264 final GeneratedTypeBuilder interfaceBuilder,
265 final String schemaNodeName, final String comment,
266 final Type returnType) {
267 final MethodSignatureBuilder getMethod = interfaceBuilder
268 .addMethod(getterMethodName(schemaNodeName));
270 getMethod.addComment(comment);
271 getMethod.addReturnType(returnType);
276 private MethodSignatureBuilder constructSetter(
277 final GeneratedTypeBuilder interfaceBuilder,
278 final String schemaNodeName, final String comment,
279 final Type parameterType) {
280 final MethodSignatureBuilder setMethod = interfaceBuilder
281 .addMethod(setterMethodName(schemaNodeName));
283 setMethod.addComment(comment);
284 setMethod.addParameter(parameterType,
285 CodeGeneratorHelper.parseToParamName(schemaNodeName));
286 setMethod.addReturnType(Types.voidType());
291 private boolean isCompositeKey(final String keyDefinition) {
292 if (keyDefinition.contains(" ")) {
298 private String resolveBasePackageName(final URI moduleNamespace,
299 final String yangVersion) {
300 final StringBuilder packageNameBuilder = new StringBuilder();
302 packageNameBuilder.append("com.cisco.yang.gen.v");
303 packageNameBuilder.append(yangVersion);
304 packageNameBuilder.append(".rev");
305 packageNameBuilder.append(calendar.get(Calendar.YEAR));
306 packageNameBuilder.append((calendar.get(Calendar.MONTH) + 1));
307 packageNameBuilder.append(calendar.get(Calendar.DAY_OF_MONTH));
308 packageNameBuilder.append(".");
310 String namespace = moduleNamespace.toString();
311 namespace = namespace.replace(":", ".");
312 namespace = namespace.replace("-", ".");
314 packageNameBuilder.append(namespace);
316 return packageNameBuilder.toString();
319 private GeneratedType listToGenType(ListSchemaNode list) {
323 final GeneratedTypeBuilder typeBuilder = resolveListTypeBuilder(list);
325 final Set<DataSchemaNode> schemaNodes = list.getChildNodes();
326 for (final DataSchemaNode node : schemaNodes) {
327 if (node instanceof LeafSchemaNode) {
328 resolveLeafSchemaNode(typeBuilder, (LeafSchemaNode) node);
329 } else if (node instanceof LeafListSchemaNode) {
330 resolveLeafListSchemaNode(typeBuilder,
331 (LeafListSchemaNode) node);
332 } else if (node instanceof ContainerSchemaNode) {
333 resolveContainerSchemaNode(typeBuilder,
334 (ContainerSchemaNode) node);
335 } else if (node instanceof ListSchemaNode) {
336 resolveListSchemaNode(typeBuilder, (ListSchemaNode) node);
339 return typeBuilder.toInstance();
342 private GeneratedTypeBuilder resolveListTypeBuilder(
343 final ListSchemaNode list) {
344 final String packageName = resolveGeneratedTypePackageName(list
346 final String schemaNodeName = list.getQName().getLocalName();
347 final String genTypeName = CodeGeneratorHelper
348 .parseToClassName(schemaNodeName);
350 GeneratedTypeBuilder typeBuilder = null;
351 if (genTypeBuilders.containsKey(packageName)) {
352 final Map<String, GeneratedTypeBuilder> builders = new HashMap<String, GeneratedTypeBuilder>();
353 typeBuilder = builders.get(genTypeName);
355 if (null == typeBuilder) {
356 typeBuilder = addRawInterfaceDefinition(list);
362 private void traverseModule(final Module module) {
363 final Set<DataSchemaNode> schemaNodes = module.getChildNodes();
365 for (DataSchemaNode node : schemaNodes) {
366 if (node instanceof ContainerSchemaNode) {
367 schemaContainers.add((ContainerSchemaNode) node);
368 traverse((ContainerSchemaNode) node);
373 private void traverse(final DataNodeContainer dataNode) {
374 if (!containChildDataNodeContainer(dataNode)) {
378 final Set<DataSchemaNode> childs = dataNode.getChildNodes();
379 if (childs != null) {
380 for (DataSchemaNode childNode : childs) {
381 if (childNode instanceof ContainerSchemaNode) {
382 final ContainerSchemaNode container = (ContainerSchemaNode) childNode;
383 schemaContainers.add(container);
387 if (childNode instanceof ListSchemaNode) {
388 final ListSchemaNode list = (ListSchemaNode) childNode;
389 schemaLists.add(list);
397 * Returns <code>true</code> if and only if the child node contain at least
398 * one child container schema node or child list schema node, otherwise will
399 * always returns <code>false</code>
402 * @return <code>true</code> if and only if the child node contain at least
403 * one child container schema node or child list schema node,
404 * otherwise will always returns <code>false</code>
406 private boolean containChildDataNodeContainer(
407 final DataNodeContainer container) {
408 if (container != null) {
409 final Set<DataSchemaNode> childs = container.getChildNodes();
410 if ((childs != null) && (childs.size() > 0)) {
411 for (final DataSchemaNode childNode : childs) {
412 if (childNode instanceof DataNodeContainer) {