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.Typedef);
769 final String genTypeName =
770 JavaIdentifierNormalizer.normalizeClassIdentifier(packageName, identity.getQName().getLocalName());
772 final Type baseType = Types.typeForClass(Class.class);
773 final Type paramType = Types.wildcardTypeFor(packageName, genTypeName);
774 return Types.parameterizedTypeFor(baseType, paramType);
778 * Converts <code>typedef</code> to the generated TO builder.
780 * @param basePackageName
781 * string with name of package to which the module belongs
783 * type definition from which is the generated TO builder created
784 * @return generated TO builder which contains data from
785 * <code>typedef</code> and <code>basePackageName</code>
787 @SuppressWarnings({ "rawtypes", "unchecked" })
788 private static GeneratedTOBuilderImpl typedefToTransferObject(final String basePackageName, final TypeDefinition<?> typedef, final String moduleName) {
790 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typedef.getPath
791 (), BindingNamespaceType.Typedef);
792 final String typeDefTOName = typedef.getQName().getLocalName();
794 if ((packageName != null) && (typeDefTOName != null)) {
795 final GeneratedTOBuilderImpl newType = new GeneratedTOBuilderImpl(packageName, typeDefTOName);
796 final String typedefDescription = encodeAngleBrackets(typedef.getDescription());
798 newType.setDescription(typedefDescription);
799 newType.setReference(typedef.getReference());
800 newType.setSchemaPath((List) typedef.getPath().getPathFromRoot());
801 newType.setModuleName(moduleName);
808 private static GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto, final Restrictions r) {
809 final GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName());
810 final GeneratedTransferObject parent = gto.getSuperType();
811 if (parent != null) {
812 gtob.setExtendsType(parent);
814 gtob.setRestrictions(r);
815 for (final GeneratedProperty gp : gto.getProperties()) {
816 final GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
817 gpb.setValue(gp.getValue());
818 gpb.setReadOnly(gp.isReadOnly());
819 gpb.setAccessModifier(gp.getAccessModifier());
820 gpb.setReturnType(gp.getReturnType());
821 gpb.setFinal(gp.isFinal());
822 gpb.setStatic(gp.isStatic());
824 return gtob.toInstance();
828 * Adds a new property with the name <code>propertyName</code> and with type
829 * <code>type</code> to <code>unonGenTransObject</code>.
831 * @param unionGenTransObject
832 * generated TO to which should be property added
834 * JAVA <code>type</code> of the property which should be added
835 * to <code>unionGentransObject</code>
836 * @param propertyName
837 * string with name of property which should be added to
838 * <code>unionGentransObject</code>
840 private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type, final String propertyName) {
841 if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) {
842 final GeneratedPropertyBuilder propBuilder = unionGenTransObject
843 .addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(propertyName, JavaIdentifier.METHOD));
844 propBuilder.setReturnType(type);
846 unionGenTransObject.addEqualsIdentity(propBuilder);
847 unionGenTransObject.addHashIdentity(propBuilder);
848 unionGenTransObject.addToStringProperty(propBuilder);
853 * Wraps code which handle case when union subtype is also of the type
854 * <code>UnionType</code>.
856 * In this case the new generated TO is created for union subtype (recursive
858 * {@link #provideGeneratedTOBuildersForUnionTypeDef(String, UnionTypeDefinition,
859 * String, SchemaNode, SchemaContext, Map)}
860 * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder
861 * <code>parentUnionGenTOBuilder</code> is created property which type is
862 * equal to new generated TO.
864 * @param parentUnionGenTOBuilder
865 * generated TO builder to which is the property with the child
866 * union subtype added
867 * @param basePackageName
868 * string with the name of the module package
869 * @param unionSubtype
870 * type definition which represents union subtype
871 * @return list of generated TO builders. The number of the builders can be
872 * bigger one due to recursive call of
873 * <code>provideGeneratedTOBuildersForUnionTypeDef</code> method.
875 private GeneratedTOBuilder resolveUnionSubtypeAsUnion(final GeneratedTOBuilder
876 parentUnionGenTOBuilder, final UnionTypeDefinition unionSubtype, final String basePackageName,
877 final SchemaNode parentNode, final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
879 final String newTOBuilderName = provideAvailableNameForGenTOBuilder(parentUnionGenTOBuilder.getName());
880 final GeneratedTOBuilder subUnionGenTOBUilder = provideGeneratedTOBuilderForUnionTypeDef(
881 basePackageName, unionSubtype, newTOBuilderName, parentNode, schemaContext, genTypeDefsContextMap);
883 final GeneratedPropertyBuilder propertyBuilder;
884 propertyBuilder = parentUnionGenTOBuilder
885 .addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(newTOBuilderName, JavaIdentifier.METHOD));
886 propertyBuilder.setReturnType(subUnionGenTOBUilder);
887 parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder);
888 parentUnionGenTOBuilder.addToStringProperty(propertyBuilder);
890 return subUnionGenTOBUilder;
894 * Converts output list of generated TO builders to one TO builder (first
895 * from list) which contains the remaining builders as its enclosing TO.
897 * @param basePackageName
898 * string with name of package to which the module belongs
900 * type definition which should be of type
901 * <code>UnionTypeDefinition</code>
903 * string with name for generated TO
904 * @return generated TO builder with the list of enclosed generated TO
907 public GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final String basePackageName,
908 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode, final SchemaContext
909 schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
911 final List<GeneratedTOBuilder> builders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
912 typedef, typeDefName, parentNode, schemaContext, genTypeDefsContextMap);
913 Preconditions.checkState(!builders.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typedef);
915 final GeneratedTOBuilder resultTOBuilder = builders.remove(0);
916 for (final GeneratedTOBuilder genTOBuilder : builders) {
917 resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
920 final GeneratedPropertyBuilder genPropBuilder;
922 genPropBuilder = resultTOBuilder.addProperty("value").setReturnType(Types.CHAR_ARRAY).setReadOnly(false);
923 resultTOBuilder.addEqualsIdentity(genPropBuilder);
924 resultTOBuilder.addHashIdentity(genPropBuilder);
925 resultTOBuilder.addToStringProperty(genPropBuilder);
927 provideGeneratedTOBuilderForUnionBuilder(findParentModule(schemaContext, parentNode), resultTOBuilder);
929 return resultTOBuilder;
933 private GeneratedTOBuilder provideGeneratedTOBuilderForUnionBuilder(final Module parentModule,
934 final GeneratedTOBuilder genTOBuilder) {
935 final String outerCls = Types.getOuterClassName(genTOBuilder);
936 final StringBuilder name;
937 if (outerCls != null) {
938 name = new StringBuilder(outerCls);
940 name = new StringBuilder();
942 name.append(genTOBuilder.getName());
943 name.append("Builder");
944 final GeneratedTOBuilderImpl unionBuilder = new GeneratedTOBuilderImpl(getOuterClassPackageName(genTOBuilder),
945 name.toString(), true);
946 unionBuilder.setIsUnionBuilder(true);
948 final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
949 method.setReturnType(genTOBuilder);
950 method.addParameter(Types.STRING, "defaultValue");
951 method.setAccessModifier(AccessModifier.PUBLIC);
952 method.setStatic(true);
954 final Set<Type> types = this.getAdditionalTypes().get(parentModule);
956 this.getAdditionalTypes().put(parentModule,
957 Sets.newHashSet(unionBuilder.toInstance()));
959 types.add(unionBuilder.toInstance());
966 * Wraps code which handle case when union subtype is of the type
967 * <code>ExtendedType</code>.
969 * If TO for this type already exists it is used for the creation of the
970 * property in <code>parentUnionGenTOBuilder</code>. In other case the base
971 * type is used for the property creation.
973 * @param parentUnionGenTOBuilder
974 * generated TO builder in which new property is created
975 * @param unionSubtype
976 * type definition of the <code>ExtendedType</code> type which
977 * represents union subtype
978 * @param regularExpressions
979 * list of strings with the regular expressions
981 * parent Schema Node for Extended Subtype
984 private static void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder, final
985 TypeDefinition<?> unionSubtype, final List<String> regularExpressions, final SchemaNode parentNode,
986 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
988 final String unionTypeName = unionSubtype.getQName().getLocalName();
989 final Type genTO = findGenTO(unionTypeName, unionSubtype, schemaContext, genTypeDefsContextMap);
991 updateUnionTypeAsProperty(parentUnionGenTOBuilder, genTO, genTO.getName());
993 final TypeDefinition<?> baseType = baseTypeDefForExtendedType(unionSubtype);
994 if (unionTypeName.equals(baseType.getQName().getLocalName())) {
995 final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType,
997 if (javaType != null) {
998 updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
1001 if (baseType instanceof StringTypeDefinition) {
1002 regularExpressions.addAll(resolveRegExpressionsFromTypedef(unionSubtype));
1008 * Returns string which contains the same value as <code>name</code> but
1009 * integer suffix is incremented by one. If <code>name</code> contains no
1010 * number suffix then number 1 is added.
1013 * string with name of augmented node
1014 * @return string with the number suffix incremented by one (or 1 is added)
1016 private static String provideAvailableNameForGenTOBuilder(final String name) {
1017 final Matcher mtch = NUMBERS_PATTERN.matcher(name);
1019 final int newSuffix = Integer.valueOf(name.substring(mtch.start())) + 1;
1020 return name.substring(0, mtch.start()) + newSuffix;
1027 * Searches for generated TO for <code>searchedTypeDef</code> type
1028 * definition in {@link #genTypeDefsContextMap genTypeDefsContextMap}
1030 * @param searchedTypeName
1031 * string with name of <code>searchedTypeDef</code>
1032 * @return generated TO for <code>searchedTypeDef</code> or
1033 * <code>null</code> it it doesn't exist
1035 private static Type findGenTO(final String searchedTypeName, final SchemaNode parentNode,
1036 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
1038 final Module typeModule = findParentModule(schemaContext, parentNode);
1039 if (typeModule != null && typeModule.getName() != null) {
1040 final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(typeModule.getName());
1041 final Map<String, Type> genTOs = modulesByDate.get(typeModule.getRevision());
1042 if (genTOs != null) {
1043 return genTOs.get(searchedTypeName);
1050 * Adds enumeration to <code>typeBuilder</code>. The enumeration data are
1051 * taken from <code>enumTypeDef</code>.
1053 * @param enumTypeDef
1054 * enumeration type definition is source of enumeration data for
1055 * <code>typeBuilder</code>
1057 * string with the name of enumeration
1058 * @param typeBuilder
1059 * generated type builder to which is enumeration added
1060 * @return enumeration type which contains enumeration data form
1061 * <code>enumTypeDef</code>
1062 * @throws IllegalArgumentException
1064 * <li>if <code>enumTypeDef</code> equals null</li>
1065 * <li>if enum values of <code>enumTypeDef</code> equal null</li>
1066 * <li>if Q name of <code>enumTypeDef</code> equal null</li>
1067 * <li>if name of <code>enumTypeDef</code> equal null</li>
1068 * <li>if name of <code>typeBuilder</code> equal null</li>
1072 private static Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef, final String enumName, final GeneratedTypeBuilderBase<?> typeBuilder) {
1073 Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
1074 Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
1075 "Local Name in EnumTypeDefinition QName cannot be NULL!");
1076 Preconditions.checkArgument(typeBuilder != null, "Generated Type Builder reference cannot be NULL!");
1078 final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumName);
1079 final String enumTypedefDescription = encodeAngleBrackets(enumTypeDef.getDescription());
1080 enumBuilder.setDescription(enumTypedefDescription);
1081 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
1082 return enumBuilder.toInstance(enumBuilder);
1085 private static boolean isLeafRefSelfReference(final LeafrefTypeDefinition leafref, final SchemaNode parentNode,
1086 final SchemaContext schemaContext) {
1087 final SchemaNode leafRefValueNode;
1088 final RevisionAwareXPath leafRefXPath = leafref.getPathStatement();
1089 final RevisionAwareXPath leafRefStrippedXPath = new RevisionAwareXPathImpl(leafRefXPath.toString()
1090 .replaceAll("\\[(.*?)\\]", ""), leafRefXPath.isAbsolute());
1092 ///// skip leafrefs in augments - they're checked once augments are resolved
1093 final Iterator<QName> iterator = parentNode.getPath().getPathFromRoot().iterator();
1094 boolean isAugmenting = false;
1095 DataNodeContainer current = null;
1096 DataSchemaNode dataChildByName;
1098 while (iterator.hasNext() && !isAugmenting) {
1099 final QName next = iterator.next();
1100 if (current == null) {
1101 dataChildByName = schemaContext.getDataChildByName(next);
1103 dataChildByName = current.getDataChildByName(next);
1105 if (dataChildByName != null) {
1106 isAugmenting = dataChildByName.isAugmenting();
1110 if (dataChildByName instanceof DataNodeContainer) {
1111 current = (DataNodeContainer) dataChildByName;
1119 final Module parentModule = getParentModule(parentNode, schemaContext);
1120 if (!leafRefStrippedXPath.isAbsolute()) {
1121 leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
1122 parentNode, leafRefStrippedXPath);
1124 leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath);
1126 return (leafRefValueNode != null) && leafRefValueNode.equals(parentNode);