2 * Copyright (c) 2017 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
9 package org.opendaylight.mdsal.binding.javav2.generator.yang.types;
11 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
12 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.packageNameWithNamespacePrefix;
13 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.getOuterClassPackageName;
14 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.addStringRegExAsConstant;
15 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.baseTypeDefForExtendedType;
16 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.getAllTypedefs;
17 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.getParentModule;
18 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.makeSerializable;
19 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.provideGeneratedTOFromExtendedType;
20 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.provideTypeForEnum;
21 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.resolveRegExpressionsFromTypedef;
22 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.sortTypeDefinitionAccordingDepth;
23 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.wrapJavaTypeIntoTO;
24 import static org.opendaylight.mdsal.binding.javav2.util.BindingMapping.getRootPackageName;
25 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
26 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
27 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
29 import com.google.common.annotations.Beta;
30 import com.google.common.base.Preconditions;
31 import com.google.common.base.Strings;
32 import com.google.common.collect.Sets;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
39 import java.util.Optional;
41 import java.util.regex.Matcher;
42 import java.util.regex.Pattern;
43 import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
44 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
45 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
46 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier;
47 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer;
48 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
49 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
50 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
51 import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier;
52 import org.opendaylight.mdsal.binding.javav2.model.api.Enumeration;
53 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty;
54 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
55 import org.opendaylight.mdsal.binding.javav2.model.api.Restrictions;
56 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
57 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.EnumBuilder;
58 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedPropertyBuilder;
59 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder;
60 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilderBase;
61 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.MethodSignatureBuilder;
62 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
63 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
64 import org.opendaylight.yangtools.yang.common.QName;
65 import org.opendaylight.yangtools.yang.common.Revision;
66 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
67 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
68 import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
69 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
70 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
71 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
72 import org.opendaylight.yangtools.yang.model.api.Module;
73 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
74 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
75 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
76 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
77 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
78 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
79 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
80 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
81 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
82 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
83 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
84 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
85 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
86 import org.opendaylight.yangtools.yang.model.util.ModuleDependencySort;
87 import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
88 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
89 import org.slf4j.Logger;
90 import org.slf4j.LoggerFactory;
93 public final class TypeProviderImpl implements TypeProvider {
95 private static final Logger LOG = LoggerFactory.getLogger(TypeProviderImpl.class);
96 private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
99 * Contains the schema data red from YANG files.
101 private final SchemaContext schemaContext;
104 * Map<moduleName, Map<moduleDate, Map<typeName, type>>>
106 private final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap;
109 * Map which maps schema paths to JAVA <code>Type</code>.
111 private final Map<SchemaPath, Type> referencedTypes;
114 * Map for additional types e.g unions
116 private final Map<Module, Set<Type>> additionalTypes;
119 * Creates new instance of class <code>TypeProviderImpl</code>.
121 * @param schemaContext
122 * contains the schema data red from YANG files
123 * @throws IllegalArgumentException
124 * if <code>schemaContext</code> equal null.
126 public TypeProviderImpl(final SchemaContext schemaContext) {
127 this.schemaContext = schemaContext;
128 this.genTypeDefsContextMap = new HashMap<>();
129 this.referencedTypes = new HashMap<>();
130 this.additionalTypes = new HashMap<>();
131 resolveTypeDefsFromContext(schemaContext, this.genTypeDefsContextMap, this.additionalTypes);
135 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode,
136 final ModuleContext context) {
137 return javaTypeForSchemaDefinitionType(type, parentNode, null, context);
141 * Converts schema definition type <code>typeDefinition</code> to JAVA
145 * type definition which is converted to JAVA type
146 * @throws IllegalArgumentException
148 * <li>if <code>typeDefinition</code> equal null</li>
149 * <li>if QName of <code>typeDefinition</code> equal null</li>
150 * <li>if name of <code>typeDefinition</code> equal null</li>
154 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode, final
155 Restrictions restrictions, final ModuleContext context) {
156 return javaTypeForSchemaDefType(type, parentNode, restrictions, this.schemaContext, this
157 .genTypeDefsContextMap, context);
161 public String getTypeDefaultConstruction(final LeafSchemaNode node) {
166 public String getConstructorPropertyName(final SchemaNode node) {
171 public String getParamNameFromType(final TypeDefinition<?> type) {
175 public Map<String, Map<Optional<Revision>, Map<String, Type>>> getGenTypeDefsContextMap() {
176 return this.genTypeDefsContextMap;
180 * Passes through all modules and through all its type definitions and
181 * convert it to generated types.
183 * The modules are firstly sorted by mutual dependencies. The modules are
184 * sequentially passed. All type definitions of a module are at the
185 * beginning sorted so that type definition with less amount of references
186 * to other type definition are processed first.<br />
187 * For each module is created mapping record in the map
188 * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap}
189 * which map current module name to the map which maps type names to
190 * returned types (generated types).
193 private void resolveTypeDefsFromContext(final SchemaContext schemaContext,
194 final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap,
195 final Map<Module, Set<Type>> additionalTypes) {
197 final Set<Module> modules = schemaContext.getModules();
198 Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL!");
199 final List<Module> modulesSortedByDependency = ModuleDependencySort.sort(modules);
201 for (final Module module : modulesSortedByDependency) {
202 Map<Optional<Revision>, Map<String, Type>> dateTypeMap = genTypeDefsContextMap.get(module.getName());
203 if (dateTypeMap == null) {
204 dateTypeMap = new HashMap<>();
206 dateTypeMap.put(module.getRevision(), Collections.emptyMap());
207 genTypeDefsContextMap.put(module.getName(), dateTypeMap);
210 modulesSortedByDependency.stream().filter(module -> module != null).forEach(module -> {
211 ModuleContext context = new ModuleContext();
212 final String basePackageName = packageNameWithNamespacePrefix(getRootPackageName(module),
213 BindingNamespaceType.Typedef);
214 final List<TypeDefinition<?>> typeDefinitions = getAllTypedefs(module);
215 final List<TypeDefinition<?>> listTypeDefinitions = sortTypeDefinitionAccordingDepth(typeDefinitions);
216 if (listTypeDefinitions != null) {
217 for (final TypeDefinition<?> typedef : listTypeDefinitions) {
218 typedefToGeneratedType(basePackageName, module, typedef, genTypeDefsContextMap,
219 additionalTypes, schemaContext, context);
226 * Converts <code>typeDefinition</code> to concrete JAVA <code>Type</code>.
228 * @param typeDefinition
229 * type definition which should be converted to JAVA
231 * @return JAVA <code>Type</code> which represents
232 * <code>typeDefinition</code>
233 * @throws IllegalArgumentException
235 * <li>if <code>typeDefinition</code> equal null</li>
236 * <li>if Q name of <code>typeDefinition</code></li>
237 * <li>if name of <code>typeDefinition</code></li>
240 public Type generatedTypeForExtendedDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
241 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
242 Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
243 "Type Definitions Local Name cannot be NULL!");
245 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
246 if (!(baseTypeDef instanceof LeafrefTypeDefinition) && !(baseTypeDef instanceof IdentityrefTypeDefinition)) {
247 final Module module = findParentModule(this.schemaContext, parentNode);
249 if (module != null) {
250 final Map<Optional<Revision>, Map<String, Type>> modulesByDate = this.genTypeDefsContextMap.get(module.getName());
251 final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
252 if (genTOs != null) {
253 return genTOs.get(typeDefinition.getQName().getLocalName());
261 * Puts <code>refType</code> to map with key <code>refTypePath</code>
264 * schema path used as the map key
266 * type which represents the map value
267 * @throws IllegalArgumentException
269 * <li>if <code>refTypePath</code> equal null</li>
270 * <li>if <code>refType</code> equal null</li>
274 public void putReferencedType(final SchemaPath refTypePath, final Type refType) {
275 Preconditions.checkArgument(refTypePath != null,
276 "Path reference of Enumeration Type Definition cannot be NULL!");
277 Preconditions.checkArgument(refType != null, "Reference to Enumeration Type cannot be NULL!");
278 this.referencedTypes.put(refTypePath, refType);
282 * Converts <code>typeDef</code> which should be of the type
283 * <code>BitsTypeDefinition</code> to <code>GeneratedTOBuilder</code>.
285 * All the bits of the typeDef are added to returning generated TO as
288 * @param basePackageName
289 * string with name of package to which the module belongs
291 * type definition from which is the generated TO builder created
293 * string with the name for generated TO builder
294 * @return generated TO builder which represents <code>typeDef</code>
295 * @throws IllegalArgumentException
297 * <li>if <code>typeDef</code> equals null</li>
298 * <li>if <code>basePackageName</code> equals null</li>
301 @SuppressWarnings({ "rawtypes", "unchecked" })
302 public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName,
303 final TypeDefinition<?> typeDef, final String typeDefName, final String moduleName, final ModuleContext context) {
305 Preconditions.checkArgument(typeDef != null, "typeDef cannot be NULL!");
306 Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
308 if (typeDef instanceof BitsTypeDefinition) {
309 final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
311 final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName,
312 true, false, context);
313 final String typedefDescription = encodeAngleBrackets(typeDef.getDescription().orElse(null));
315 genTOBuilder.setDescription(typedefDescription);
316 typeDef.getReference().ifPresent(genTOBuilder::setReference);
317 genTOBuilder.setSchemaPath((List) typeDef.getPath().getPathFromRoot());
318 genTOBuilder.setModuleName(moduleName);
319 genTOBuilder.setBaseType(typeDef);
321 final List<Bit> bitList = bitsTypeDefinition.getBits();
322 GeneratedPropertyBuilder genPropertyBuilder;
323 for (final Bit bit : bitList) {
324 final String name = bit.getName();
326 genTOBuilder.addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(name, JavaIdentifier.METHOD));
327 genPropertyBuilder.setReadOnly(true);
328 genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE);
330 genTOBuilder.addEqualsIdentity(genPropertyBuilder);
331 genTOBuilder.addHashIdentity(genPropertyBuilder);
332 genTOBuilder.addToStringProperty(genPropertyBuilder);
341 * Converts <code>typedef</code> to generated TO with
342 * <code>typeDefName</code>. Every union type from <code>typedef</code> is
343 * added to generated TO builder as property.
345 * @param basePackageName
346 * string with name of package to which the module belongs
348 * type definition which should be of type
349 * <code>UnionTypeDefinition</code>
351 * string with name for generated TO
352 * @return generated TO builder which represents <code>typedef</code>
353 * @throws NullPointerException
355 * <li>if <code>basePackageName</code> is null</li>
356 * <li>if <code>typedef</code> is null</li>
357 * <li>if QName of <code>typedef</code> is null</li>
360 @SuppressWarnings({ "rawtypes", "unchecked" })
361 public List<GeneratedTOBuilder> provideGeneratedTOBuildersForUnionTypeDef(final String basePackageName,
362 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode,
363 final SchemaContext schemaContext, final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap, final ModuleContext context) {
364 Preconditions.checkNotNull(basePackageName, "Base Package Name cannot be NULL!");
365 Preconditions.checkNotNull(typedef, "Type Definition cannot be NULL!");
366 Preconditions.checkNotNull(typedef.getQName(), "Type definition QName cannot be NULL!");
368 final List<GeneratedTOBuilder> generatedTOBuilders = new ArrayList<>();
369 final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
370 final Module module = findParentModule(schemaContext, parentNode);
372 final GeneratedTOBuilderImpl unionGenTOBuilder;
373 unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName, true, false,
375 final String typedefDescription = encodeAngleBrackets(typedef.getDescription().orElse(null));
376 unionGenTOBuilder.setDescription(typedefDescription);
377 typedef.getReference().ifPresent(unionGenTOBuilder::setReference);
378 unionGenTOBuilder.setSchemaPath((List) typedef.getPath().getPathFromRoot());
379 unionGenTOBuilder.setModuleName(module.getName());
381 generatedTOBuilders.add(unionGenTOBuilder);
382 unionGenTOBuilder.setIsUnion(true);
383 final List<String> regularExpressions = new ArrayList<>();
384 for (final TypeDefinition<?> unionType : unionTypes) {
385 final String unionTypeName = unionType.getQName().getLocalName();
386 if (unionType.getBaseType() != null) {
387 resolveExtendedSubtypeAsUnion(unionGenTOBuilder, unionType, regularExpressions,
388 parentNode, schemaContext, genTypeDefsContextMap);
389 } else if (unionType instanceof UnionTypeDefinition) {
390 generatedTOBuilders.add(resolveUnionSubtypeAsUnion(unionGenTOBuilder, (UnionTypeDefinition) unionType,
391 unionGenTOBuilder.getFullyQualifiedName(), parentNode, schemaContext, genTypeDefsContextMap,
393 } else if (unionType instanceof EnumTypeDefinition) {
394 final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType,
395 unionTypeName, unionGenTOBuilder, context);
396 updateUnionTypeAsProperty(unionGenTOBuilder, enumeration, unionTypeName);
398 final Type javaType = javaTypeForSchemaDefType(unionType, parentNode, null, schemaContext,
399 genTypeDefsContextMap, context);
400 updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName);
403 if (!regularExpressions.isEmpty()) {
404 addStringRegExAsConstant(unionGenTOBuilder, regularExpressions);
407 //storeGenTO(typedef, unionGenTOBuilder, parentNode);
409 return generatedTOBuilders;
412 public Map<Module, Set<Type>> getAdditionalTypes() {
413 return this.additionalTypes;
416 public static void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) {
417 if (!Strings.isNullOrEmpty(units)) {
418 to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\"");
419 final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
420 prop.setReturnType(Types.STRING);
421 to.addToStringProperty(prop);
425 private Type javaTypeForSchemaDefType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
426 final Restrictions r, final SchemaContext schemaContext,
427 final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap, final ModuleContext context) {
428 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
429 final String typedefName = typeDefinition.getQName().getLocalName();
430 Preconditions.checkArgument(typedefName != null, "Type Definitions Local Name cannot be NULL!");
432 // Deal with base types
433 if (typeDefinition.getBaseType() == null) {
434 // We have to deal with differing handling of decimal64. The old parser used a fixed Decimal64 type
435 // and generated an enclosing ExtendedType to hold any range constraints. The new parser instantiates
436 // a base type which holds these constraints.
437 if (typeDefinition instanceof DecimalTypeDefinition) {
438 final Type ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType
439 (typeDefinition, parentNode, r, context);
445 // Deal with leafrefs/identityrefs
446 Type ret = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode, schemaContext,
447 genTypeDefsContextMap, context);
452 ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition, parentNode,
455 LOG.debug("Failed to resolve Java type for {}", typeDefinition);
461 Type returnType = javaTypeForExtendedType(typeDefinition, schemaContext, genTypeDefsContextMap, context);
462 if (r != null && !r.isEmpty() && returnType instanceof GeneratedTransferObject) {
463 final GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
464 final Module module = findParentModule(schemaContext, parentNode);
465 final Module module1 = findParentModule(schemaContext, typeDefinition);
466 final String basePackageName = BindingMapping.getRootPackageName(module);
467 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typeDefinition
468 .getPath(), BindingNamespaceType.Typedef);
469 final String genTOName =
470 JavaIdentifierNormalizer.normalizeSpecificIdentifier(typedefName, JavaIdentifier.CLASS);
471 final String name = packageName + "." + genTOName;
472 if (module.equals(module1) && !returnType.getFullyQualifiedName().equals(name)) {
473 returnType = shadedTOWithRestrictions(gto, r, context);
481 * @param basePackageName
482 * string with name of package to which the module belongs
484 * string with the name of the module for to which the
485 * <code>typedef</code> belongs
487 * type definition of the node for which should be creted JAVA
488 * <code>Type</code> (usually generated TO)
489 * @return JAVA <code>Type</code> representation of <code>typedef</code> or
490 * <code>null</code> value if <code>basePackageName</code> or
491 * <code>modulName</code> or <code>typedef</code> or Q name of
492 * <code>typedef</code> equals <code>null</code>
494 private Type typedefToGeneratedType(final String basePackageName, final Module module,
495 final TypeDefinition<?> typedef,
496 final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap,
497 final Map<Module, Set<Type>> additionalTypes, final SchemaContext schemaContext, final ModuleContext context) {
498 final String moduleName = module.getName();
499 final Optional<Revision> moduleRevision = module.getRevision();
500 if (basePackageName != null && moduleName != null && typedef != null) {
501 final String typedefName = typedef.getQName().getLocalName();
502 final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
503 if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
504 && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) {
506 if (innerTypeDefinition.getBaseType() != null) {
507 returnType = provideGeneratedTOFromExtendedType(typedef, innerTypeDefinition, basePackageName,
508 module.getName(), schemaContext, genTypeDefsContextMap, context);
509 } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
510 final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
511 (UnionTypeDefinition) innerTypeDefinition, typedefName, typedef, schemaContext,
512 genTypeDefsContextMap, context);
513 genTOBuilder.setTypedef(true);
514 genTOBuilder.setIsUnion(true);
515 addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null));
516 makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
517 returnType = genTOBuilder.toInstance();
518 } else if (innerTypeDefinition instanceof EnumTypeDefinition) {
519 // enums are automatically Serializable
520 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypeDefinition;
521 // TODO units for typedef enum
522 returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef, schemaContext, context);
523 } else if (innerTypeDefinition instanceof BitsTypeDefinition) {
524 final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition;
525 final GeneratedTOBuilder genTOBuilder =
526 provideGeneratedTOBuilderForBitsTypeDefinition(
527 basePackageName, bitsTypeDefinition, typedefName, module.getName(), context);
528 genTOBuilder.setTypedef(true);
529 addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null));
530 makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
531 returnType = genTOBuilder.toInstance();
533 final Type javaType = javaTypeForSchemaDefType(innerTypeDefinition, typedef, null,
534 schemaContext, genTypeDefsContextMap, context);
535 returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName(), context);
537 if (returnType != null) {
538 final Map<Optional<Revision>, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(moduleName);
539 Map<String, Type> typeMap = modulesByDate.get(moduleRevision);
540 if (typeMap != null) {
541 if (typeMap.isEmpty()) {
542 typeMap = new HashMap<>(4);
543 modulesByDate.put(moduleRevision, typeMap);
545 typeMap.put(typedefName, returnType);
555 * Returns JAVA <code>Type</code> for instances of the type
556 * <code>ExtendedType</code>.
558 * @param typeDefinition
559 * type definition which is converted to JAVA <code>Type</code>
560 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
562 private Type javaTypeForExtendedType(final TypeDefinition<?> typeDefinition, final SchemaContext schemaContext,
563 final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap, final ModuleContext context) {
565 final String typedefName = typeDefinition.getQName().getLocalName();
566 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
567 Type returnType = javaTypeForLeafrefOrIdentityRef(baseTypeDef, typeDefinition, schemaContext,
568 genTypeDefsContextMap, context);
569 if (returnType == null) {
570 final Module module = findParentModule(schemaContext, typeDefinition);
571 final Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
572 if (module != null) {
573 final Map<Optional<Revision>, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
574 final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
575 if (genTOs != null) {
576 returnType = genTOs.get(typedefName);
578 if (returnType == null) {
579 returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
580 baseTypeDef, typeDefinition, r, context);
588 * Returns JAVA <code>Type</code> for instances of the type
589 * <code>LeafrefTypeDefinition</code> or
590 * <code>IdentityrefTypeDefinition</code>.
592 * @param typeDefinition
593 * type definition which is converted to JAVA <code>Type</code>
594 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
596 private Type javaTypeForLeafrefOrIdentityRef(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
597 final SchemaContext schemaContext, final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap,
598 final ModuleContext context) {
599 if (typeDefinition instanceof LeafrefTypeDefinition) {
600 final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition;
601 Preconditions.checkArgument(!isLeafRefSelfReference(leafref, parentNode, schemaContext),
602 "Leafref %s is referencing itself, incoming StackOverFlowError detected.", leafref);
603 return provideTypeForLeafref(leafref, parentNode, schemaContext, genTypeDefsContextMap, context);
604 } else if (typeDefinition instanceof IdentityrefTypeDefinition) {
605 final IdentityrefTypeDefinition idref = (IdentityrefTypeDefinition) typeDefinition;
606 return provideTypeForIdentityref(idref, schemaContext);
613 * Converts <code>leafrefType</code> to JAVA <code>Type</code>.
615 * The path of <code>leafrefType</code> is followed to find referenced node
616 * and its <code>Type</code> is returned.
619 * leafref type definition for which is the type sought
620 * @return JAVA <code>Type</code> of data schema node which is referenced in
621 * <code>leafrefType</code>
622 * @throws IllegalArgumentException
624 * <li>if <code>leafrefType</code> equal null</li>
625 * <li>if path statement of <code>leafrefType</code> equal null</li>
629 public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode,
630 final SchemaContext schemaContext, final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap,
631 final ModuleContext context) {
633 Type returnType = null;
634 Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!");
636 Preconditions.checkArgument(leafrefType.getPathStatement() != null,
637 "The Path Statement for Leafref Type Definition cannot be NULL!");
639 final RevisionAwareXPath xpath = leafrefType.getPathStatement();
640 final String strXPath = xpath.toString();
641 if (strXPath != null) {
642 if (strXPath.indexOf('[') == -1) {
644 final SchemaNode actualParentSchemaNode;
645 if (parentNode instanceof DerivableSchemaNode && ((DerivableSchemaNode) parentNode).isAddedByUses()) {
646 final Optional<? extends SchemaNode> originalNode = ((DerivableSchemaNode) parentNode).getOriginal();
647 Preconditions.checkArgument(originalNode.isPresent(), "originalNode can not be null.");
648 actualParentSchemaNode = originalNode.get();
649 module = findParentModule(schemaContext, originalNode.get());
651 actualParentSchemaNode = parentNode;
652 module = findParentModule(schemaContext, parentNode);
654 Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode);
656 final SchemaNode dataNode;
657 if (xpath.isAbsolute()) {
658 dataNode = findDataSchemaNode(schemaContext, module, xpath);
660 dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, actualParentSchemaNode, xpath);
662 Preconditions.checkArgument(dataNode != null, "Failed to find leafref target: %s in module %s (%s)",
663 strXPath, getParentModule(parentNode, schemaContext).getName(), parentNode.getQName().getModule());
665 if (leafContainsEnumDefinition(dataNode)) {
666 returnType = this.referencedTypes.get(dataNode.getPath());
667 } else if (leafListContainsEnumDefinition(dataNode)) {
668 returnType = Types.listTypeFor(this.referencedTypes.get(dataNode.getPath()));
670 returnType = resolveTypeFromDataSchemaNode(dataNode, schemaContext, genTypeDefsContextMap, context);
673 returnType = Types.typeForClass(Object.class);
676 Preconditions.checkArgument(returnType != null, "Failed to find leafref target: %s in module %s (%s)",
677 strXPath, getParentModule(parentNode, schemaContext).getName(), parentNode.getQName().getModule());
682 * Checks if <code>dataNode</code> is <code>LeafSchemaNode</code> and if it
683 * so then checks if it is of type <code>EnumTypeDefinition</code>.
686 * data schema node for which is checked if it is leaf and if it
688 * @return boolean value
690 * <li>true - if <code>dataNode</code> is leaf of type enumeration</li>
691 * <li>false - other cases</li>
694 private static boolean leafContainsEnumDefinition(final SchemaNode dataNode) {
695 if (dataNode instanceof LeafSchemaNode) {
696 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
697 //CompatUtils is not used here anymore
698 if (leaf.getType() instanceof EnumTypeDefinition) {
706 * Checks if <code>dataNode</code> is <code>LeafListSchemaNode</code> and if
707 * it so then checks if it is of type <code>EnumTypeDefinition</code>.
710 * data schema node for which is checked if it is leaflist and if
712 * @return boolean value
714 * <li>true - if <code>dataNode</code> is leaflist of type
716 * <li>false - other cases</li>
719 private static boolean leafListContainsEnumDefinition(final SchemaNode dataNode) {
720 if (dataNode instanceof LeafListSchemaNode) {
721 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
722 if (leafList.getType() instanceof EnumTypeDefinition) {
730 * Converts <code>dataNode</code> to JAVA <code>Type</code>.
733 * contains information about YANG type
734 * @return JAVA <code>Type</code> representation of <code>dataNode</code>
736 private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode, final SchemaContext schemaContext,
737 final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap, final ModuleContext context) {
738 Type returnType = null;
739 if (dataNode != null) {
740 if (dataNode instanceof LeafSchemaNode) {
741 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
742 //not using CompatUtils here anymore
743 final TypeDefinition<?> type = leaf.getType();
744 returnType = javaTypeForSchemaDefType(type, leaf, null, schemaContext, genTypeDefsContextMap, context);
745 } else if (dataNode instanceof LeafListSchemaNode) {
746 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
747 returnType = javaTypeForSchemaDefType(leafList.getType(), leafList, null, schemaContext,
748 genTypeDefsContextMap, context);
755 * Seeks for identity reference <code>idref</code> the JAVA
756 * <code>type</code>.<br />
760 * If identy which is referenced via <code>idref</code> has name <b>Idn</b>
761 * then returning type is <b>{@code Class<? extends Idn>}</b></i>
764 * identityref type definition for which JAVA <code>Type</code>
766 * @return JAVA <code>Type</code> of the identity which is refrenced through
769 private static Type provideTypeForIdentityref(final IdentityrefTypeDefinition idref, final SchemaContext schemaContext) {
770 //TODO: incompatibility with Binding spec v2, get first or only one
771 final QName baseIdQName = idref.getIdentities().iterator().next().getQName();
772 final Module module = schemaContext.findModule(baseIdQName.getModule()).orElse(null);
773 IdentitySchemaNode identity = null;
774 for (final IdentitySchemaNode id : module.getIdentities()) {
775 if (id.getQName().equals(baseIdQName)) {
779 Preconditions.checkArgument(identity != null, "Target identity '" + baseIdQName + "' do not exists");
781 final String basePackageName = BindingMapping.getRootPackageName(module);
782 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity.getPath
783 (), BindingNamespaceType.Identity);
785 final String genTypeName = JavaIdentifierNormalizer.normalizeSpecificIdentifier(identity.getQName().getLocalName(),
786 JavaIdentifier.CLASS);
788 final Type baseType = Types.typeForClass(Class.class);
789 final Type paramType = Types.wildcardTypeFor(packageName, genTypeName, true, true, null);
790 return Types.parameterizedTypeFor(baseType, paramType);
793 private static GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto,
794 final Restrictions r, final ModuleContext context) {
795 final GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName(), context);
796 final GeneratedTransferObject parent = gto.getSuperType();
797 if (parent != null) {
798 gtob.setExtendsType(parent);
800 gtob.setRestrictions(r);
801 for (final GeneratedProperty gp : gto.getProperties()) {
802 final GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
803 gpb.setValue(gp.getValue());
804 gpb.setReadOnly(gp.isReadOnly());
805 gpb.setAccessModifier(gp.getAccessModifier());
806 gpb.setReturnType(gp.getReturnType());
807 gpb.setFinal(gp.isFinal());
808 gpb.setStatic(gp.isStatic());
810 return gtob.toInstance();
814 * Adds a new property with the name <code>propertyName</code> and with type
815 * <code>type</code> to <code>unonGenTransObject</code>.
817 * @param unionGenTransObject
818 * generated TO to which should be property added
820 * JAVA <code>type</code> of the property which should be added
821 * to <code>unionGentransObject</code>
822 * @param propertyName
823 * string with name of property which should be added to
824 * <code>unionGentransObject</code>
826 private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type, final String propertyName) {
827 if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) {
828 final GeneratedPropertyBuilder propBuilder = unionGenTransObject
829 .addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(propertyName, JavaIdentifier.METHOD));
830 propBuilder.setReturnType(type);
832 unionGenTransObject.addEqualsIdentity(propBuilder);
833 unionGenTransObject.addHashIdentity(propBuilder);
834 unionGenTransObject.addToStringProperty(propBuilder);
839 * Wraps code which handle case when union subtype is also of the type
840 * <code>UnionType</code>.
842 * In this case the new generated TO is created for union subtype (recursive
844 * {@link #provideGeneratedTOBuilderForUnionTypeDef(String, UnionTypeDefinition, String, SchemaNode, SchemaContext, Map, ModuleContext)}
845 * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder
846 * <code>parentUnionGenTOBuilder</code> is created property which type is
847 * equal to new generated TO.
849 * @param parentUnionGenTOBuilder
850 * generated TO builder to which is the property with the child
851 * union subtype added
852 * @param basePackageName
853 * string with the name of the module package
854 * @param unionSubtype
855 * type definition which represents union subtype
856 * @return list of generated TO builders. The number of the builders can be
857 * bigger one due to recursive call of
858 * <code>provideGeneratedTOBuildersForUnionTypeDef</code> method.
860 private GeneratedTOBuilder resolveUnionSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
861 final UnionTypeDefinition unionSubtype, final String basePackageName, final SchemaNode parentNode,
862 final SchemaContext schemaContext, final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap,
863 final ModuleContext context) {
865 final String newTOBuilderName = provideAvailableNameForGenTOBuilder(parentUnionGenTOBuilder.getName());
866 final GeneratedTOBuilder subUnionGenTOBUilder = provideGeneratedTOBuilderForUnionTypeDef(
867 basePackageName, unionSubtype, newTOBuilderName, parentNode, schemaContext, genTypeDefsContextMap,
870 final GeneratedPropertyBuilder propertyBuilder;
871 propertyBuilder = parentUnionGenTOBuilder
872 .addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(newTOBuilderName, JavaIdentifier.METHOD));
873 propertyBuilder.setReturnType(subUnionGenTOBUilder);
874 parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder);
875 parentUnionGenTOBuilder.addToStringProperty(propertyBuilder);
877 return subUnionGenTOBUilder;
881 * Converts output list of generated TO builders to one TO builder (first
882 * from list) which contains the remaining builders as its enclosing TO.
884 * @param basePackageName
885 * string with name of package to which the module belongs
887 * type definition which should be of type
888 * <code>UnionTypeDefinition</code>
890 * string with name for generated TO
891 * @return generated TO builder with the list of enclosed generated TO
894 public GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final String basePackageName,
895 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode,
896 final SchemaContext schemaContext, final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap,
897 final ModuleContext context) {
899 final List<GeneratedTOBuilder> builders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
900 typedef, typeDefName, parentNode, schemaContext, genTypeDefsContextMap, context);
901 Preconditions.checkState(!builders.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typedef);
903 final GeneratedTOBuilder resultTOBuilder = builders.remove(0);
904 for (final GeneratedTOBuilder genTOBuilder : builders) {
905 resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
908 final GeneratedPropertyBuilder genPropBuilder;
910 genPropBuilder = resultTOBuilder.addProperty("value").setReturnType(Types.CHAR_ARRAY).setReadOnly(false);
911 resultTOBuilder.addEqualsIdentity(genPropBuilder);
912 resultTOBuilder.addHashIdentity(genPropBuilder);
913 resultTOBuilder.addToStringProperty(genPropBuilder);
915 provideGeneratedTOBuilderForUnionBuilder(findParentModule(schemaContext, parentNode), resultTOBuilder);
917 return resultTOBuilder;
921 private GeneratedTOBuilder provideGeneratedTOBuilderForUnionBuilder(final Module parentModule,
922 final GeneratedTOBuilder genTOBuilder) {
923 final String outerCls = Types.getOuterClassName(genTOBuilder);
924 final StringBuilder name;
925 if (outerCls != null) {
926 name = new StringBuilder(outerCls);
928 name = new StringBuilder();
930 name.append(genTOBuilder.getName());
931 name.append("Builder");
932 final GeneratedTOBuilderImpl unionBuilder = new GeneratedTOBuilderImpl(getOuterClassPackageName(genTOBuilder),
933 name.toString(), true);
934 unionBuilder.setIsUnionBuilder(true);
936 final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
937 method.setReturnType(genTOBuilder);
938 method.addParameter(Types.STRING, "defaultValue");
939 method.setAccessModifier(AccessModifier.PUBLIC);
940 method.setStatic(true);
942 final Set<Type> types = this.getAdditionalTypes().get(parentModule);
944 this.getAdditionalTypes().put(parentModule,
945 Sets.newHashSet(unionBuilder.toInstance()));
947 types.add(unionBuilder.toInstance());
954 * Wraps code which handle case when union subtype is of the type
955 * <code>ExtendedType</code>.
957 * If TO for this type already exists it is used for the creation of the
958 * property in <code>parentUnionGenTOBuilder</code>. In other case the base
959 * type is used for the property creation.
961 * @param parentUnionGenTOBuilder
962 * generated TO builder in which new property is created
963 * @param unionSubtype
964 * type definition of the <code>ExtendedType</code> type which
965 * represents union subtype
966 * @param regularExpressions
967 * list of strings with the regular expressions
969 * parent Schema Node for Extended Subtype
972 private static void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
973 final TypeDefinition<?> unionSubtype, final List<String> regularExpressions, final SchemaNode parentNode,
974 final SchemaContext schemaContext, final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap) {
976 final String unionTypeName = unionSubtype.getQName().getLocalName();
977 final Type genTO = findGenTO(unionTypeName, unionSubtype, schemaContext, genTypeDefsContextMap);
979 updateUnionTypeAsProperty(parentUnionGenTOBuilder, genTO, unionTypeName);
981 final TypeDefinition<?> baseType = baseTypeDefForExtendedType(unionSubtype);
982 if (unionTypeName.equals(baseType.getQName().getLocalName())) {
983 final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType,
985 if (javaType != null) {
986 updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
989 if (baseType instanceof StringTypeDefinition) {
990 regularExpressions.addAll(resolveRegExpressionsFromTypedef(unionSubtype));
996 * Returns string which contains the same value as <code>name</code> but
997 * integer suffix is incremented by one. If <code>name</code> contains no
998 * number suffix then number 1 is added.
1001 * string with name of augmented node
1002 * @return string with the number suffix incremented by one (or 1 is added)
1004 private static String provideAvailableNameForGenTOBuilder(final String name) {
1005 final Matcher mtch = NUMBERS_PATTERN.matcher(name);
1007 final int newSuffix = Integer.valueOf(name.substring(mtch.start())) + 1;
1008 return name.substring(0, mtch.start()) + newSuffix;
1015 * Searches for generated TO for <code>searchedTypeDef</code> type
1016 * definition in {@link #genTypeDefsContextMap genTypeDefsContextMap}
1018 * @param searchedTypeName
1019 * string with name of <code>searchedTypeDef</code>
1020 * @return generated TO for <code>searchedTypeDef</code> or
1021 * <code>null</code> it it doesn't exist
1023 private static Type findGenTO(final String searchedTypeName, final SchemaNode parentNode,
1024 final SchemaContext schemaContext, final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap) {
1026 final Module typeModule = findParentModule(schemaContext, parentNode);
1027 if (typeModule != null && typeModule.getName() != null) {
1028 final Map<Optional<Revision>, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(typeModule.getName());
1029 final Map<String, Type> genTOs = modulesByDate.get(typeModule.getRevision());
1030 if (genTOs != null) {
1031 return genTOs.get(searchedTypeName);
1038 * Adds enumeration to <code>typeBuilder</code>. The enumeration data are
1039 * taken from <code>enumTypeDef</code>.
1041 * @param enumTypeDef
1042 * enumeration type definition is source of enumeration data for
1043 * <code>typeBuilder</code>
1045 * string with the name of enumeration
1046 * @param typeBuilder
1047 * generated type builder to which is enumeration added
1048 * @return enumeration type which contains enumeration data form
1049 * <code>enumTypeDef</code>
1050 * @throws IllegalArgumentException
1052 * <li>if <code>enumTypeDef</code> equals null</li>
1053 * <li>if enum values of <code>enumTypeDef</code> equal null</li>
1054 * <li>if Q name of <code>enumTypeDef</code> equal null</li>
1055 * <li>if name of <code>enumTypeDef</code> equal null</li>
1056 * <li>if name of <code>typeBuilder</code> equal null</li>
1060 private static Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef,
1061 final String enumName, final GeneratedTypeBuilderBase<?> typeBuilder, final ModuleContext context) {
1062 Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
1063 Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
1064 "Local Name in EnumTypeDefinition QName cannot be NULL!");
1065 Preconditions.checkArgument(typeBuilder != null, "Generated Type Builder reference cannot be NULL!");
1067 final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumName, context);
1068 final String enumTypedefDescription = encodeAngleBrackets(enumTypeDef.getDescription().orElse(null));
1069 enumBuilder.setDescription(enumTypedefDescription);
1070 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
1071 return enumBuilder.toInstance(enumBuilder);
1074 private static boolean isLeafRefSelfReference(final LeafrefTypeDefinition leafref, final SchemaNode parentNode,
1075 final SchemaContext schemaContext) {
1076 final SchemaNode leafRefValueNode;
1077 final RevisionAwareXPath leafRefXPath = leafref.getPathStatement();
1078 final RevisionAwareXPath leafRefStrippedXPath = new RevisionAwareXPathImpl(leafRefXPath.toString()
1079 .replaceAll("\\[(.*?)\\]", ""), leafRefXPath.isAbsolute());
1081 ///// skip leafrefs in augments - they're checked once augments are resolved
1082 final Iterator<QName> iterator = parentNode.getPath().getPathFromRoot().iterator();
1083 boolean isAugmenting = false;
1084 DataNodeContainer current = null;
1085 DataSchemaNode dataChildByName;
1087 while (iterator.hasNext() && !isAugmenting) {
1088 final QName next = iterator.next();
1089 if (current == null) {
1090 dataChildByName = schemaContext.getDataChildByName(next);
1092 dataChildByName = current.getDataChildByName(next);
1094 if (dataChildByName != null) {
1095 isAugmenting = dataChildByName.isAugmenting();
1099 if (dataChildByName instanceof DataNodeContainer) {
1100 current = (DataNodeContainer) dataChildByName;
1108 final Module parentModule = getParentModule(parentNode, schemaContext);
1109 if (!leafRefStrippedXPath.isAbsolute()) {
1110 leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
1111 parentNode, leafRefStrippedXPath);
1113 leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath);
1115 return leafRefValueNode != null && leafRefValueNode.equals(parentNode);