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.Types.getOuterClassPackageName;
13 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.addStringRegExAsConstant;
14 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.baseTypeDefForExtendedType;
15 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.getAllTypedefs;
16 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.getParentModule;
17 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.makeSerializable;
18 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.provideGeneratedTOFromExtendedType;
19 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.provideTypeForEnum;
20 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.resolveRegExpressionsFromTypedef;
21 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.sortTypeDefinitionAccordingDepth;
22 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.wrapJavaTypeIntoTO;
23 import static org.opendaylight.mdsal.binding.javav2.util.BindingMapping.getRootPackageName;
24 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
25 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
26 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
28 import com.google.common.annotations.Beta;
29 import com.google.common.base.Preconditions;
30 import com.google.common.base.Strings;
31 import com.google.common.collect.Sets;
32 import java.util.ArrayList;
33 import java.util.Collections;
34 import java.util.Date;
35 import java.util.HashMap;
36 import java.util.Iterator;
37 import java.util.List;
40 import java.util.regex.Matcher;
41 import java.util.regex.Pattern;
42 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
43 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
44 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier;
45 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer;
46 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
47 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
48 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
49 import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier;
50 import org.opendaylight.mdsal.binding.javav2.model.api.Enumeration;
51 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty;
52 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
53 import org.opendaylight.mdsal.binding.javav2.model.api.Restrictions;
54 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
55 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.EnumBuilder;
56 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedPropertyBuilder;
57 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder;
58 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilderBase;
59 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.MethodSignatureBuilder;
60 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
61 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
62 import org.opendaylight.yangtools.yang.common.QName;
63 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
64 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
65 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
66 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
67 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
68 import org.opendaylight.yangtools.yang.model.api.Module;
69 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
70 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
71 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
72 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
73 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
74 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
75 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
76 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
77 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
78 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
79 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
80 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
81 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
82 import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
83 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
84 import org.opendaylight.yangtools.yang.parser.util.YangValidationException;
85 import org.slf4j.Logger;
86 import org.slf4j.LoggerFactory;
89 public final class TypeProviderImpl implements TypeProvider {
91 private static final Logger LOG = LoggerFactory.getLogger(TypeProviderImpl.class);
92 private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
95 * Contains the schema data red from YANG files.
97 private final SchemaContext schemaContext;
100 * Map<moduleName, Map<moduleDate, Map<typeName, type>>>
102 private final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap;
105 * Map which maps schema paths to JAVA <code>Type</code>.
107 private final Map<SchemaPath, Type> referencedTypes;
110 * Map for additional types e.g unions
112 private final Map<Module, Set<Type>> additionalTypes;
115 * Creates new instance of class <code>TypeProviderImpl</code>.
117 * @param schemaContext
118 * contains the schema data red from YANG files
119 * @throws IllegalArgumentException
120 * if <code>schemaContext</code> equal null.
122 public TypeProviderImpl(final SchemaContext schemaContext) {
123 this.schemaContext = schemaContext;
124 this.genTypeDefsContextMap = new HashMap<>();
125 this.referencedTypes = new HashMap<>();
126 this.additionalTypes = new HashMap<>();
127 resolveTypeDefsFromContext(schemaContext, this.genTypeDefsContextMap, this.additionalTypes);
131 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode) {
132 return javaTypeForSchemaDefinitionType(type, parentNode, null);
136 * Converts schema definition type <code>typeDefinition</code> to JAVA
140 * type definition which is converted to JAVA type
141 * @throws IllegalArgumentException
143 * <li>if <code>typeDefinition</code> equal null</li>
144 * <li>if QName of <code>typeDefinition</code> equal null</li>
145 * <li>if name of <code>typeDefinition</code> equal null</li>
149 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode, final Restrictions restrictions) {
150 return javaTypeForSchemaDefType(type, parentNode, restrictions, this.schemaContext, this.genTypeDefsContextMap);
154 public String getTypeDefaultConstruction(final LeafSchemaNode node) {
159 public String getConstructorPropertyName(final SchemaNode node) {
164 public String getParamNameFromType(final TypeDefinition<?> type) {
168 public Map<String, Map<Date, Map<String, Type>>> getGenTypeDefsContextMap() {
169 return this.genTypeDefsContextMap;
173 * Passes through all modules and through all its type definitions and
174 * convert it to generated types.
176 * The modules are firstly sorted by mutual dependencies. The modules are
177 * sequentially passed. All type definitions of a module are at the
178 * beginning sorted so that type definition with less amount of references
179 * to other type definition are processed first.<br />
180 * For each module is created mapping record in the map
181 * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap}
182 * which map current module name to the map which maps type names to
183 * returned types (generated types).
186 private void resolveTypeDefsFromContext(final SchemaContext schemaContext, final Map<String, Map<Date, Map<String,
187 Type>>> genTypeDefsContextMap, final Map<Module, Set<Type>> additionalTypes) {
189 final Set<Module> modules = schemaContext.getModules();
190 Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL!");
191 final Module[] modulesArray = new Module[modules.size()];
193 for (final Module modul : modules) {
194 modulesArray[i++] = modul;
196 final List<Module> modulesSortedByDependency = org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort
199 for (final Module module : modulesSortedByDependency) {
200 Map<Date, Map<String, Type>> dateTypeMap = genTypeDefsContextMap.get(module.getName());
201 if (dateTypeMap == null) {
202 dateTypeMap = new HashMap<>();
204 dateTypeMap.put(module.getRevision(), Collections.emptyMap());
205 genTypeDefsContextMap.put(module.getName(), dateTypeMap);
208 modulesSortedByDependency.stream().filter(module -> module != null).forEach(module -> {
209 final String basePackageName = getRootPackageName(module);
210 final List<TypeDefinition<?>> typeDefinitions = getAllTypedefs(module);
211 final List<TypeDefinition<?>> listTypeDefinitions = sortTypeDefinitionAccordingDepth(typeDefinitions);
212 if (listTypeDefinitions != null) {
213 for (final TypeDefinition<?> typedef : listTypeDefinitions) {
214 typedefToGeneratedType(basePackageName, module, typedef, genTypeDefsContextMap,
215 additionalTypes, schemaContext);
222 * Converts <code>typeDefinition</code> to concrete JAVA <code>Type</code>.
224 * @param typeDefinition
225 * type definition which should be converted to JAVA
227 * @return JAVA <code>Type</code> which represents
228 * <code>typeDefinition</code>
229 * @throws IllegalArgumentException
231 * <li>if <code>typeDefinition</code> equal null</li>
232 * <li>if Q name of <code>typeDefinition</code></li>
233 * <li>if name of <code>typeDefinition</code></li>
236 public Type generatedTypeForExtendedDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
237 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
238 Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
239 "Type Definitions Local Name cannot be NULL!");
241 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
242 if (!(baseTypeDef instanceof LeafrefTypeDefinition) && !(baseTypeDef instanceof IdentityrefTypeDefinition)) {
243 final Module module = findParentModule(this.schemaContext, parentNode);
245 if (module != null) {
246 final Map<Date, Map<String, Type>> modulesByDate = this.genTypeDefsContextMap.get(module.getName());
247 final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
248 if (genTOs != null) {
249 return genTOs.get(typeDefinition.getQName().getLocalName());
257 * Puts <code>refType</code> to map with key <code>refTypePath</code>
260 * schema path used as the map key
262 * type which represents the map value
263 * @throws IllegalArgumentException
265 * <li>if <code>refTypePath</code> equal null</li>
266 * <li>if <code>refType</code> equal null</li>
270 public void putReferencedType(final SchemaPath refTypePath, final Type refType) {
271 Preconditions.checkArgument(refTypePath != null,
272 "Path reference of Enumeration Type Definition cannot be NULL!");
273 Preconditions.checkArgument(refType != null, "Reference to Enumeration Type cannot be NULL!");
274 this.referencedTypes.put(refTypePath, refType);
278 * Converts <code>typeDef</code> which should be of the type
279 * <code>BitsTypeDefinition</code> to <code>GeneratedTOBuilder</code>.
281 * All the bits of the typeDef are added to returning generated TO as
284 * @param basePackageName
285 * string with name of package to which the module belongs
287 * type definition from which is the generated TO builder created
289 * string with the name for generated TO builder
290 * @return generated TO builder which represents <code>typeDef</code>
291 * @throws IllegalArgumentException
293 * <li>if <code>typeDef</code> equals null</li>
294 * <li>if <code>basePackageName</code> equals null</li>
297 @SuppressWarnings({ "rawtypes", "unchecked" })
298 public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName, final
299 TypeDefinition<?> typeDef, final String typeDefName, final String moduleName) {
301 Preconditions.checkArgument(typeDef != null, "typeDef cannot be NULL!");
302 Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
304 if (typeDef instanceof BitsTypeDefinition) {
305 final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
307 final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName, true, false);
308 final String typedefDescription = encodeAngleBrackets(typeDef.getDescription());
310 genTOBuilder.setDescription(typedefDescription);
311 genTOBuilder.setReference(typeDef.getReference());
312 genTOBuilder.setSchemaPath((List) typeDef.getPath().getPathFromRoot());
313 genTOBuilder.setModuleName(moduleName);
314 genTOBuilder.setBaseType(typeDef);
316 final List<Bit> bitList = bitsTypeDefinition.getBits();
317 GeneratedPropertyBuilder genPropertyBuilder;
318 for (final Bit bit : bitList) {
319 final String name = bit.getName();
321 genTOBuilder.addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(name, JavaIdentifier.METHOD));
322 genPropertyBuilder.setReadOnly(true);
323 genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE);
325 genTOBuilder.addEqualsIdentity(genPropertyBuilder);
326 genTOBuilder.addHashIdentity(genPropertyBuilder);
327 genTOBuilder.addToStringProperty(genPropertyBuilder);
336 * Converts <code>typedef</code> to generated TO with
337 * <code>typeDefName</code>. Every union type from <code>typedef</code> is
338 * added to generated TO builder as property.
340 * @param basePackageName
341 * string with name of package to which the module belongs
343 * type definition which should be of type
344 * <code>UnionTypeDefinition</code>
346 * string with name for generated TO
347 * @return generated TO builder which represents <code>typedef</code>
348 * @throws NullPointerException
350 * <li>if <code>basePackageName</code> is null</li>
351 * <li>if <code>typedef</code> is null</li>
352 * <li>if QName of <code>typedef</code> is null</li>
355 @SuppressWarnings({ "rawtypes", "unchecked" })
356 public List<GeneratedTOBuilder> provideGeneratedTOBuildersForUnionTypeDef(final String basePackageName,
357 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode, final SchemaContext
358 schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
359 Preconditions.checkNotNull(basePackageName, "Base Package Name cannot be NULL!");
360 Preconditions.checkNotNull(typedef, "Type Definition cannot be NULL!");
361 Preconditions.checkNotNull(typedef.getQName(), "Type definition QName cannot be NULL!");
363 final List<GeneratedTOBuilder> generatedTOBuilders = new ArrayList<>();
364 final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
365 final Module module = findParentModule(schemaContext, parentNode);
367 final GeneratedTOBuilderImpl unionGenTOBuilder;
368 if (typeDefName != null && !typeDefName.isEmpty()) {
369 unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName, true, false);
370 final String typedefDescription = encodeAngleBrackets(typedef.getDescription());
371 unionGenTOBuilder.setDescription(typedefDescription);
372 unionGenTOBuilder.setReference(typedef.getReference());
373 unionGenTOBuilder.setSchemaPath((List) typedef.getPath().getPathFromRoot());
374 unionGenTOBuilder.setModuleName(module.getName());
376 unionGenTOBuilder = typedefToTransferObject(basePackageName, typedef, module.getName());
379 generatedTOBuilders.add(unionGenTOBuilder);
380 unionGenTOBuilder.setIsUnion(true);
381 final List<String> regularExpressions = new ArrayList<>();
382 for (final TypeDefinition<?> unionType : unionTypes) {
383 final String unionTypeName = unionType.getQName().getLocalName();
384 if (unionType.getBaseType() != null) {
385 resolveExtendedSubtypeAsUnion(unionGenTOBuilder, unionType, regularExpressions,
386 parentNode, schemaContext, genTypeDefsContextMap);
387 } else if (unionType instanceof UnionTypeDefinition) {
388 generatedTOBuilders.add(resolveUnionSubtypeAsUnion(unionGenTOBuilder, (UnionTypeDefinition) unionType,
389 unionGenTOBuilder.getFullyQualifiedName(), parentNode, schemaContext, genTypeDefsContextMap));
390 } else if (unionType instanceof EnumTypeDefinition) {
391 final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType,
392 unionTypeName, unionGenTOBuilder);
393 updateUnionTypeAsProperty(unionGenTOBuilder, enumeration, unionTypeName);
395 final Type javaType = javaTypeForSchemaDefType(unionType, parentNode, null, schemaContext,
396 genTypeDefsContextMap);
397 updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName);
400 if (!regularExpressions.isEmpty()) {
401 addStringRegExAsConstant(unionGenTOBuilder, regularExpressions);
404 //storeGenTO(typedef, unionGenTOBuilder, parentNode);
406 return generatedTOBuilders;
409 public Map<Module, Set<Type>> getAdditionalTypes() {
410 return this.additionalTypes;
413 public static void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) {
414 if (!Strings.isNullOrEmpty(units)) {
415 to.addConstant(Types.STRING, "Units", "\"" + units + "\"");
416 final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
417 prop.setReturnType(Types.STRING);
418 to.addToStringProperty(prop);
422 private Type javaTypeForSchemaDefType(final TypeDefinition<?> typeDefinition, final SchemaNode
423 parentNode, final Restrictions r, final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
424 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
425 final String typedefName = typeDefinition.getQName().getLocalName();
426 Preconditions.checkArgument(typedefName != null, "Type Definitions Local Name cannot be NULL!");
428 // Deal with base types
429 if (typeDefinition.getBaseType() == null) {
430 // We have to deal with differing handling of decimal64. The old parser used a fixed Decimal64 type
431 // and generated an enclosing ExtendedType to hold any range constraints. The new parser instantiates
432 // a base type which holds these constraints.
433 if (typeDefinition instanceof DecimalTypeDefinition) {
434 final Type ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition, parentNode, r);
440 // Deal with leafrefs/identityrefs
441 Type ret = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode, schemaContext, genTypeDefsContextMap);
446 ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition, parentNode);
448 LOG.debug("Failed to resolve Java type for {}", typeDefinition);
454 Type returnType = javaTypeForExtendedType(typeDefinition, schemaContext, genTypeDefsContextMap);
455 if (r != null && !r.isEmpty() && returnType instanceof GeneratedTransferObject) {
456 final GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
457 final Module module = findParentModule(schemaContext, parentNode);
458 final String basePackageName = BindingMapping.getRootPackageName(module);
459 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typeDefinition
460 .getPath(), BindingNamespaceType.Typedef);
461 final String genTOName =
462 JavaIdentifierNormalizer.normalizeSpecificIdentifier(typedefName, JavaIdentifier.CLASS);
463 final String name = packageName + "." + genTOName;
464 if (!(returnType.getFullyQualifiedName().equals(name))) {
465 returnType = shadedTOWithRestrictions(gto, r);
473 * @param basePackageName
474 * string with name of package to which the module belongs
476 * string with the name of the module for to which the
477 * <code>typedef</code> belongs
479 * type definition of the node for which should be creted JAVA
480 * <code>Type</code> (usually generated TO)
481 * @return JAVA <code>Type</code> representation of <code>typedef</code> or
482 * <code>null</code> value if <code>basePackageName</code> or
483 * <code>modulName</code> or <code>typedef</code> or Q name of
484 * <code>typedef</code> equals <code>null</code>
486 private Type typedefToGeneratedType(final String basePackageName, final Module module, final
487 TypeDefinition<?> typedef, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap, final Map<Module,
488 Set<Type>> additionalTypes, final SchemaContext schemaContext) {
489 final String moduleName = module.getName();
490 final Date moduleRevision = module.getRevision();
491 if ((basePackageName != null) && (moduleName != null) && (typedef != null)) {
492 final String typedefName = typedef.getQName().getLocalName();
493 final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
494 if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
495 && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) {
497 if (innerTypeDefinition.getBaseType() != null) {
498 returnType = provideGeneratedTOFromExtendedType(typedef, innerTypeDefinition, basePackageName,
499 module.getName(), schemaContext, genTypeDefsContextMap);
500 } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
501 final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
502 (UnionTypeDefinition) innerTypeDefinition, typedefName, typedef, schemaContext, genTypeDefsContextMap);
503 genTOBuilder.setTypedef(true);
504 genTOBuilder.setIsUnion(true);
505 addUnitsToGenTO(genTOBuilder, typedef.getUnits());
506 makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
507 returnType = genTOBuilder.toInstance();
508 } else if (innerTypeDefinition instanceof EnumTypeDefinition) {
509 // enums are automatically Serializable
510 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypeDefinition;
511 // TODO units for typedef enum
512 returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef, schemaContext);
513 } else if (innerTypeDefinition instanceof BitsTypeDefinition) {
514 final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition;
515 final GeneratedTOBuilder genTOBuilder =
516 provideGeneratedTOBuilderForBitsTypeDefinition(
517 basePackageName, bitsTypeDefinition, typedefName, module.getName());
518 genTOBuilder.setTypedef(true);
519 addUnitsToGenTO(genTOBuilder, typedef.getUnits());
520 makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
521 returnType = genTOBuilder.toInstance();
523 final Type javaType = javaTypeForSchemaDefType(innerTypeDefinition, typedef, null,
524 schemaContext, genTypeDefsContextMap);
525 returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName());
527 if (returnType != null) {
528 final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(moduleName);
529 Map<String, Type> typeMap = modulesByDate.get(moduleRevision);
530 if (typeMap != null) {
531 if (typeMap.isEmpty()) {
532 typeMap = new HashMap<>(4);
533 modulesByDate.put(moduleRevision, typeMap);
535 typeMap.put(typedefName, returnType);
545 * Returns JAVA <code>Type</code> for instances of the type
546 * <code>ExtendedType</code>.
548 * @param typeDefinition
549 * type definition which is converted to JAVA <code>Type</code>
550 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
552 private Type javaTypeForExtendedType(final TypeDefinition<?> typeDefinition, final SchemaContext
553 schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
555 final String typedefName = typeDefinition.getQName().getLocalName();
556 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
557 Type returnType = javaTypeForLeafrefOrIdentityRef(baseTypeDef, typeDefinition, schemaContext, genTypeDefsContextMap);
558 if (returnType == null) {
559 if (baseTypeDef instanceof EnumTypeDefinition) {
560 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) baseTypeDef;
561 returnType = provideTypeForEnum(enumTypeDef, typedefName, typeDefinition, schemaContext);
563 final Module module = findParentModule(schemaContext, typeDefinition);
564 final Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
565 if (module != null) {
566 final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
567 final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
568 if (genTOs != null) {
569 returnType = genTOs.get(typedefName);
571 if (returnType == null) {
572 returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
573 baseTypeDef, typeDefinition, r);
582 * Returns JAVA <code>Type</code> for instances of the type
583 * <code>LeafrefTypeDefinition</code> or
584 * <code>IdentityrefTypeDefinition</code>.
586 * @param typeDefinition
587 * type definition which is converted to JAVA <code>Type</code>
588 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
590 private Type javaTypeForLeafrefOrIdentityRef(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
591 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
592 if (typeDefinition instanceof LeafrefTypeDefinition) {
593 final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition;
594 if (isLeafRefSelfReference(leafref, parentNode, schemaContext)) {
595 throw new YangValidationException("Leafref " + leafref.toString() + " is referencing itself, incoming" +
596 " StackOverFlowError detected.");
598 return provideTypeForLeafref(leafref, parentNode, schemaContext, genTypeDefsContextMap);
599 } else if (typeDefinition instanceof IdentityrefTypeDefinition) {
600 final IdentityrefTypeDefinition idref = (IdentityrefTypeDefinition) typeDefinition;
601 return provideTypeForIdentityref(idref, schemaContext);
608 * Converts <code>leafrefType</code> to JAVA <code>Type</code>.
610 * The path of <code>leafrefType</code> is followed to find referenced node
611 * and its <code>Type</code> is returned.
614 * leafref type definition for which is the type sought
615 * @return JAVA <code>Type</code> of data schema node which is referenced in
616 * <code>leafrefType</code>
617 * @throws IllegalArgumentException
619 * <li>if <code>leafrefType</code> equal null</li>
620 * <li>if path statement of <code>leafrefType</code> equal null</li>
624 public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode,
625 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
627 Type returnType = null;
628 Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!");
630 Preconditions.checkArgument(leafrefType.getPathStatement() != null,
631 "The Path Statement for Leafref Type Definition cannot be NULL!");
633 final RevisionAwareXPath xpath = leafrefType.getPathStatement();
634 final String strXPath = xpath.toString();
636 if (strXPath != null) {
637 if (strXPath.indexOf('[') == -1) {
638 final Module module = findParentModule(schemaContext, parentNode);
639 Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode);
641 final SchemaNode dataNode;
642 if (xpath.isAbsolute()) {
643 dataNode = findDataSchemaNode(schemaContext, module, xpath);
645 dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, parentNode, xpath);
647 Preconditions.checkArgument(dataNode != null, "Failed to find leafref target: %s in module %s (%s)",
648 strXPath, getParentModule(parentNode, schemaContext).getName(), parentNode.getQName().getModule());
650 if (leafContainsEnumDefinition(dataNode)) {
651 returnType = this.referencedTypes.get(dataNode.getPath());
652 } else if (leafListContainsEnumDefinition(dataNode)) {
653 returnType = Types.listTypeFor(this.referencedTypes.get(dataNode.getPath()));
655 returnType = resolveTypeFromDataSchemaNode(dataNode, schemaContext, genTypeDefsContextMap);
658 returnType = Types.typeForClass(Object.class);
661 Preconditions.checkArgument(returnType != null, "Failed to find leafref target: %s in module %s (%s)",
662 strXPath, getParentModule(parentNode, schemaContext).getName(), parentNode.getQName().getModule());
667 * Checks if <code>dataNode</code> is <code>LeafSchemaNode</code> and if it
668 * so then checks if it is of type <code>EnumTypeDefinition</code>.
671 * data schema node for which is checked if it is leaf and if it
673 * @return boolean value
675 * <li>true - if <code>dataNode</code> is leaf of type enumeration</li>
676 * <li>false - other cases</li>
679 private static boolean leafContainsEnumDefinition(final SchemaNode dataNode) {
680 if (dataNode instanceof LeafSchemaNode) {
681 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
682 //CompatUtils is not used here anymore
683 if (leaf.getType() instanceof EnumTypeDefinition) {
691 * Checks if <code>dataNode</code> is <code>LeafListSchemaNode</code> and if
692 * it so then checks if it is of type <code>EnumTypeDefinition</code>.
695 * data schema node for which is checked if it is leaflist and if
697 * @return boolean value
699 * <li>true - if <code>dataNode</code> is leaflist of type
701 * <li>false - other cases</li>
704 private static boolean leafListContainsEnumDefinition(final SchemaNode dataNode) {
705 if (dataNode instanceof LeafListSchemaNode) {
706 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
707 if (leafList.getType() instanceof EnumTypeDefinition) {
715 * Converts <code>dataNode</code> to JAVA <code>Type</code>.
718 * contains information about YANG type
719 * @return JAVA <code>Type</code> representation of <code>dataNode</code>
721 private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode, final SchemaContext schemaContext,
722 final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
723 Type returnType = null;
724 if (dataNode != null) {
725 if (dataNode instanceof LeafSchemaNode) {
726 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
727 //not using CompatUtils here anymore
728 final TypeDefinition<?> type = leaf.getType();
729 returnType = javaTypeForSchemaDefType(type, leaf, null, schemaContext, genTypeDefsContextMap);
730 } else if (dataNode instanceof LeafListSchemaNode) {
731 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
732 returnType = javaTypeForSchemaDefType(leafList.getType(), leafList, null, schemaContext, genTypeDefsContextMap);
739 * Seeks for identity reference <code>idref</code> the JAVA
740 * <code>type</code>.<br />
744 * If identy which is referenced via <code>idref</code> has name <b>Idn</b>
745 * then returning type is <b>{@code Class<? extends Idn>}</b></i>
748 * identityref type definition for which JAVA <code>Type</code>
750 * @return JAVA <code>Type</code> of the identity which is refrenced through
753 private static Type provideTypeForIdentityref(final IdentityrefTypeDefinition idref, final SchemaContext schemaContext) {
754 //TODO: incompatibility with Binding spec v2, get first or only one
755 final QName baseIdQName = idref.getIdentities().iterator().next().getQName();
756 final Module module = schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
757 baseIdQName.getRevision());
758 IdentitySchemaNode identity = null;
759 for (final IdentitySchemaNode id : module.getIdentities()) {
760 if (id.getQName().equals(baseIdQName)) {
764 Preconditions.checkArgument(identity != null, "Target identity '" + baseIdQName + "' do not exists");
766 final String basePackageName = BindingMapping.getRootPackageName(module);
767 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity.getPath
768 (), BindingNamespaceType.Identity);
770 final String genTypeName = JavaIdentifierNormalizer.normalizeSpecificIdentifier(identity.getQName().getLocalName(),
771 JavaIdentifier.CLASS);
773 final Type baseType = Types.typeForClass(Class.class);
774 final Type paramType = Types.wildcardTypeFor(packageName, genTypeName, true, true);
775 return Types.parameterizedTypeFor(baseType, paramType);
779 * Converts <code>typedef</code> to the generated TO builder.
781 * @param basePackageName
782 * string with name of package to which the module belongs
784 * type definition from which is the generated TO builder created
785 * @return generated TO builder which contains data from
786 * <code>typedef</code> and <code>basePackageName</code>
788 @SuppressWarnings({ "rawtypes", "unchecked" })
789 private static GeneratedTOBuilderImpl typedefToTransferObject(final String basePackageName, final TypeDefinition<?> typedef, final String moduleName) {
791 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typedef.getPath
792 (), BindingNamespaceType.Typedef);
793 final String typeDefTOName = typedef.getQName().getLocalName();
795 if ((packageName != null) && (typeDefTOName != null)) {
796 final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, typeDefTOName);
797 final String typedefDescription = encodeAngleBrackets(typedef.getDescription());
799 newType.setDescription(typedefDescription);
800 newType.setReference(typedef.getReference());
801 newType.setSchemaPath((List) typedef.getPath().getPathFromRoot());
802 newType.setModuleName(moduleName);
809 private static GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto, final Restrictions r) {
810 final GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName());
811 final GeneratedTransferObject parent = gto.getSuperType();
812 if (parent != null) {
813 gtob.setExtendsType(parent);
815 gtob.setRestrictions(r);
816 for (final GeneratedProperty gp : gto.getProperties()) {
817 final GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
818 gpb.setValue(gp.getValue());
819 gpb.setReadOnly(gp.isReadOnly());
820 gpb.setAccessModifier(gp.getAccessModifier());
821 gpb.setReturnType(gp.getReturnType());
822 gpb.setFinal(gp.isFinal());
823 gpb.setStatic(gp.isStatic());
825 return gtob.toInstance();
829 * Adds a new property with the name <code>propertyName</code> and with type
830 * <code>type</code> to <code>unonGenTransObject</code>.
832 * @param unionGenTransObject
833 * generated TO to which should be property added
835 * JAVA <code>type</code> of the property which should be added
836 * to <code>unionGentransObject</code>
837 * @param propertyName
838 * string with name of property which should be added to
839 * <code>unionGentransObject</code>
841 private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type, final String propertyName) {
842 if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) {
843 final GeneratedPropertyBuilder propBuilder = unionGenTransObject
844 .addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(propertyName, JavaIdentifier.METHOD));
845 propBuilder.setReturnType(type);
847 unionGenTransObject.addEqualsIdentity(propBuilder);
848 unionGenTransObject.addHashIdentity(propBuilder);
849 unionGenTransObject.addToStringProperty(propBuilder);
854 * Wraps code which handle case when union subtype is also of the type
855 * <code>UnionType</code>.
857 * In this case the new generated TO is created for union subtype (recursive
859 * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, UnionTypeDefinition,
860 * String, SchemaNode, SchemaContext, Map)}
861 * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder
862 * <code>parentUnionGenTOBuilder</code> is created property which type is
863 * equal to new generated TO.
865 * @param parentUnionGenTOBuilder
866 * generated TO builder to which is the property with the child
867 * union subtype added
868 * @param basePackageName
869 * string with the name of the module package
870 * @param unionSubtype
871 * type definition which represents union subtype
872 * @return list of generated TO builders. The number of the builders can be
873 * bigger one due to recursive call of
874 * <code>provideGeneratedTOBuildersForUnionTypeDef</code> method.
876 private GeneratedTOBuilder resolveUnionSubtypeAsUnion(final GeneratedTOBuilder
877 parentUnionGenTOBuilder, final UnionTypeDefinition unionSubtype, final String basePackageName,
878 final SchemaNode parentNode, final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
880 final String newTOBuilderName = provideAvailableNameForGenTOBuilder(parentUnionGenTOBuilder.getName());
881 final GeneratedTOBuilder subUnionGenTOBUilder = provideGeneratedTOBuilderForUnionTypeDef(
882 basePackageName, unionSubtype, newTOBuilderName, parentNode, schemaContext, genTypeDefsContextMap);
884 final GeneratedPropertyBuilder propertyBuilder;
885 propertyBuilder = parentUnionGenTOBuilder
886 .addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(newTOBuilderName, JavaIdentifier.METHOD));
887 propertyBuilder.setReturnType(subUnionGenTOBUilder);
888 parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder);
889 parentUnionGenTOBuilder.addToStringProperty(propertyBuilder);
891 return subUnionGenTOBUilder;
895 * Converts output list of generated TO builders to one TO builder (first
896 * from list) which contains the remaining builders as its enclosing TO.
898 * @param basePackageName
899 * string with name of package to which the module belongs
901 * type definition which should be of type
902 * <code>UnionTypeDefinition</code>
904 * string with name for generated TO
905 * @return generated TO builder with the list of enclosed generated TO
908 public GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final String basePackageName,
909 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode, final SchemaContext
910 schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
912 final List<GeneratedTOBuilder> builders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
913 typedef, typeDefName, parentNode, schemaContext, genTypeDefsContextMap);
914 Preconditions.checkState(!builders.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typedef);
916 final GeneratedTOBuilder resultTOBuilder = builders.remove(0);
917 for (final GeneratedTOBuilder genTOBuilder : builders) {
918 resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
921 final GeneratedPropertyBuilder genPropBuilder;
923 genPropBuilder = resultTOBuilder.addProperty("value").setReturnType(Types.CHAR_ARRAY).setReadOnly(false);
924 resultTOBuilder.addEqualsIdentity(genPropBuilder);
925 resultTOBuilder.addHashIdentity(genPropBuilder);
926 resultTOBuilder.addToStringProperty(genPropBuilder);
928 provideGeneratedTOBuilderForUnionBuilder(findParentModule(schemaContext, parentNode), resultTOBuilder);
930 return resultTOBuilder;
934 private GeneratedTOBuilder provideGeneratedTOBuilderForUnionBuilder(final Module parentModule,
935 final GeneratedTOBuilder genTOBuilder) {
936 final String outerCls = Types.getOuterClassName(genTOBuilder);
937 final StringBuilder name;
938 if (outerCls != null) {
939 name = new StringBuilder(outerCls);
941 name = new StringBuilder();
943 name.append(genTOBuilder.getName());
944 name.append("Builder");
945 final GeneratedTOBuilderImpl unionBuilder = new GeneratedTOBuilderImpl(getOuterClassPackageName(genTOBuilder),
946 name.toString(), true);
947 unionBuilder.setIsUnionBuilder(true);
949 final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
950 method.setReturnType(genTOBuilder);
951 method.addParameter(Types.STRING, "defaultValue");
952 method.setAccessModifier(AccessModifier.PUBLIC);
953 method.setStatic(true);
955 final Set<Type> types = this.getAdditionalTypes().get(parentModule);
957 this.getAdditionalTypes().put(parentModule,
958 Sets.newHashSet(unionBuilder.toInstance()));
960 types.add(unionBuilder.toInstance());
967 * Wraps code which handle case when union subtype is of the type
968 * <code>ExtendedType</code>.
970 * If TO for this type already exists it is used for the creation of the
971 * property in <code>parentUnionGenTOBuilder</code>. In other case the base
972 * type is used for the property creation.
974 * @param parentUnionGenTOBuilder
975 * generated TO builder in which new property is created
976 * @param unionSubtype
977 * type definition of the <code>ExtendedType</code> type which
978 * represents union subtype
979 * @param regularExpressions
980 * list of strings with the regular expressions
982 * parent Schema Node for Extended Subtype
985 private static void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder, final
986 TypeDefinition<?> unionSubtype, final List<String> regularExpressions, final SchemaNode parentNode,
987 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
989 final String unionTypeName = unionSubtype.getQName().getLocalName();
990 final Type genTO = findGenTO(unionTypeName, unionSubtype, schemaContext, genTypeDefsContextMap);
992 updateUnionTypeAsProperty(parentUnionGenTOBuilder, genTO, genTO.getName());
994 final TypeDefinition<?> baseType = baseTypeDefForExtendedType(unionSubtype);
995 if (unionTypeName.equals(baseType.getQName().getLocalName())) {
996 final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType,
998 if (javaType != null) {
999 updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
1002 if (baseType instanceof StringTypeDefinition) {
1003 regularExpressions.addAll(resolveRegExpressionsFromTypedef(unionSubtype));
1009 * Returns string which contains the same value as <code>name</code> but
1010 * integer suffix is incremented by one. If <code>name</code> contains no
1011 * number suffix then number 1 is added.
1014 * string with name of augmented node
1015 * @return string with the number suffix incremented by one (or 1 is added)
1017 private static String provideAvailableNameForGenTOBuilder(final String name) {
1018 final Matcher mtch = NUMBERS_PATTERN.matcher(name);
1020 final int newSuffix = Integer.valueOf(name.substring(mtch.start())) + 1;
1021 return name.substring(0, mtch.start()) + newSuffix;
1028 * Searches for generated TO for <code>searchedTypeDef</code> type
1029 * definition in {@link #genTypeDefsContextMap genTypeDefsContextMap}
1031 * @param searchedTypeName
1032 * string with name of <code>searchedTypeDef</code>
1033 * @return generated TO for <code>searchedTypeDef</code> or
1034 * <code>null</code> it it doesn't exist
1036 private static Type findGenTO(final String searchedTypeName, final SchemaNode parentNode,
1037 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
1039 final Module typeModule = findParentModule(schemaContext, parentNode);
1040 if (typeModule != null && typeModule.getName() != null) {
1041 final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(typeModule.getName());
1042 final Map<String, Type> genTOs = modulesByDate.get(typeModule.getRevision());
1043 if (genTOs != null) {
1044 return genTOs.get(searchedTypeName);
1051 * Adds enumeration to <code>typeBuilder</code>. The enumeration data are
1052 * taken from <code>enumTypeDef</code>.
1054 * @param enumTypeDef
1055 * enumeration type definition is source of enumeration data for
1056 * <code>typeBuilder</code>
1058 * string with the name of enumeration
1059 * @param typeBuilder
1060 * generated type builder to which is enumeration added
1061 * @return enumeration type which contains enumeration data form
1062 * <code>enumTypeDef</code>
1063 * @throws IllegalArgumentException
1065 * <li>if <code>enumTypeDef</code> equals null</li>
1066 * <li>if enum values of <code>enumTypeDef</code> equal null</li>
1067 * <li>if Q name of <code>enumTypeDef</code> equal null</li>
1068 * <li>if name of <code>enumTypeDef</code> equal null</li>
1069 * <li>if name of <code>typeBuilder</code> equal null</li>
1073 private static Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef, final String enumName, final GeneratedTypeBuilderBase<?> typeBuilder) {
1074 Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
1075 Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
1076 "Local Name in EnumTypeDefinition QName cannot be NULL!");
1077 Preconditions.checkArgument(typeBuilder != null, "Generated Type Builder reference cannot be NULL!");
1079 final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumName);
1080 final String enumTypedefDescription = encodeAngleBrackets(enumTypeDef.getDescription());
1081 enumBuilder.setDescription(enumTypedefDescription);
1082 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
1083 return enumBuilder.toInstance(enumBuilder);
1086 private static boolean isLeafRefSelfReference(final LeafrefTypeDefinition leafref, final SchemaNode parentNode,
1087 final SchemaContext schemaContext) {
1088 final SchemaNode leafRefValueNode;
1089 final RevisionAwareXPath leafRefXPath = leafref.getPathStatement();
1090 final RevisionAwareXPath leafRefStrippedXPath = new RevisionAwareXPathImpl(leafRefXPath.toString()
1091 .replaceAll("\\[(.*?)\\]", ""), leafRefXPath.isAbsolute());
1093 ///// skip leafrefs in augments - they're checked once augments are resolved
1094 final Iterator<QName> iterator = parentNode.getPath().getPathFromRoot().iterator();
1095 boolean isAugmenting = false;
1096 DataNodeContainer current = null;
1097 DataSchemaNode dataChildByName;
1099 while (iterator.hasNext() && !isAugmenting) {
1100 final QName next = iterator.next();
1101 if (current == null) {
1102 dataChildByName = schemaContext.getDataChildByName(next);
1104 dataChildByName = current.getDataChildByName(next);
1106 if (dataChildByName != null) {
1107 isAugmenting = dataChildByName.isAugmenting();
1111 if (dataChildByName instanceof DataNodeContainer) {
1112 current = (DataNodeContainer) dataChildByName;
1120 final Module parentModule = getParentModule(parentNode, schemaContext);
1121 if (!leafRefStrippedXPath.isAbsolute()) {
1122 leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
1123 parentNode, leafRefStrippedXPath);
1125 leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath);
1127 return (leafRefValueNode != null) && leafRefValueNode.equals(parentNode);