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.yangtools.sal.binding.yang.types;
10 import static org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil.*;
11 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.*;
13 import java.math.BigDecimal;
14 import java.math.BigInteger;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.Comparator;
19 import java.util.HashMap;
20 import java.util.List;
23 import java.util.TreeMap;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
27 import org.apache.commons.lang3.StringEscapeUtils;
28 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
29 import org.opendaylight.yangtools.binding.generator.util.TypeConstants;
30 import org.opendaylight.yangtools.binding.generator.util.Types;
31 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.EnumerationBuilderImpl;
32 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
33 import org.opendaylight.yangtools.binding.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
34 import org.opendaylight.yangtools.sal.binding.generator.spi.TypeProvider;
35 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
36 import org.opendaylight.yangtools.sal.binding.model.api.Enumeration;
37 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
38 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
39 import org.opendaylight.yangtools.sal.binding.model.api.Type;
40 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.EnumBuilder;
41 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedPropertyBuilder;
42 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
43 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilderBase;
44 import org.opendaylight.yangtools.yang.common.QName;
45 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
46 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
47 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
48 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
50 import org.opendaylight.yangtools.yang.model.api.Module;
51 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
52 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
53 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
54 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
55 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
56 import org.opendaylight.yangtools.yang.model.api.YangNode;
57 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
58 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
59 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
60 import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
61 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
62 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
63 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
64 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
65 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
66 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
67 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
68 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
69 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
70 import org.opendaylight.yangtools.yang.model.util.DataNodeIterator;
71 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
72 import org.opendaylight.yangtools.yang.model.util.Int16;
73 import org.opendaylight.yangtools.yang.model.util.Int32;
74 import org.opendaylight.yangtools.yang.model.util.Int64;
75 import org.opendaylight.yangtools.yang.model.util.Int8;
76 import org.opendaylight.yangtools.yang.model.util.StringType;
77 import org.opendaylight.yangtools.yang.model.util.Uint16;
78 import org.opendaylight.yangtools.yang.model.util.Uint32;
79 import org.opendaylight.yangtools.yang.model.util.Uint64;
80 import org.opendaylight.yangtools.yang.model.util.Uint8;
81 import org.opendaylight.yangtools.yang.model.util.UnionType;
82 import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
84 import com.google.common.base.Preconditions;
85 import com.google.common.io.BaseEncoding;
87 public final class TypeProviderImpl implements TypeProvider {
89 * Contains the schema data red from YANG files.
91 private final SchemaContext schemaContext;
94 * The outter map maps module names to the map of the types for the module.
95 * The inner map maps the name of the concrete type to the JAVA
96 * <code>Type</code> (usually it is generated TO).
98 private Map<String, Map<String, Type>> genTypeDefsContextMap;
101 * The map which maps schema paths to JAVA <code>Type</code>.
103 private final Map<SchemaPath, Type> referencedTypes;
106 * Creates new instance of class <code>TypeProviderImpl</code>.
108 * @param schemaContext
109 * contains the schema data red from YANG files
110 * @throws IllegalArgumentException
111 * if <code>schemaContext</code> equal null.
113 public TypeProviderImpl(final SchemaContext schemaContext) {
114 Preconditions.checkArgument(schemaContext != null, "Schema Context cannot be null!");
116 this.schemaContext = schemaContext;
117 this.genTypeDefsContextMap = new HashMap<>();
118 this.referencedTypes = new HashMap<>();
119 resolveTypeDefsFromContext();
123 * Puts <code>refType</code> to map with key <code>refTypePath</code>
126 * schema path used as the map key
128 * type which represents the map value
129 * @throws IllegalArgumentException
131 * <li>if <code>refTypePath</code> equal null</li>
132 * <li>if <code>refType</code> equal null</li>
136 public void putReferencedType(final SchemaPath refTypePath, final Type refType) {
137 Preconditions.checkArgument(refTypePath != null,
138 "Path reference of Enumeration Type Definition cannot be NULL!");
139 Preconditions.checkArgument(refType != null, "Reference to Enumeration Type cannot be NULL!");
140 referencedTypes.put(refTypePath, refType);
145 * Converts basic YANG type <code>type</code> to JAVA <code>Type</code>.
148 * string with YANG name of type
149 * @return JAVA <code>Type</code> for YANG type <code>type</code>
150 * @see TypeProvider#javaTypeForYangType(String)
153 public Type javaTypeForYangType(String type) {
154 return BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForYangType(type);
158 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
159 return javaTypeForSchemaDefinitionType(typeDefinition, parentNode, null);
163 * Converts schema definition type <code>typeDefinition</code> to JAVA
166 * @param typeDefinition
167 * type definition which is converted to JAVA type
168 * @throws IllegalArgumentException
170 * <li>if <code>typeDefinition</code> equal null</li>
171 * <li>if Q name of <code>typeDefinition</code> equal null</li>
172 * <li>if name of <code>typeDefinition</code> equal null</li>
176 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode, Restrictions r) {
177 Type returnType = null;
178 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
179 if (typeDefinition.getQName() == null) {
180 throw new IllegalArgumentException(
181 "Type Definition cannot have non specified QName (QName cannot be NULL!)");
183 Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
184 "Type Definitions Local Name cannot be NULL!");
186 if (typeDefinition instanceof ExtendedType) {
187 returnType = javaTypeForExtendedType(typeDefinition);
189 returnType = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode);
190 if (returnType == null) {
191 returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition,
195 // TODO: add throw exception when we will be able to resolve ALL yang
197 // if (returnType == null) {
198 // throw new IllegalArgumentException("Type Provider can't resolve " +
199 // "type for specified Type Definition " + typedefName);
205 * Returns JAVA <code>Type</code> for instances of the type
206 * <code>LeafrefTypeDefinition</code> or
207 * <code>IdentityrefTypeDefinition</code>.
209 * @param typeDefinition
210 * type definition which is converted to JAVA <code>Type</code>
211 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
213 private Type javaTypeForLeafrefOrIdentityRef(TypeDefinition<?> typeDefinition, SchemaNode parentNode) {
214 if (typeDefinition instanceof LeafrefTypeDefinition) {
215 final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition;
216 return provideTypeForLeafref(leafref, parentNode);
217 } else if (typeDefinition instanceof IdentityrefTypeDefinition) {
218 final IdentityrefTypeDefinition idref = (IdentityrefTypeDefinition) typeDefinition;
219 return provideTypeForIdentityref(idref);
226 * Returns JAVA <code>Type</code> for instances of the type
227 * <code>ExtendedType</code>.
229 * @param typeDefinition
230 * type definition which is converted to JAVA <code>Type</code>
231 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
233 private Type javaTypeForExtendedType(TypeDefinition<?> typeDefinition) {
234 final String typedefName = typeDefinition.getQName().getLocalName();
235 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
236 Type returnType = null;
237 returnType = javaTypeForLeafrefOrIdentityRef(baseTypeDef, typeDefinition);
238 if (returnType == null) {
239 if (baseTypeDef instanceof EnumTypeDefinition) {
240 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDef;
241 returnType = provideTypeForEnum(enumTypeDef, typedefName, typeDefinition);
243 final Module module = findParentModule(schemaContext, typeDefinition);
244 Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
245 if (module != null) {
246 final Map<String, Type> genTOs = genTypeDefsContextMap.get(module.getName());
247 if (genTOs != null) {
248 returnType = genTOs.get(typedefName);
250 if (returnType == null) {
251 returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
252 baseTypeDef, typeDefinition, r);
258 // TODO: add throw exception when we will be able to resolve ALL yang
260 // if (returnType == null) {
261 // throw new IllegalArgumentException("Type Provider can't resolve " +
262 // "type for specified Type Definition " + typedefName);
267 * Seeks for identity reference <code>idref</code> the JAVA
268 * <code>type</code>.<br />
272 * If identy which is referenced via <code>idref</code> has name <b>Idn</b>
273 * then returning type is <b>{@code Class<? extends Idn>}</b></i>
276 * identityref type definition for which JAVA <code>Type</code>
278 * @return JAVA <code>Type</code> of the identity which is refrenced through
281 private Type provideTypeForIdentityref(IdentityrefTypeDefinition idref) {
282 QName baseIdQName = idref.getIdentity().getQName();
283 Module module = schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
284 baseIdQName.getRevision());
285 IdentitySchemaNode identity = null;
286 for (IdentitySchemaNode id : module.getIdentities()) {
287 if (id.getQName().equals(baseIdQName)) {
291 Preconditions.checkArgument(identity != null, "Target identity '" + baseIdQName + "' do not exists");
293 final String basePackageName = moduleNamespaceToPackageName(module);
294 final String packageName = packageNameForGeneratedType(basePackageName, identity.getPath());
295 final String genTypeName = parseToClassName(identity.getQName().getLocalName());
297 Type baseType = Types.typeForClass(Class.class);
298 Type paramType = Types.wildcardTypeFor(packageName, genTypeName);
299 return Types.parameterizedTypeFor(baseType, paramType);
303 * Converts <code>typeDefinition</code> to concrete JAVA <code>Type</code>.
305 * @param typeDefinition
306 * type definition which should be converted to JAVA
308 * @return JAVA <code>Type</code> which represents
309 * <code>typeDefinition</code>
310 * @throws IllegalArgumentException
312 * <li>if <code>typeDefinition</code> equal null</li>
313 * <li>if Q name of <code>typeDefinition</code></li>
314 * <li>if name of <code>typeDefinition</code></li>
317 public Type generatedTypeForExtendedDefinitionType(final TypeDefinition<?> typeDefinition,
318 final SchemaNode parentNode) {
319 Type returnType = null;
320 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
321 if (typeDefinition.getQName() == null) {
322 throw new IllegalArgumentException(
323 "Type Definition cannot have non specified QName (QName cannot be NULL!)");
325 Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
326 "Type Definitions Local Name cannot be NULL!");
328 final String typedefName = typeDefinition.getQName().getLocalName();
329 if (typeDefinition instanceof ExtendedType) {
330 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
332 if (!(baseTypeDef instanceof LeafrefTypeDefinition) && !(baseTypeDef instanceof IdentityrefTypeDefinition)) {
333 final Module module = findParentModule(schemaContext, parentNode);
335 if (module != null) {
336 final Map<String, Type> genTOs = genTypeDefsContextMap.get(module.getName());
337 if (genTOs != null) {
338 returnType = genTOs.get(typedefName);
347 * Gets base type definition for <code>extendTypeDef</code>. The method is
348 * recursivelly called until non <code>ExtendedType</code> type is found.
350 * @param extendTypeDef
351 * type definition for which is the base type definition sought
352 * @return type definition which is base type for <code>extendTypeDef</code>
353 * @throws IllegalArgumentException
354 * if <code>extendTypeDef</code> equal null
356 private TypeDefinition<?> baseTypeDefForExtendedType(final TypeDefinition<?> extendTypeDef) {
357 Preconditions.checkArgument(extendTypeDef != null, "Type Definiition reference cannot be NULL!");
358 final TypeDefinition<?> baseTypeDef = extendTypeDef.getBaseType();
359 if (baseTypeDef instanceof ExtendedType) {
360 return baseTypeDefForExtendedType(baseTypeDef);
368 * Converts <code>leafrefType</code> to JAVA <code>Type</code>.
370 * The path of <code>leafrefType</code> is followed to find referenced node
371 * and its <code>Type</code> is returned.
374 * leafref type definition for which is the type sought
375 * @return JAVA <code>Type</code> of data schema node which is referenced in
376 * <code>leafrefType</code>
377 * @throws IllegalArgumentException
379 * <li>if <code>leafrefType</code> equal null</li>
380 * <li>if path statement of <code>leafrefType</code> equal null</li>
384 public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode) {
385 Type returnType = null;
386 Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!");
388 Preconditions.checkArgument(leafrefType.getPathStatement() != null,
389 "The Path Statement for Leafref Type Definition cannot be NULL!");
391 final RevisionAwareXPath xpath = leafrefType.getPathStatement();
392 final String strXPath = xpath.toString();
394 if (strXPath != null) {
395 if (strXPath.contains("[")) {
396 returnType = Types.typeForClass(Object.class);
398 final Module module = findParentModule(schemaContext, parentNode);
399 if (module != null) {
400 final SchemaNode dataNode;
401 if (xpath.isAbsolute()) {
402 dataNode = findDataSchemaNode(schemaContext, module, xpath);
404 dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
407 if (leafContainsEnumDefinition(dataNode)) {
408 returnType = referencedTypes.get(dataNode.getPath());
409 } else if (leafListContainsEnumDefinition(dataNode)) {
410 returnType = Types.listTypeFor(referencedTypes.get(dataNode.getPath()));
412 returnType = resolveTypeFromDataSchemaNode(dataNode);
421 * Checks if <code>dataNode</code> is <code>LeafSchemaNode</code> and if it
422 * so then checks if it is of type <code>EnumTypeDefinition</code>.
425 * data schema node for which is checked if it is leaf and if it
427 * @return boolean value
429 * <li>true - if <code>dataNode</code> is leaf of type enumeration</li>
430 * <li>false - other cases</li>
433 private boolean leafContainsEnumDefinition(final SchemaNode dataNode) {
434 if (dataNode instanceof LeafSchemaNode) {
435 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
436 if (leaf.getType() instanceof EnumTypeDefinition) {
444 * Checks if <code>dataNode</code> is <code>LeafListSchemaNode</code> and if
445 * it so then checks if it is of type <code>EnumTypeDefinition</code>.
448 * data schema node for which is checked if it is leaflist and if
450 * @return boolean value
452 * <li>true - if <code>dataNode</code> is leaflist of type
454 * <li>false - other cases</li>
457 private boolean leafListContainsEnumDefinition(final SchemaNode dataNode) {
458 if (dataNode instanceof LeafListSchemaNode) {
459 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
460 if (leafList.getType() instanceof EnumTypeDefinition) {
468 * Converts <code>enumTypeDef</code> to
469 * {@link org.opendaylight.yangtools.sal.binding.model.api.Enumeration
473 * enumeration type definition which is converted to enumeration
475 * string with name which is used as the enumeration name
476 * @return enumeration type which is built with data (name, enum values)
477 * from <code>enumTypeDef</code>
478 * @throws IllegalArgumentException
480 * <li>if <code>enumTypeDef</code> equals null</li>
481 * <li>if enum values of <code>enumTypeDef</code> equal null</li>
482 * <li>if Q name of <code>enumTypeDef</code> equal null</li>
483 * <li>if name of <code>enumTypeDef</code> equal null</li>
486 private Enumeration provideTypeForEnum(final EnumTypeDefinition enumTypeDef, final String enumName,
487 final SchemaNode parentNode) {
488 Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
489 Preconditions.checkArgument(enumTypeDef.getValues() != null,
490 "EnumTypeDefinition MUST contain at least ONE value definition!");
491 Preconditions.checkArgument(enumTypeDef.getQName() != null, "EnumTypeDefinition MUST contain NON-NULL QName!");
492 Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
493 "Local Name in EnumTypeDefinition QName cannot be NULL!");
495 final String enumerationName = parseToClassName(enumName);
497 Module module = findParentModule(schemaContext, parentNode);
498 final String basePackageName = moduleNamespaceToPackageName(module);
500 final EnumBuilder enumBuilder = new EnumerationBuilderImpl(basePackageName, enumerationName);
501 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
502 return enumBuilder.toInstance(null);
506 * Adds enumeration to <code>typeBuilder</code>. The enumeration data are
507 * taken from <code>enumTypeDef</code>.
510 * enumeration type definition is source of enumeration data for
511 * <code>typeBuilder</code>
513 * string with the name of enumeration
515 * generated type builder to which is enumeration added
516 * @return enumeration type which contains enumeration data form
517 * <code>enumTypeDef</code>
518 * @throws IllegalArgumentException
520 * <li>if <code>enumTypeDef</code> equals null</li>
521 * <li>if enum values of <code>enumTypeDef</code> equal null</li>
522 * <li>if Q name of <code>enumTypeDef</code> equal null</li>
523 * <li>if name of <code>enumTypeDef</code> equal null</li>
524 * <li>if name of <code>typeBuilder</code> equal null</li>
528 private Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef, final String enumName,
529 final GeneratedTypeBuilderBase<?> typeBuilder) {
530 Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
531 Preconditions.checkArgument(enumTypeDef.getValues() != null,
532 "EnumTypeDefinition MUST contain at least ONE value definition!");
533 Preconditions.checkArgument(enumTypeDef.getQName() != null, "EnumTypeDefinition MUST contain NON-NULL QName!");
534 Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
535 "Local Name in EnumTypeDefinition QName cannot be NULL!");
536 Preconditions.checkArgument(typeBuilder != null, "Generated Type Builder reference cannot be NULL!");
538 final String enumerationName = parseToClassName(enumName);
540 final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumerationName);
541 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
542 return enumBuilder.toInstance(enumBuilder);
546 * Converts <code>dataNode</code> to JAVA <code>Type</code>.
549 * contains information about YANG type
550 * @return JAVA <code>Type</code> representation of <code>dataNode</code>
552 private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode) {
553 Type returnType = null;
554 if (dataNode != null) {
555 if (dataNode instanceof LeafSchemaNode) {
556 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
557 returnType = javaTypeForSchemaDefinitionType(leaf.getType(), leaf);
558 } else if (dataNode instanceof LeafListSchemaNode) {
559 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
560 returnType = javaTypeForSchemaDefinitionType(leafList.getType(), leafList);
567 * Passes through all modules and through all its type definitions and
568 * convert it to generated types.
570 * The modules are firstly sorted by mutual dependencies. The modules are
571 * sequentially passed. All type definitions of a module are at the
572 * beginning sorted so that type definition with less amount of references
573 * to other type definition are processed first.<br />
574 * For each module is created mapping record in the map
575 * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap}
576 * which map current module name to the map which maps type names to
577 * returned types (generated types).
580 private void resolveTypeDefsFromContext() {
581 final Set<Module> modules = schemaContext.getModules();
582 Preconditions.checkArgument(modules != null, "Sef of Modules cannot be NULL!");
583 final Module[] modulesArray = new Module[modules.size()];
585 for (Module modul : modules) {
586 modulesArray[i++] = modul;
588 final List<Module> modulesSortedByDependency = ModuleDependencySort.sort(modulesArray);
590 for (final Module module : modulesSortedByDependency) {
591 if (module == null) {
594 final String moduleName = module.getName();
595 final String basePackageName = moduleNamespaceToPackageName(module);
597 final DataNodeIterator it = new DataNodeIterator(module);
598 final List<TypeDefinition<?>> typeDefinitions = it.allTypedefs();
599 final List<TypeDefinition<?>> listTypeDefinitions = sortTypeDefinitionAccordingDepth(typeDefinitions);
601 final Map<String, Type> typeMap = new HashMap<>();
602 genTypeDefsContextMap.put(moduleName, typeMap);
604 if ((listTypeDefinitions != null) && (basePackageName != null)) {
605 for (final TypeDefinition<?> typedef : listTypeDefinitions) {
606 typedefToGeneratedType(basePackageName, moduleName, typedef);
614 * @param basePackageName
615 * string with name of package to which the module belongs
617 * string with the name of the module for to which the
618 * <code>typedef</code> belongs
620 * type definition of the node for which should be creted JAVA
621 * <code>Type</code> (usually generated TO)
622 * @return JAVA <code>Type</code> representation of <code>typedef</code> or
623 * <code>null</code> value if <code>basePackageName</code> or
624 * <code>modulName</code> or <code>typedef</code> or Q name of
625 * <code>typedef</code> equals <code>null</code>
627 private Type typedefToGeneratedType(final String basePackageName, final String moduleName,
628 final TypeDefinition<?> typedef) {
629 if ((basePackageName != null) && (moduleName != null) && (typedef != null) && (typedef.getQName() != null)) {
631 final String typedefName = typedef.getQName().getLocalName();
632 final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
633 if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
634 && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) {
635 Type returnType = null;
636 if (innerTypeDefinition instanceof ExtendedType) {
637 ExtendedType innerExtendedType = (ExtendedType) innerTypeDefinition;
638 returnType = provideGeneratedTOFromExtendedType(typedef, innerExtendedType, basePackageName);
639 } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
640 final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
641 (UnionTypeDefinition) innerTypeDefinition, typedefName, typedef);
642 genTOBuilder.setIsUnion(true);
643 addUnitsToGenTO(genTOBuilder, typedef.getUnits());
644 returnType = genTOBuilder.toInstance();
645 } else if (innerTypeDefinition instanceof EnumTypeDefinition) {
646 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypeDefinition;
647 // TODO units for typedef enum
648 returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef);
649 } else if (innerTypeDefinition instanceof BitsTypeDefinition) {
650 final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition;
651 final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForBitsTypeDefinition(
652 basePackageName, bitsTypeDefinition, typedefName);
653 addUnitsToGenTO(genTOBuilder, typedef.getUnits());
654 returnType = genTOBuilder.toInstance();
656 final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
657 innerTypeDefinition, typedef);
658 returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType);
660 if (returnType != null) {
661 final Map<String, Type> typeMap = genTypeDefsContextMap.get(moduleName);
662 if (typeMap != null) {
663 typeMap.put(typedefName, returnType);
673 * Wraps base YANG type to generated TO.
675 * @param basePackageName
676 * string with name of package to which the module belongs
678 * type definition which is converted to the TO
680 * JAVA <code>Type</code> to which is <code>typedef</code> mapped
681 * @return generated transfer object which represent<code>javaType</code>
683 private GeneratedTransferObject wrapJavaTypeIntoTO(final String basePackageName, final TypeDefinition<?> typedef,
684 final Type javaType) {
685 Preconditions.checkNotNull(javaType, "javaType cannot be null");
686 final String propertyName = "value";
688 final GeneratedTOBuilder genTOBuilder = typedefToTransferObject(basePackageName, typedef);
689 genTOBuilder.setRestrictions(BindingGeneratorUtil.getRestrictions(typedef));
690 final GeneratedPropertyBuilder genPropBuilder = genTOBuilder.addProperty(propertyName);
691 genPropBuilder.setReturnType(javaType);
692 genTOBuilder.addEqualsIdentity(genPropBuilder);
693 genTOBuilder.addHashIdentity(genPropBuilder);
694 genTOBuilder.addToStringProperty(genPropBuilder);
695 if (javaType instanceof ConcreteType && "String".equals(javaType.getName()) && typedef instanceof ExtendedType) {
696 final List<String> regExps = resolveRegExpressionsFromTypedef((ExtendedType) typedef);
697 addStringRegExAsConstant(genTOBuilder, regExps);
699 addUnitsToGenTO(genTOBuilder, typedef.getUnits());
700 return genTOBuilder.toInstance();
704 * Converts output list of generated TO builders to one TO builder (first
705 * from list) which contains the remaining builders as its enclosing TO.
707 * @param basePackageName
708 * string with name of package to which the module belongs
710 * type definition which should be of type
711 * <code>UnionTypeDefinition</code>
713 * string with name for generated TO
714 * @return generated TO builder with the list of enclosed generated TO
717 public GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final String basePackageName,
718 final UnionTypeDefinition typedef, String typeDefName, SchemaNode parentNode) {
719 final List<GeneratedTOBuilder> genTOBuilders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
720 typedef, typeDefName, parentNode);
721 GeneratedTOBuilder resultTOBuilder = null;
722 if (!genTOBuilders.isEmpty()) {
723 resultTOBuilder = genTOBuilders.get(0);
724 genTOBuilders.remove(0);
725 for (GeneratedTOBuilder genTOBuilder : genTOBuilders) {
726 resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
729 return resultTOBuilder;
733 * Converts <code>typedef</code> to generated TO with
734 * <code>typeDefName</code>. Every union type from <code>typedef</code> is
735 * added to generated TO builder as property.
737 * @param basePackageName
738 * string with name of package to which the module belongs
740 * type definition which should be of type
741 * <code>UnionTypeDefinition</code>
743 * string with name for generated TO
744 * @return generated TO builder which represents <code>typedef</code>
745 * @throws IllegalArgumentException
747 * <li>if <code>basePackageName</code> equals null</li>
748 * <li>if <code>typedef</code> equals null</li>
749 * <li>if Q name of <code>typedef</code> equals null</li>
752 public List<GeneratedTOBuilder> provideGeneratedTOBuildersForUnionTypeDef(final String basePackageName,
753 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode) {
754 Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
755 Preconditions.checkArgument(typedef != null, "Type Definition cannot be NULL!");
756 Preconditions.checkArgument(typedef.getQName() != null,
757 "Type Definition cannot have non specified QName (QName cannot be NULL!)");
759 final List<GeneratedTOBuilder> generatedTOBuilders = new ArrayList<>();
761 if (typedef != null) {
762 final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
764 final GeneratedTOBuilder unionGenTOBuilder;
765 if (typeDefName != null && !typeDefName.isEmpty()) {
766 final String typeName = parseToClassName(typeDefName);
767 unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
769 unionGenTOBuilder = typedefToTransferObject(basePackageName, typedef);
771 generatedTOBuilders.add(unionGenTOBuilder);
772 unionGenTOBuilder.setIsUnion(true);
773 final List<String> regularExpressions = new ArrayList<String>();
774 for (final TypeDefinition<?> unionType : unionTypes) {
775 final String unionTypeName = unionType.getQName().getLocalName();
776 if (unionType instanceof UnionType) {
777 generatedTOBuilders.addAll(resolveUnionSubtypeAsUnion(unionGenTOBuilder, (UnionType) unionType,
778 basePackageName, parentNode));
779 } else if (unionType instanceof ExtendedType) {
780 resolveExtendedSubtypeAsUnion(unionGenTOBuilder, (ExtendedType) unionType, unionTypeName,
781 regularExpressions, parentNode);
782 } else if (unionType instanceof EnumTypeDefinition) {
783 final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType,
784 unionTypeName, unionGenTOBuilder);
785 updateUnionTypeAsProperty(unionGenTOBuilder, enumeration, unionTypeName);
787 final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
788 unionType, parentNode);
789 updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName);
792 if (!regularExpressions.isEmpty()) {
793 addStringRegExAsConstant(unionGenTOBuilder, regularExpressions);
796 storeGenTO(typedef, unionGenTOBuilder, parentNode);
798 return generatedTOBuilders;
802 * Wraps code which handle case when union subtype is also of the type
803 * <code>UnionType</code>.
805 * In this case the new generated TO is created for union subtype (recursive
807 * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, TypeDefinition, String)
808 * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder
809 * <code>parentUnionGenTOBuilder</code> is created property which type is
810 * equal to new generated TO.
812 * @param parentUnionGenTOBuilder
813 * generated TO builder to which is the property with the child
814 * union subtype added
815 * @param basePackageName
816 * string with the name of the module package
817 * @param unionSubtype
818 * type definition which represents union subtype
819 * @return list of generated TO builders. The number of the builders can be
820 * bigger one due to recursive call of
821 * <code>provideGeneratedTOBuildersForUnionTypeDef</code> method.
823 private List<GeneratedTOBuilder> resolveUnionSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
824 final UnionTypeDefinition unionSubtype, final String basePackageName, final SchemaNode parentNode) {
825 final String newTOBuilderName = provideAvailableNameForGenTOBuilder(parentUnionGenTOBuilder.getName());
826 final List<GeneratedTOBuilder> subUnionGenTOBUilders = provideGeneratedTOBuildersForUnionTypeDef(
827 basePackageName, unionSubtype, newTOBuilderName, parentNode);
829 final GeneratedPropertyBuilder propertyBuilder;
830 propertyBuilder = parentUnionGenTOBuilder.addProperty(BindingGeneratorUtil
831 .parseToValidParamName(newTOBuilderName));
832 propertyBuilder.setReturnType(subUnionGenTOBUilders.get(0));
833 parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder);
834 parentUnionGenTOBuilder.addToStringProperty(propertyBuilder);
836 return subUnionGenTOBUilders;
840 * Wraps code which handle case when union subtype is of the type
841 * <code>ExtendedType</code>.
843 * If TO for this type already exists it is used for the creation of the
844 * property in <code>parentUnionGenTOBuilder</code>. In other case the base
845 * type is used for the property creation.
847 * @param parentUnionGenTOBuilder
848 * generated TO builder in which new property is created
849 * @param unionSubtype
850 * type definition of the <code>ExtendedType</code> type which
851 * represents union subtype
852 * @param unionTypeName
853 * string with the name for <code>unionSubtype</code>
854 * @param regularExpressions
855 * list of strings with the regular expressions
857 private void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
858 final ExtendedType unionSubtype, final String unionTypeName, final List<String> regularExpressions,
859 final SchemaNode parentNode) {
860 final Type genTO = findGenTO(unionTypeName, parentNode);
862 updateUnionTypeAsProperty(parentUnionGenTOBuilder, genTO, genTO.getName());
864 final TypeDefinition<?> baseType = baseTypeDefForExtendedType(unionSubtype);
865 if (unionTypeName.equals(baseType.getQName().getLocalName())) {
866 final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType,
868 if (javaType != null) {
869 updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
872 if (baseType instanceof StringType) {
873 regularExpressions.addAll(resolveRegExpressionsFromTypedef(unionSubtype));
879 * Searches for generated TO for <code>searchedTypeDef</code> type
880 * definition in {@link #genTypeDefsContextMap genTypeDefsContextMap}
882 * @param searchedTypeName
883 * string with name of <code>searchedTypeDef</code>
884 * @return generated TO for <code>searchedTypeDef</code> or
885 * <code>null</code> it it doesn't exist
887 private Type findGenTO(final String searchedTypeName, final SchemaNode parentNode) {
888 final Module typeModule = findParentModule(schemaContext, parentNode);
889 if (typeModule != null && typeModule.getName() != null) {
890 final Map<String, Type> genTOs = genTypeDefsContextMap.get(typeModule.getName());
891 if (genTOs != null) {
892 return genTOs.get(searchedTypeName);
899 * Stores generated TO created from <code>genTOBuilder</code> for
900 * <code>newTypeDef</code> to {@link #genTypeDefsContextMap
901 * genTypeDefsContextMap} if the module for <code>newTypeDef</code> exists
904 * type definition for which is <code>genTOBuilder</code> created
905 * @param genTOBuilder
906 * generated TO builder which is converted to generated TO and
909 private void storeGenTO(TypeDefinition<?> newTypeDef, GeneratedTOBuilder genTOBuilder, SchemaNode parentNode) {
910 if (!(newTypeDef instanceof UnionType)) {
911 Map<String, Type> genTOsMap = null;
912 final Module parentModule = findParentModule(schemaContext, parentNode);
913 if (parentModule != null && parentModule.getName() != null) {
914 genTOsMap = genTypeDefsContextMap.get(parentModule.getName());
915 genTOsMap.put(newTypeDef.getQName().getLocalName(), genTOBuilder.toInstance());
921 * Adds a new property with the name <code>propertyName</code> and with type
922 * <code>type</code> to <code>unonGenTransObject</code>.
924 * @param unionGenTransObject
925 * generated TO to which should be property added
927 * JAVA <code>type</code> of the property which should be added
928 * to <code>unionGentransObject</code>
929 * @param propertyName
930 * string with name of property which should be added to
931 * <code>unionGentransObject</code>
933 private void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type,
934 final String propertyName) {
935 if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) {
936 final GeneratedPropertyBuilder propBuilder = unionGenTransObject
937 .addProperty(parseToValidParamName(propertyName));
938 propBuilder.setReturnType(type);
940 unionGenTransObject.addEqualsIdentity(propBuilder);
941 unionGenTransObject.addHashIdentity(propBuilder);
942 unionGenTransObject.addToStringProperty(propBuilder);
947 * Converts <code>typedef</code> to the generated TO builder.
949 * @param basePackageName
950 * string with name of package to which the module belongs
952 * type definition from which is the generated TO builder created
953 * @return generated TO builder which contains data from
954 * <code>typedef</code> and <code>basePackageName</code>
956 private GeneratedTOBuilder typedefToTransferObject(final String basePackageName, final TypeDefinition<?> typedef) {
958 final String packageName = packageNameForGeneratedType(basePackageName, typedef.getPath());
959 final String typeDefTOName = typedef.getQName().getLocalName();
961 if ((packageName != null) && (typedef != null) && (typeDefTOName != null)) {
962 final String genTOName = parseToClassName(typeDefTOName);
963 final GeneratedTOBuilder newType = new GeneratedTOBuilderImpl(packageName, genTOName);
964 newType.addComment(typedef.getDescription());
971 * Converts <code>typeDef</code> which should be of the type
972 * <code>BitsTypeDefinition</code> to <code>GeneratedTOBuilder</code>.
974 * All the bits of the typeDef are added to returning generated TO as
977 * @param basePackageName
978 * string with name of package to which the module belongs
980 * type definition from which is the generated TO builder created
982 * string with the name for generated TO builder
983 * @return generated TO builder which represents <code>typeDef</code>
984 * @throws IllegalArgumentException
986 * <li>if <code>typeDef</code> equals null</li>
987 * <li>if <code>basePackageName</code> equals null</li>
990 public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName,
991 final TypeDefinition<?> typeDef, String typeDefName) {
993 Preconditions.checkArgument(typeDef != null, "typeDef cannot be NULL!");
994 Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
996 if (typeDef instanceof BitsTypeDefinition) {
997 BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
999 final String typeName = parseToClassName(typeDefName);
1000 final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeName);
1002 final List<Bit> bitList = bitsTypeDefinition.getBits();
1003 GeneratedPropertyBuilder genPropertyBuilder;
1004 for (final Bit bit : bitList) {
1005 String name = bit.getName();
1006 genPropertyBuilder = genTOBuilder.addProperty(parseToValidParamName(name));
1007 genPropertyBuilder.setReadOnly(true);
1008 genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE);
1010 genTOBuilder.addEqualsIdentity(genPropertyBuilder);
1011 genTOBuilder.addHashIdentity(genPropertyBuilder);
1012 genTOBuilder.addToStringProperty(genPropertyBuilder);
1015 return genTOBuilder;
1021 * Converts the pattern constraints from <code>typedef</code> to the list of
1022 * the strings which represents these constraints.
1025 * extended type in which are the pattern constraints sought
1026 * @return list of strings which represents the constraint patterns
1027 * @throws IllegalArgumentException
1028 * if <code>typedef</code> equals null
1031 private List<String> resolveRegExpressionsFromTypedef(ExtendedType typedef) {
1032 final List<String> regExps = new ArrayList<String>();
1033 Preconditions.checkArgument(typedef != null, "typedef can't be null");
1034 final TypeDefinition<?> strTypeDef = baseTypeDefForExtendedType(typedef);
1035 if (strTypeDef instanceof StringType) {
1036 final List<PatternConstraint> patternConstraints = typedef.getPatternConstraints();
1037 if (!patternConstraints.isEmpty()) {
1039 String modifiedRegEx;
1040 for (PatternConstraint patternConstraint : patternConstraints) {
1041 regEx = patternConstraint.getRegularExpression();
1042 modifiedRegEx = StringEscapeUtils.escapeJava(regEx);
1043 regExps.add(modifiedRegEx);
1052 * Adds to the <code>genTOBuilder</code> the constant which contains regular
1053 * expressions from the <code>regularExpressions</code>
1055 * @param genTOBuilder
1056 * generated TO builder to which are
1057 * <code>regular expressions</code> added
1058 * @param regularExpressions
1059 * list of string which represent regular expressions
1060 * @throws IllegalArgumentException
1062 * <li>if <code>genTOBuilder</code> equals null</li>
1063 * <li>if <code>regularExpressions</code> equals null</li>
1066 private void addStringRegExAsConstant(GeneratedTOBuilder genTOBuilder, List<String> regularExpressions) {
1067 if (genTOBuilder == null) {
1068 throw new IllegalArgumentException("Generated transfer object builder can't be null");
1070 if (regularExpressions == null) {
1071 throw new IllegalArgumentException("List of regular expressions can't be null");
1073 if (!regularExpressions.isEmpty()) {
1074 genTOBuilder.addConstant(Types.listTypeFor(BaseYangTypes.STRING_TYPE), TypeConstants.PATTERN_CONSTANT_NAME,
1075 regularExpressions);
1080 * Creates generated TO with data about inner extended type
1081 * <code>innerExtendedType</code>, about the package name
1082 * <code>typedefName</code> and about the generated TO name
1083 * <code>typedefName</code>.
1085 * It is supposed that <code>innerExtendedType</code> is already present in
1086 * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap} to
1087 * be possible set it as extended type for the returning generated TO.
1089 * @param innerExtendedType
1090 * extended type which is part of some other extended type
1091 * @param basePackageName
1092 * string with the package name of the module
1093 * @param typedefName
1094 * string with the name for the generated TO
1095 * @return generated TO which extends generated TO for
1096 * <code>innerExtendedType</code>
1097 * @throws IllegalArgumentException
1099 * <li>if <code>extendedType</code> equals null</li>
1100 * <li>if <code>basePackageName</code> equals null</li>
1101 * <li>if <code>typedefName</code> equals null</li>
1104 private GeneratedTransferObject provideGeneratedTOFromExtendedType(final TypeDefinition<?> typedef, final ExtendedType innerExtendedType,
1105 final String basePackageName) {
1106 Preconditions.checkArgument(innerExtendedType != null, "Extended type cannot be NULL!");
1107 Preconditions.checkArgument(basePackageName != null, "String with base package name cannot be NULL!");
1109 final String typedefName = typedef.getQName().getLocalName();
1110 final String classTypedefName = parseToClassName(typedefName);
1111 final String innerTypeDef = innerExtendedType.getQName().getLocalName();
1112 final GeneratedTOBuilder genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, classTypedefName);
1113 Restrictions r = BindingGeneratorUtil.getRestrictions(typedef);
1114 genTOBuilder.setRestrictions(r);
1116 if (baseTypeDefForExtendedType(innerExtendedType) instanceof UnionTypeDefinition) {
1117 genTOBuilder.setIsUnion(true);
1120 Map<String, Type> typeMap = null;
1121 final Module parentModule = findParentModule(schemaContext, innerExtendedType);
1122 if (parentModule != null) {
1123 typeMap = genTypeDefsContextMap.get(parentModule.getName());
1126 if (typeMap != null) {
1127 Type type = typeMap.get(innerTypeDef);
1128 if (type instanceof GeneratedTransferObject) {
1129 genTOBuilder.setExtendsType((GeneratedTransferObject) type);
1132 addUnitsToGenTO(genTOBuilder, typedef.getUnits());
1134 return genTOBuilder.toInstance();
1138 * Finds out for each type definition how many immersion (depth) is
1139 * necessary to get to the base type. Every type definition is inserted to
1140 * the map which key is depth and value is list of type definitions with
1141 * equal depth. In next step are lists from this map concatenated to one
1142 * list in ascending order according to their depth. All type definitions
1143 * are in the list behind all type definitions on which depends.
1145 * @param unsortedTypeDefinitions
1146 * list of type definitions which should be sorted by depth
1147 * @return list of type definitions sorted according their each other
1148 * dependencies (type definitions which are depend on other type
1149 * definitions are in list behind them).
1151 private List<TypeDefinition<?>> sortTypeDefinitionAccordingDepth(
1152 final Collection<TypeDefinition<?>> unsortedTypeDefinitions) {
1153 List<TypeDefinition<?>> sortedTypeDefinition = new ArrayList<>();
1155 Map<Integer, List<TypeDefinition<?>>> typeDefinitionsDepths = new TreeMap<>();
1156 for (TypeDefinition<?> unsortedTypeDefinition : unsortedTypeDefinitions) {
1157 final int depth = getTypeDefinitionDepth(unsortedTypeDefinition);
1158 List<TypeDefinition<?>> typeDefinitionsConcreteDepth = typeDefinitionsDepths.get(depth);
1159 if (typeDefinitionsConcreteDepth == null) {
1160 typeDefinitionsConcreteDepth = new ArrayList<TypeDefinition<?>>();
1161 typeDefinitionsDepths.put(depth, typeDefinitionsConcreteDepth);
1163 typeDefinitionsConcreteDepth.add(unsortedTypeDefinition);
1165 // keys are in ascending order
1166 Set<Integer> depths = typeDefinitionsDepths.keySet();
1167 for (Integer depth : depths) {
1168 sortedTypeDefinition.addAll(typeDefinitionsDepths.get(depth));
1171 return sortedTypeDefinition;
1175 * Returns how many immersion is necessary to get from the type definition
1178 * @param typeDefinition
1179 * type definition for which is depth sought.
1180 * @return number of immersions which are necessary to get from the type
1181 * definition to the base type
1183 private int getTypeDefinitionDepth(final TypeDefinition<?> typeDefinition) {
1184 if (typeDefinition == null) {
1188 TypeDefinition<?> baseType = typeDefinition.getBaseType();
1190 if (baseType instanceof ExtendedType) {
1191 depth = depth + getTypeDefinitionDepth(typeDefinition.getBaseType());
1192 } else if (baseType instanceof UnionType) {
1193 List<TypeDefinition<?>> childTypeDefinitions = ((UnionType) baseType).getTypes();
1194 int maxChildDepth = 0;
1196 for (TypeDefinition<?> childTypeDefinition : childTypeDefinitions) {
1197 childDepth = childDepth + getTypeDefinitionDepth(childTypeDefinition);
1198 if (childDepth > maxChildDepth) {
1199 maxChildDepth = childDepth;
1202 return maxChildDepth;
1208 * Returns string which contains the same value as <code>name</code> but
1209 * integer suffix is incremented by one. If <code>name</code> contains no
1210 * number suffix then number 1 is added.
1213 * string with name of augmented node
1214 * @return string with the number suffix incremented by one (or 1 is added)
1216 private String provideAvailableNameForGenTOBuilder(String name) {
1217 Pattern searchedPattern = Pattern.compile("[0-9]+\\z");
1218 Matcher mtch = searchedPattern.matcher(name);
1220 final int newSuffix = Integer.valueOf(name.substring(mtch.start())) + 1;
1221 return name.substring(0, mtch.start()) + newSuffix;
1227 private void addUnitsToGenTO(GeneratedTOBuilder to, String units) {
1228 if (units != null && !units.isEmpty()) {
1229 to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\"");
1230 GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
1231 prop.setReturnType(Types.STRING);
1232 to.addToStringProperty(prop);
1237 public String getTypeDefaultConstruction(LeafSchemaNode node) {
1238 return getTypeDefaultConstruction(node, node.getDefault());
1241 public String getTypeDefaultConstruction(LeafSchemaNode node, String defaultValue) {
1242 TypeDefinition<?> type = node.getType();
1243 Preconditions.checkNotNull(type, "Cannot provide default construction for null type of " + node);
1244 Preconditions.checkNotNull(defaultValue, "Cannot provide default construction for null default statement of "
1247 Module module = getParentModule(node);
1248 String basePackageName = BindingGeneratorUtil.moduleNamespaceToPackageName(module);
1249 String packageName = packageNameForGeneratedType(basePackageName, node.getPath());
1250 String className = packageName + "." + parseToClassName(node.getQName().getLocalName());
1252 StringBuilder sb = new StringBuilder();
1253 TypeDefinition<?> base = baseTypeDefForExtendedType(type);
1254 final boolean isBaseNull = base == null;
1260 String result = null;
1261 if (base instanceof BinaryTypeDefinition) {
1262 result = binaryToDef(defaultValue);
1263 } else if (base instanceof BitsTypeDefinition) {
1265 YangNode parent = node.getParent();
1266 if (parent instanceof Module) {
1267 parentName = parseToClassName(((Module)parent).getName()) + "Data";
1268 className = basePackageName + "." + parentName + "." + parseToClassName(node.getQName().getLocalName());
1270 parentName = parseToClassName(((SchemaNode)parent).getQName().getLocalName());
1271 className = packageName + "." + parentName + "." + parseToClassName(node.getQName().getLocalName());
1273 result = bitsToDef((BitsTypeDefinition) base, className, defaultValue, isBaseNull);
1274 } else if (base instanceof BooleanTypeDefinition) {
1275 result = typeToDef(Boolean.class, defaultValue);
1276 } else if (base instanceof DecimalTypeDefinition) {
1277 result = typeToDef(BigDecimal.class, defaultValue);
1278 } else if (base instanceof EmptyTypeDefinition) {
1279 result = typeToDef(Boolean.class, defaultValue);
1280 } else if (base instanceof EnumTypeDefinition) {
1281 char[] defValArray = defaultValue.toCharArray();
1282 char first = Character.toUpperCase(defaultValue.charAt(0));
1283 defValArray[0] = first;
1284 String newDefVal = new String(defValArray);
1285 if (type instanceof ExtendedType) {
1286 className = packageName + "." + parseToClassName(node.getType().getQName().getLocalName());
1288 result = className + "." + newDefVal;
1289 } else if (base instanceof IdentityrefTypeDefinition) {
1290 throw new UnsupportedOperationException("Cannot get default construction for identityref type");
1291 } else if (base instanceof InstanceIdentifierTypeDefinition) {
1292 throw new UnsupportedOperationException("Cannot get default construction for instance-identifier type");
1293 } else if (base instanceof Int8) {
1294 result = typeToDef(Byte.class, defaultValue);
1295 } else if (base instanceof Int16) {
1296 result = typeToDef(Short.class, defaultValue);
1297 } else if (base instanceof Int32) {
1298 result = typeToDef(Integer.class, defaultValue);
1299 } else if (base instanceof Int64) {
1300 result = typeToDef(Long.class, defaultValue);
1301 } else if (base instanceof LeafrefTypeDefinition) {
1302 result = leafrefToDef(node, (LeafrefTypeDefinition)base);
1303 } else if (base instanceof StringTypeDefinition) {
1304 result = "\"" + defaultValue + "\"";
1305 } else if (base instanceof Uint8) {
1306 result = typeToDef(Short.class, defaultValue);
1307 } else if (base instanceof Uint16) {
1308 result = typeToDef(Integer.class, defaultValue);
1309 } else if (base instanceof Uint32) {
1310 result = typeToDef(Long.class, defaultValue);
1311 } else if (base instanceof Uint64) {
1312 result = typeToDef(BigInteger.class, defaultValue);
1313 } else if (base instanceof UnionTypeDefinition) {
1314 throw new UnsupportedOperationException("Cannot get default construction for union type");
1320 if (result != null && !result.isEmpty() && type instanceof ExtendedType && !(base instanceof LeafrefTypeDefinition)) {
1321 className = packageName + "." + parseToClassName(node.getType().getQName().getLocalName());
1322 sb.insert(0, "new " + className + "(");
1323 sb.insert(sb.length(), ")");
1326 return sb.toString();
1330 private String typeToDef(Class<?> clazz, String defaultValue) {
1331 return "new " + clazz.getName() + "(\"" + defaultValue + "\")";
1334 private String binaryToDef(String defaultValue) {
1335 StringBuilder sb = new StringBuilder();
1336 BaseEncoding en = BaseEncoding.base64();
1337 byte[] encoded = en.decode(defaultValue);
1338 sb.append("new byte[] {");
1339 for (int i = 0; i < encoded.length; i++) {
1340 sb.append(encoded[i]);
1341 if (i != encoded.length - 1) {
1346 return sb.toString();
1349 private String bitsToDef(BitsTypeDefinition type, String className, String defaultValue, boolean isBase) {
1350 List<Bit> bits = new ArrayList<>(type.getBits());
1351 Collections.sort(bits, new Comparator<Bit>() {
1353 public int compare(Bit o1, Bit o2) {
1354 return o1.getName().compareTo(o2.getName());
1357 StringBuilder sb = new StringBuilder();
1358 sb.append(isBase ? "new " + className + "(" : "");
1359 for (int i = 0; i < bits.size(); i++) {
1360 if (bits.get(i).getName().equals(defaultValue)) {
1365 if (i != bits.size() - 1) {
1369 sb.append(isBase ? ")" : "");
1370 return sb.toString();
1373 private Module getParentModule(YangNode node) {
1374 if (node instanceof Module) {
1375 return (Module) node;
1378 YangNode parent = null;
1379 if (node instanceof DataSchemaNode) {
1380 parent = ((DataSchemaNode) node).getParent();
1381 } else if (node instanceof DataNodeContainer) {
1382 parent = ((DataNodeContainer) node).getParent();
1387 while (parent != null && !(parent instanceof Module)) {
1388 if (parent instanceof DataSchemaNode) {
1389 parent = ((DataSchemaNode) parent).getParent();
1390 } else if (parent instanceof DataNodeContainer) {
1391 parent = ((DataNodeContainer) parent).getParent();
1396 return (Module) parent;
1399 private String leafrefToDef(LeafSchemaNode parentNode, LeafrefTypeDefinition leafrefType) {
1400 Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!");
1401 Preconditions.checkArgument(leafrefType.getPathStatement() != null, "The Path Statement for Leafref Type Definition cannot be NULL!");
1403 final RevisionAwareXPath xpath = leafrefType.getPathStatement();
1404 final String strXPath = xpath.toString();
1406 if (strXPath != null) {
1407 if (strXPath.contains("[")) {
1408 return "new java.lang.Object()";
1410 final Module module = findParentModule(schemaContext, parentNode);
1411 if (module != null) {
1412 final SchemaNode dataNode;
1413 if (xpath.isAbsolute()) {
1414 dataNode = findDataSchemaNode(schemaContext, module, xpath);
1416 dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
1418 return getTypeDefaultConstruction((LeafSchemaNode)dataNode, parentNode.getDefault());