2 * Copyright (c) 2017 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.mdsal.binding.javav2.generator.yang.types;
11 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
12 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.packageNameWithNamespacePrefix;
13 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.getOuterClassPackageName;
14 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.addStringRegExAsConstant;
15 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.baseTypeDefForExtendedType;
16 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.getAllTypedefs;
17 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.getParentModule;
18 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.makeSerializable;
19 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.provideGeneratedTOFromExtendedType;
20 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.provideTypeForEnum;
21 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.resolveRegExpressionsFromTypedef;
22 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.sortTypeDefinitionAccordingDepth;
23 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.wrapJavaTypeIntoTO;
24 import static org.opendaylight.mdsal.binding.javav2.util.BindingMapping.getRootPackageName;
25 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
26 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
27 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
29 import com.google.common.base.Optional;
30 import com.google.common.annotations.Beta;
31 import com.google.common.base.Preconditions;
32 import com.google.common.base.Strings;
33 import com.google.common.collect.Sets;
34 import java.util.ArrayList;
35 import java.util.Collections;
36 import java.util.Date;
37 import java.util.HashMap;
38 import java.util.Iterator;
39 import java.util.List;
42 import java.util.regex.Matcher;
43 import java.util.regex.Pattern;
44 import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
45 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
46 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
47 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier;
48 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer;
49 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
50 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
51 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
52 import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier;
53 import org.opendaylight.mdsal.binding.javav2.model.api.Enumeration;
54 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty;
55 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
56 import org.opendaylight.mdsal.binding.javav2.model.api.Restrictions;
57 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
58 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.EnumBuilder;
59 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedPropertyBuilder;
60 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder;
61 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilderBase;
62 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.MethodSignatureBuilder;
63 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
64 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
65 import org.opendaylight.yangtools.yang.common.QName;
66 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
67 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
68 import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
69 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
70 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
71 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
72 import org.opendaylight.yangtools.yang.model.api.Module;
73 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
74 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
75 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
76 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
77 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
78 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
79 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
80 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
81 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
82 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
83 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
84 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
85 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
86 import org.opendaylight.yangtools.yang.model.util.ModuleDependencySort;
87 import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
88 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
89 import org.opendaylight.yangtools.yang.parser.util.YangValidationException;
90 import org.slf4j.Logger;
91 import org.slf4j.LoggerFactory;
94 public final class TypeProviderImpl implements TypeProvider {
96 private static final Logger LOG = LoggerFactory.getLogger(TypeProviderImpl.class);
97 private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
100 * Contains the schema data red from YANG files.
102 private final SchemaContext schemaContext;
105 * Map<moduleName, Map<moduleDate, Map<typeName, type>>>
107 private final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap;
110 * Map which maps schema paths to JAVA <code>Type</code>.
112 private final Map<SchemaPath, Type> referencedTypes;
115 * Map for additional types e.g unions
117 private final Map<Module, Set<Type>> additionalTypes;
120 * Creates new instance of class <code>TypeProviderImpl</code>.
122 * @param schemaContext
123 * contains the schema data red from YANG files
124 * @throws IllegalArgumentException
125 * if <code>schemaContext</code> equal null.
127 public TypeProviderImpl(final SchemaContext schemaContext) {
128 this.schemaContext = schemaContext;
129 this.genTypeDefsContextMap = new HashMap<>();
130 this.referencedTypes = new HashMap<>();
131 this.additionalTypes = new HashMap<>();
132 resolveTypeDefsFromContext(schemaContext, this.genTypeDefsContextMap, this.additionalTypes);
136 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode,
137 ModuleContext context) {
138 return javaTypeForSchemaDefinitionType(type, parentNode, null, context);
142 * Converts schema definition type <code>typeDefinition</code> to JAVA
146 * type definition which is converted to JAVA type
147 * @throws IllegalArgumentException
149 * <li>if <code>typeDefinition</code> equal null</li>
150 * <li>if QName of <code>typeDefinition</code> equal null</li>
151 * <li>if name of <code>typeDefinition</code> equal null</li>
155 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode, final
156 Restrictions restrictions, ModuleContext context) {
157 return javaTypeForSchemaDefType(type, parentNode, restrictions, this.schemaContext, this
158 .genTypeDefsContextMap, context);
162 public String getTypeDefaultConstruction(final LeafSchemaNode node) {
167 public String getConstructorPropertyName(final SchemaNode node) {
172 public String getParamNameFromType(final TypeDefinition<?> type) {
176 public Map<String, Map<Date, Map<String, Type>>> getGenTypeDefsContextMap() {
177 return this.genTypeDefsContextMap;
181 * Passes through all modules and through all its type definitions and
182 * convert it to generated types.
184 * The modules are firstly sorted by mutual dependencies. The modules are
185 * sequentially passed. All type definitions of a module are at the
186 * beginning sorted so that type definition with less amount of references
187 * to other type definition are processed first.<br />
188 * For each module is created mapping record in the map
189 * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap}
190 * which map current module name to the map which maps type names to
191 * returned types (generated types).
194 private void resolveTypeDefsFromContext(final SchemaContext schemaContext, final Map<String, Map<Date, Map<String,
195 Type>>> genTypeDefsContextMap, final Map<Module, Set<Type>> additionalTypes) {
197 final Set<Module> modules = schemaContext.getModules();
198 Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL!");
199 final List<Module> modulesSortedByDependency = ModuleDependencySort.sort(modules);
201 for (final Module module : modulesSortedByDependency) {
202 Map<Date, Map<String, Type>> dateTypeMap = genTypeDefsContextMap.get(module.getName());
203 if (dateTypeMap == null) {
204 dateTypeMap = new HashMap<>();
206 dateTypeMap.put(module.getRevision(), Collections.emptyMap());
207 genTypeDefsContextMap.put(module.getName(), dateTypeMap);
210 modulesSortedByDependency.stream().filter(module -> module != null).forEach(module -> {
211 ModuleContext context = new ModuleContext();
212 final String basePackageName = packageNameWithNamespacePrefix(getRootPackageName(module),
213 BindingNamespaceType.Typedef);
214 final List<TypeDefinition<?>> typeDefinitions = getAllTypedefs(module);
215 final List<TypeDefinition<?>> listTypeDefinitions = sortTypeDefinitionAccordingDepth(typeDefinitions);
216 if (listTypeDefinitions != null) {
217 for (final TypeDefinition<?> typedef : listTypeDefinitions) {
218 typedefToGeneratedType(basePackageName, module, typedef, genTypeDefsContextMap,
219 additionalTypes, schemaContext, context);
226 * Converts <code>typeDefinition</code> to concrete JAVA <code>Type</code>.
228 * @param typeDefinition
229 * type definition which should be converted to JAVA
231 * @return JAVA <code>Type</code> which represents
232 * <code>typeDefinition</code>
233 * @throws IllegalArgumentException
235 * <li>if <code>typeDefinition</code> equal null</li>
236 * <li>if Q name of <code>typeDefinition</code></li>
237 * <li>if name of <code>typeDefinition</code></li>
240 public Type generatedTypeForExtendedDefinitionType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode) {
241 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
242 Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
243 "Type Definitions Local Name cannot be NULL!");
245 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
246 if (!(baseTypeDef instanceof LeafrefTypeDefinition) && !(baseTypeDef instanceof IdentityrefTypeDefinition)) {
247 final Module module = findParentModule(this.schemaContext, parentNode);
249 if (module != null) {
250 final Map<Date, Map<String, Type>> modulesByDate = this.genTypeDefsContextMap.get(module.getName());
251 final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
252 if (genTOs != null) {
253 return genTOs.get(typeDefinition.getQName().getLocalName());
261 * Puts <code>refType</code> to map with key <code>refTypePath</code>
264 * schema path used as the map key
266 * type which represents the map value
267 * @throws IllegalArgumentException
269 * <li>if <code>refTypePath</code> equal null</li>
270 * <li>if <code>refType</code> equal null</li>
274 public void putReferencedType(final SchemaPath refTypePath, final Type refType) {
275 Preconditions.checkArgument(refTypePath != null,
276 "Path reference of Enumeration Type Definition cannot be NULL!");
277 Preconditions.checkArgument(refType != null, "Reference to Enumeration Type cannot be NULL!");
278 this.referencedTypes.put(refTypePath, refType);
282 * Converts <code>typeDef</code> which should be of the type
283 * <code>BitsTypeDefinition</code> to <code>GeneratedTOBuilder</code>.
285 * All the bits of the typeDef are added to returning generated TO as
288 * @param basePackageName
289 * string with name of package to which the module belongs
291 * type definition from which is the generated TO builder created
293 * string with the name for generated TO builder
294 * @return generated TO builder which represents <code>typeDef</code>
295 * @throws IllegalArgumentException
297 * <li>if <code>typeDef</code> equals null</li>
298 * <li>if <code>basePackageName</code> equals null</li>
301 @SuppressWarnings({ "rawtypes", "unchecked" })
302 public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName,
303 final TypeDefinition<?> typeDef, final String typeDefName, final String moduleName, ModuleContext context) {
305 Preconditions.checkArgument(typeDef != null, "typeDef cannot be NULL!");
306 Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
308 if (typeDef instanceof BitsTypeDefinition) {
309 final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
311 final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName,
312 true, false, context);
313 final String typedefDescription = encodeAngleBrackets(typeDef.getDescription());
315 genTOBuilder.setDescription(typedefDescription);
316 genTOBuilder.setReference(typeDef.getReference());
317 genTOBuilder.setSchemaPath((List) typeDef.getPath().getPathFromRoot());
318 genTOBuilder.setModuleName(moduleName);
319 genTOBuilder.setBaseType(typeDef);
321 final List<Bit> bitList = bitsTypeDefinition.getBits();
322 GeneratedPropertyBuilder genPropertyBuilder;
323 for (final Bit bit : bitList) {
324 final String name = bit.getName();
326 genTOBuilder.addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(name, JavaIdentifier.METHOD));
327 genPropertyBuilder.setReadOnly(true);
328 genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE);
330 genTOBuilder.addEqualsIdentity(genPropertyBuilder);
331 genTOBuilder.addHashIdentity(genPropertyBuilder);
332 genTOBuilder.addToStringProperty(genPropertyBuilder);
341 * Converts <code>typedef</code> to generated TO with
342 * <code>typeDefName</code>. Every union type from <code>typedef</code> is
343 * added to generated TO builder as property.
345 * @param basePackageName
346 * string with name of package to which the module belongs
348 * type definition which should be of type
349 * <code>UnionTypeDefinition</code>
351 * string with name for generated TO
352 * @return generated TO builder which represents <code>typedef</code>
353 * @throws NullPointerException
355 * <li>if <code>basePackageName</code> is null</li>
356 * <li>if <code>typedef</code> is null</li>
357 * <li>if QName of <code>typedef</code> is null</li>
360 @SuppressWarnings({ "rawtypes", "unchecked" })
361 public List<GeneratedTOBuilder> provideGeneratedTOBuildersForUnionTypeDef(final String basePackageName,
362 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode,
363 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap, ModuleContext context) {
364 Preconditions.checkNotNull(basePackageName, "Base Package Name cannot be NULL!");
365 Preconditions.checkNotNull(typedef, "Type Definition cannot be NULL!");
366 Preconditions.checkNotNull(typedef.getQName(), "Type definition QName cannot be NULL!");
368 final List<GeneratedTOBuilder> generatedTOBuilders = new ArrayList<>();
369 final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
370 final Module module = findParentModule(schemaContext, parentNode);
372 final GeneratedTOBuilderImpl unionGenTOBuilder;
373 unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName, true, false,
375 final String typedefDescription = encodeAngleBrackets(typedef.getDescription());
376 unionGenTOBuilder.setDescription(typedefDescription);
377 unionGenTOBuilder.setReference(typedef.getReference());
378 unionGenTOBuilder.setSchemaPath((List) typedef.getPath().getPathFromRoot());
379 unionGenTOBuilder.setModuleName(module.getName());
381 generatedTOBuilders.add(unionGenTOBuilder);
382 unionGenTOBuilder.setIsUnion(true);
383 final List<String> regularExpressions = new ArrayList<>();
384 for (final TypeDefinition<?> unionType : unionTypes) {
385 final String unionTypeName = unionType.getQName().getLocalName();
386 if (unionType.getBaseType() != null) {
387 resolveExtendedSubtypeAsUnion(unionGenTOBuilder, unionType, regularExpressions,
388 parentNode, schemaContext, genTypeDefsContextMap);
389 } else if (unionType instanceof UnionTypeDefinition) {
390 generatedTOBuilders.add(resolveUnionSubtypeAsUnion(unionGenTOBuilder, (UnionTypeDefinition) unionType,
391 unionGenTOBuilder.getFullyQualifiedName(), parentNode, schemaContext, genTypeDefsContextMap,
393 } else if (unionType instanceof EnumTypeDefinition) {
394 final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType,
395 unionTypeName, unionGenTOBuilder, context);
396 updateUnionTypeAsProperty(unionGenTOBuilder, enumeration, unionTypeName);
398 final Type javaType = javaTypeForSchemaDefType(unionType, parentNode, null, schemaContext,
399 genTypeDefsContextMap, context);
400 updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName);
403 if (!regularExpressions.isEmpty()) {
404 addStringRegExAsConstant(unionGenTOBuilder, regularExpressions);
407 //storeGenTO(typedef, unionGenTOBuilder, parentNode);
409 return generatedTOBuilders;
412 public Map<Module, Set<Type>> getAdditionalTypes() {
413 return this.additionalTypes;
416 public static void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) {
417 if (!Strings.isNullOrEmpty(units)) {
418 to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\"");
419 final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
420 prop.setReturnType(Types.STRING);
421 to.addToStringProperty(prop);
425 private Type javaTypeForSchemaDefType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
426 final Restrictions r, final SchemaContext schemaContext,
427 final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap, ModuleContext context) {
428 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
429 final String typedefName = typeDefinition.getQName().getLocalName();
430 Preconditions.checkArgument(typedefName != null, "Type Definitions Local Name cannot be NULL!");
432 // Deal with base types
433 if (typeDefinition.getBaseType() == null) {
434 // We have to deal with differing handling of decimal64. The old parser used a fixed Decimal64 type
435 // and generated an enclosing ExtendedType to hold any range constraints. The new parser instantiates
436 // a base type which holds these constraints.
437 if (typeDefinition instanceof DecimalTypeDefinition) {
438 final Type ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType
439 (typeDefinition, parentNode, r, context);
445 // Deal with leafrefs/identityrefs
446 Type ret = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode, schemaContext,
447 genTypeDefsContextMap, context);
452 ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition, parentNode,
455 LOG.debug("Failed to resolve Java type for {}", typeDefinition);
461 Type returnType = javaTypeForExtendedType(typeDefinition, schemaContext, genTypeDefsContextMap, context);
462 if (r != null && !r.isEmpty() && returnType instanceof GeneratedTransferObject) {
463 final GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
464 final Module module = findParentModule(schemaContext, parentNode);
465 final Module module1 = findParentModule(schemaContext, typeDefinition);
466 final String basePackageName = BindingMapping.getRootPackageName(module);
467 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typeDefinition
468 .getPath(), BindingNamespaceType.Typedef);
469 final String genTOName =
470 JavaIdentifierNormalizer.normalizeSpecificIdentifier(typedefName, JavaIdentifier.CLASS);
471 final String name = packageName + "." + genTOName;
472 if (module.equals(module1) && !(returnType.getFullyQualifiedName().equals(name))) {
473 returnType = shadedTOWithRestrictions(gto, r, context);
481 * @param basePackageName
482 * string with name of package to which the module belongs
484 * string with the name of the module for to which the
485 * <code>typedef</code> belongs
487 * type definition of the node for which should be creted JAVA
488 * <code>Type</code> (usually generated TO)
489 * @return JAVA <code>Type</code> representation of <code>typedef</code> or
490 * <code>null</code> value if <code>basePackageName</code> or
491 * <code>modulName</code> or <code>typedef</code> or Q name of
492 * <code>typedef</code> equals <code>null</code>
494 private Type typedefToGeneratedType(final String basePackageName, final Module module,
495 final TypeDefinition<?> typedef, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap,
496 final Map<Module, Set<Type>> additionalTypes, final SchemaContext schemaContext, ModuleContext context) {
497 final String moduleName = module.getName();
498 final Date moduleRevision = module.getRevision();
499 if ((basePackageName != null) && (moduleName != null) && (typedef != null)) {
500 final String typedefName = typedef.getQName().getLocalName();
501 final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
502 if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
503 && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) {
505 if (innerTypeDefinition.getBaseType() != null) {
506 returnType = provideGeneratedTOFromExtendedType(typedef, innerTypeDefinition, basePackageName,
507 module.getName(), schemaContext, genTypeDefsContextMap, context);
508 } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
509 final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
510 (UnionTypeDefinition) innerTypeDefinition, typedefName, typedef, schemaContext,
511 genTypeDefsContextMap, context);
512 genTOBuilder.setTypedef(true);
513 genTOBuilder.setIsUnion(true);
514 addUnitsToGenTO(genTOBuilder, typedef.getUnits());
515 makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
516 returnType = genTOBuilder.toInstance();
517 } else if (innerTypeDefinition instanceof EnumTypeDefinition) {
518 // enums are automatically Serializable
519 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypeDefinition;
520 // TODO units for typedef enum
521 returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef, schemaContext, context);
522 } else if (innerTypeDefinition instanceof BitsTypeDefinition) {
523 final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition;
524 final GeneratedTOBuilder genTOBuilder =
525 provideGeneratedTOBuilderForBitsTypeDefinition(
526 basePackageName, bitsTypeDefinition, typedefName, module.getName(), context);
527 genTOBuilder.setTypedef(true);
528 addUnitsToGenTO(genTOBuilder, typedef.getUnits());
529 makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
530 returnType = genTOBuilder.toInstance();
532 final Type javaType = javaTypeForSchemaDefType(innerTypeDefinition, typedef, null,
533 schemaContext, genTypeDefsContextMap, context);
534 returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName(), context);
536 if (returnType != null) {
537 final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(moduleName);
538 Map<String, Type> typeMap = modulesByDate.get(moduleRevision);
539 if (typeMap != null) {
540 if (typeMap.isEmpty()) {
541 typeMap = new HashMap<>(4);
542 modulesByDate.put(moduleRevision, typeMap);
544 typeMap.put(typedefName, returnType);
554 * Returns JAVA <code>Type</code> for instances of the type
555 * <code>ExtendedType</code>.
557 * @param typeDefinition
558 * type definition which is converted to JAVA <code>Type</code>
559 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
561 private Type javaTypeForExtendedType(final TypeDefinition<?> typeDefinition, final SchemaContext schemaContext,
562 final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap, ModuleContext context) {
564 final String typedefName = typeDefinition.getQName().getLocalName();
565 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
566 Type returnType = javaTypeForLeafrefOrIdentityRef(baseTypeDef, typeDefinition, schemaContext,
567 genTypeDefsContextMap, context);
568 if (returnType == null) {
569 final Module module = findParentModule(schemaContext, typeDefinition);
570 final Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
571 if (module != null) {
572 final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module.getName());
573 final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
574 if (genTOs != null) {
575 returnType = genTOs.get(typedefName);
577 if (returnType == null) {
578 returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
579 baseTypeDef, typeDefinition, r, context);
587 * Returns JAVA <code>Type</code> for instances of the type
588 * <code>LeafrefTypeDefinition</code> or
589 * <code>IdentityrefTypeDefinition</code>.
591 * @param typeDefinition
592 * type definition which is converted to JAVA <code>Type</code>
593 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
595 private Type javaTypeForLeafrefOrIdentityRef(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
596 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap,
597 ModuleContext context) {
598 if (typeDefinition instanceof LeafrefTypeDefinition) {
599 final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition;
600 if (isLeafRefSelfReference(leafref, parentNode, schemaContext)) {
601 throw new YangValidationException("Leafref " + leafref.toString() + " is referencing itself, incoming" +
602 " StackOverFlowError detected.");
604 return provideTypeForLeafref(leafref, parentNode, schemaContext, genTypeDefsContextMap, context);
605 } else if (typeDefinition instanceof IdentityrefTypeDefinition) {
606 final IdentityrefTypeDefinition idref = (IdentityrefTypeDefinition) typeDefinition;
607 return provideTypeForIdentityref(idref, schemaContext);
614 * Converts <code>leafrefType</code> to JAVA <code>Type</code>.
616 * The path of <code>leafrefType</code> is followed to find referenced node
617 * and its <code>Type</code> is returned.
620 * leafref type definition for which is the type sought
621 * @return JAVA <code>Type</code> of data schema node which is referenced in
622 * <code>leafrefType</code>
623 * @throws IllegalArgumentException
625 * <li>if <code>leafrefType</code> equal null</li>
626 * <li>if path statement of <code>leafrefType</code> equal null</li>
630 public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode,
631 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap,
632 ModuleContext context) {
634 Type returnType = null;
635 Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!");
637 Preconditions.checkArgument(leafrefType.getPathStatement() != null,
638 "The Path Statement for Leafref Type Definition cannot be NULL!");
640 final RevisionAwareXPath xpath = leafrefType.getPathStatement();
641 final String strXPath = xpath.toString();
642 if (strXPath != null) {
643 if (strXPath.indexOf('[') == -1) {
645 final SchemaNode actualParentSchemaNode;
646 if ((parentNode instanceof DerivableSchemaNode) && ((DerivableSchemaNode) parentNode).isAddedByUses()) {
647 final Optional<? extends SchemaNode> originalNode = ((DerivableSchemaNode) parentNode).getOriginal();
648 Preconditions.checkArgument(originalNode.isPresent(), "originalNode can not be null.");
649 actualParentSchemaNode = originalNode.get();
650 module = findParentModule(schemaContext, originalNode.get());
652 actualParentSchemaNode = parentNode;
653 module = findParentModule(schemaContext, parentNode);
655 Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode);
657 final SchemaNode dataNode;
658 if (xpath.isAbsolute()) {
659 dataNode = findDataSchemaNode(schemaContext, module, xpath);
661 dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, actualParentSchemaNode, xpath);
663 Preconditions.checkArgument(dataNode != null, "Failed to find leafref target: %s in module %s (%s)",
664 strXPath, getParentModule(parentNode, schemaContext).getName(), parentNode.getQName().getModule());
666 if (leafContainsEnumDefinition(dataNode)) {
667 returnType = this.referencedTypes.get(dataNode.getPath());
668 } else if (leafListContainsEnumDefinition(dataNode)) {
669 returnType = Types.listTypeFor(this.referencedTypes.get(dataNode.getPath()));
671 returnType = resolveTypeFromDataSchemaNode(dataNode, schemaContext, genTypeDefsContextMap, context);
674 returnType = Types.typeForClass(Object.class);
677 Preconditions.checkArgument(returnType != null, "Failed to find leafref target: %s in module %s (%s)",
678 strXPath, getParentModule(parentNode, schemaContext).getName(), parentNode.getQName().getModule());
683 * Checks if <code>dataNode</code> is <code>LeafSchemaNode</code> and if it
684 * so then checks if it is of type <code>EnumTypeDefinition</code>.
687 * data schema node for which is checked if it is leaf and if it
689 * @return boolean value
691 * <li>true - if <code>dataNode</code> is leaf of type enumeration</li>
692 * <li>false - other cases</li>
695 private static boolean leafContainsEnumDefinition(final SchemaNode dataNode) {
696 if (dataNode instanceof LeafSchemaNode) {
697 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
698 //CompatUtils is not used here anymore
699 if (leaf.getType() instanceof EnumTypeDefinition) {
707 * Checks if <code>dataNode</code> is <code>LeafListSchemaNode</code> and if
708 * it so then checks if it is of type <code>EnumTypeDefinition</code>.
711 * data schema node for which is checked if it is leaflist and if
713 * @return boolean value
715 * <li>true - if <code>dataNode</code> is leaflist of type
717 * <li>false - other cases</li>
720 private static boolean leafListContainsEnumDefinition(final SchemaNode dataNode) {
721 if (dataNode instanceof LeafListSchemaNode) {
722 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
723 if (leafList.getType() instanceof EnumTypeDefinition) {
731 * Converts <code>dataNode</code> to JAVA <code>Type</code>.
734 * contains information about YANG type
735 * @return JAVA <code>Type</code> representation of <code>dataNode</code>
737 private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode, final SchemaContext schemaContext,
738 final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap, ModuleContext context) {
739 Type returnType = null;
740 if (dataNode != null) {
741 if (dataNode instanceof LeafSchemaNode) {
742 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
743 //not using CompatUtils here anymore
744 final TypeDefinition<?> type = leaf.getType();
745 returnType = javaTypeForSchemaDefType(type, leaf, null, schemaContext, genTypeDefsContextMap, context);
746 } else if (dataNode instanceof LeafListSchemaNode) {
747 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
748 returnType = javaTypeForSchemaDefType(leafList.getType(), leafList, null, schemaContext,
749 genTypeDefsContextMap, context);
756 * Seeks for identity reference <code>idref</code> the JAVA
757 * <code>type</code>.<br />
761 * If identy which is referenced via <code>idref</code> has name <b>Idn</b>
762 * then returning type is <b>{@code Class<? extends Idn>}</b></i>
765 * identityref type definition for which JAVA <code>Type</code>
767 * @return JAVA <code>Type</code> of the identity which is refrenced through
770 private static Type provideTypeForIdentityref(final IdentityrefTypeDefinition idref, final SchemaContext schemaContext) {
771 //TODO: incompatibility with Binding spec v2, get first or only one
772 final QName baseIdQName = idref.getIdentities().iterator().next().getQName();
773 final Module module = schemaContext.findModuleByNamespaceAndRevision(baseIdQName.getNamespace(),
774 baseIdQName.getRevision());
775 IdentitySchemaNode identity = null;
776 for (final IdentitySchemaNode id : module.getIdentities()) {
777 if (id.getQName().equals(baseIdQName)) {
781 Preconditions.checkArgument(identity != null, "Target identity '" + baseIdQName + "' do not exists");
783 final String basePackageName = BindingMapping.getRootPackageName(module);
784 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity.getPath
785 (), BindingNamespaceType.Identity);
787 final String genTypeName = JavaIdentifierNormalizer.normalizeSpecificIdentifier(identity.getQName().getLocalName(),
788 JavaIdentifier.CLASS);
790 final Type baseType = Types.typeForClass(Class.class);
791 final Type paramType = Types.wildcardTypeFor(packageName, genTypeName, true, true, null);
792 return Types.parameterizedTypeFor(baseType, paramType);
795 private static GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto,
796 final Restrictions r, ModuleContext context) {
797 final GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName(), context);
798 final GeneratedTransferObject parent = gto.getSuperType();
799 if (parent != null) {
800 gtob.setExtendsType(parent);
802 gtob.setRestrictions(r);
803 for (final GeneratedProperty gp : gto.getProperties()) {
804 final GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
805 gpb.setValue(gp.getValue());
806 gpb.setReadOnly(gp.isReadOnly());
807 gpb.setAccessModifier(gp.getAccessModifier());
808 gpb.setReturnType(gp.getReturnType());
809 gpb.setFinal(gp.isFinal());
810 gpb.setStatic(gp.isStatic());
812 return gtob.toInstance();
816 * Adds a new property with the name <code>propertyName</code> and with type
817 * <code>type</code> to <code>unonGenTransObject</code>.
819 * @param unionGenTransObject
820 * generated TO to which should be property added
822 * JAVA <code>type</code> of the property which should be added
823 * to <code>unionGentransObject</code>
824 * @param propertyName
825 * string with name of property which should be added to
826 * <code>unionGentransObject</code>
828 private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type, final String propertyName) {
829 if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) {
830 final GeneratedPropertyBuilder propBuilder = unionGenTransObject
831 .addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(propertyName, JavaIdentifier.METHOD));
832 propBuilder.setReturnType(type);
834 unionGenTransObject.addEqualsIdentity(propBuilder);
835 unionGenTransObject.addHashIdentity(propBuilder);
836 unionGenTransObject.addToStringProperty(propBuilder);
841 * Wraps code which handle case when union subtype is also of the type
842 * <code>UnionType</code>.
844 * In this case the new generated TO is created for union subtype (recursive
846 * {@link #provideGeneratedTOBuilderForUnionTypeDef(String, UnionTypeDefinition, String, SchemaNode, SchemaContext, Map, ModuleContext)}
847 * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder
848 * <code>parentUnionGenTOBuilder</code> is created property which type is
849 * equal to new generated TO.
851 * @param parentUnionGenTOBuilder
852 * generated TO builder to which is the property with the child
853 * union subtype added
854 * @param basePackageName
855 * string with the name of the module package
856 * @param unionSubtype
857 * type definition which represents union subtype
858 * @return list of generated TO builders. The number of the builders can be
859 * bigger one due to recursive call of
860 * <code>provideGeneratedTOBuildersForUnionTypeDef</code> method.
862 private GeneratedTOBuilder resolveUnionSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
863 final UnionTypeDefinition unionSubtype, final String basePackageName, final SchemaNode parentNode,
864 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap,
865 ModuleContext context) {
867 final String newTOBuilderName = provideAvailableNameForGenTOBuilder(parentUnionGenTOBuilder.getName());
868 final GeneratedTOBuilder subUnionGenTOBUilder = provideGeneratedTOBuilderForUnionTypeDef(
869 basePackageName, unionSubtype, newTOBuilderName, parentNode, schemaContext, genTypeDefsContextMap,
872 final GeneratedPropertyBuilder propertyBuilder;
873 propertyBuilder = parentUnionGenTOBuilder
874 .addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(newTOBuilderName, JavaIdentifier.METHOD));
875 propertyBuilder.setReturnType(subUnionGenTOBUilder);
876 parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder);
877 parentUnionGenTOBuilder.addToStringProperty(propertyBuilder);
879 return subUnionGenTOBUilder;
883 * Converts output list of generated TO builders to one TO builder (first
884 * from list) which contains the remaining builders as its enclosing TO.
886 * @param basePackageName
887 * string with name of package to which the module belongs
889 * type definition which should be of type
890 * <code>UnionTypeDefinition</code>
892 * string with name for generated TO
893 * @return generated TO builder with the list of enclosed generated TO
896 public GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final String basePackageName,
897 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode,
898 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap,
899 ModuleContext context) {
901 final List<GeneratedTOBuilder> builders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
902 typedef, typeDefName, parentNode, schemaContext, genTypeDefsContextMap, context);
903 Preconditions.checkState(!builders.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typedef);
905 final GeneratedTOBuilder resultTOBuilder = builders.remove(0);
906 for (final GeneratedTOBuilder genTOBuilder : builders) {
907 resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
910 final GeneratedPropertyBuilder genPropBuilder;
912 genPropBuilder = resultTOBuilder.addProperty("value").setReturnType(Types.CHAR_ARRAY).setReadOnly(false);
913 resultTOBuilder.addEqualsIdentity(genPropBuilder);
914 resultTOBuilder.addHashIdentity(genPropBuilder);
915 resultTOBuilder.addToStringProperty(genPropBuilder);
917 provideGeneratedTOBuilderForUnionBuilder(findParentModule(schemaContext, parentNode), resultTOBuilder);
919 return resultTOBuilder;
923 private GeneratedTOBuilder provideGeneratedTOBuilderForUnionBuilder(final Module parentModule,
924 final GeneratedTOBuilder genTOBuilder) {
925 final String outerCls = Types.getOuterClassName(genTOBuilder);
926 final StringBuilder name;
927 if (outerCls != null) {
928 name = new StringBuilder(outerCls);
930 name = new StringBuilder();
932 name.append(genTOBuilder.getName());
933 name.append("Builder");
934 final GeneratedTOBuilderImpl unionBuilder = new GeneratedTOBuilderImpl(getOuterClassPackageName(genTOBuilder),
935 name.toString(), true);
936 unionBuilder.setIsUnionBuilder(true);
938 final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
939 method.setReturnType(genTOBuilder);
940 method.addParameter(Types.STRING, "defaultValue");
941 method.setAccessModifier(AccessModifier.PUBLIC);
942 method.setStatic(true);
944 final Set<Type> types = this.getAdditionalTypes().get(parentModule);
946 this.getAdditionalTypes().put(parentModule,
947 Sets.newHashSet(unionBuilder.toInstance()));
949 types.add(unionBuilder.toInstance());
956 * Wraps code which handle case when union subtype is of the type
957 * <code>ExtendedType</code>.
959 * If TO for this type already exists it is used for the creation of the
960 * property in <code>parentUnionGenTOBuilder</code>. In other case the base
961 * type is used for the property creation.
963 * @param parentUnionGenTOBuilder
964 * generated TO builder in which new property is created
965 * @param unionSubtype
966 * type definition of the <code>ExtendedType</code> type which
967 * represents union subtype
968 * @param regularExpressions
969 * list of strings with the regular expressions
971 * parent Schema Node for Extended Subtype
974 private static void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
975 final TypeDefinition<?> unionSubtype, final List<String> regularExpressions, final SchemaNode parentNode,
976 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
978 final String unionTypeName = unionSubtype.getQName().getLocalName();
979 final Type genTO = findGenTO(unionTypeName, unionSubtype, schemaContext, genTypeDefsContextMap);
981 updateUnionTypeAsProperty(parentUnionGenTOBuilder, genTO, unionTypeName);
983 final TypeDefinition<?> baseType = baseTypeDefForExtendedType(unionSubtype);
984 if (unionTypeName.equals(baseType.getQName().getLocalName())) {
985 final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType,
987 if (javaType != null) {
988 updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
991 if (baseType instanceof StringTypeDefinition) {
992 regularExpressions.addAll(resolveRegExpressionsFromTypedef(unionSubtype));
998 * Returns string which contains the same value as <code>name</code> but
999 * integer suffix is incremented by one. If <code>name</code> contains no
1000 * number suffix then number 1 is added.
1003 * string with name of augmented node
1004 * @return string with the number suffix incremented by one (or 1 is added)
1006 private static String provideAvailableNameForGenTOBuilder(final String name) {
1007 final Matcher mtch = NUMBERS_PATTERN.matcher(name);
1009 final int newSuffix = Integer.valueOf(name.substring(mtch.start())) + 1;
1010 return name.substring(0, mtch.start()) + newSuffix;
1017 * Searches for generated TO for <code>searchedTypeDef</code> type
1018 * definition in {@link #genTypeDefsContextMap genTypeDefsContextMap}
1020 * @param searchedTypeName
1021 * string with name of <code>searchedTypeDef</code>
1022 * @return generated TO for <code>searchedTypeDef</code> or
1023 * <code>null</code> it it doesn't exist
1025 private static Type findGenTO(final String searchedTypeName, final SchemaNode parentNode,
1026 final SchemaContext schemaContext, final Map<String, Map<Date, Map<String, Type>>> genTypeDefsContextMap) {
1028 final Module typeModule = findParentModule(schemaContext, parentNode);
1029 if (typeModule != null && typeModule.getName() != null) {
1030 final Map<Date, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(typeModule.getName());
1031 final Map<String, Type> genTOs = modulesByDate.get(typeModule.getRevision());
1032 if (genTOs != null) {
1033 return genTOs.get(searchedTypeName);
1040 * Adds enumeration to <code>typeBuilder</code>. The enumeration data are
1041 * taken from <code>enumTypeDef</code>.
1043 * @param enumTypeDef
1044 * enumeration type definition is source of enumeration data for
1045 * <code>typeBuilder</code>
1047 * string with the name of enumeration
1048 * @param typeBuilder
1049 * generated type builder to which is enumeration added
1050 * @return enumeration type which contains enumeration data form
1051 * <code>enumTypeDef</code>
1052 * @throws IllegalArgumentException
1054 * <li>if <code>enumTypeDef</code> equals null</li>
1055 * <li>if enum values of <code>enumTypeDef</code> equal null</li>
1056 * <li>if Q name of <code>enumTypeDef</code> equal null</li>
1057 * <li>if name of <code>enumTypeDef</code> equal null</li>
1058 * <li>if name of <code>typeBuilder</code> equal null</li>
1062 private static Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef,
1063 final String enumName, final GeneratedTypeBuilderBase<?> typeBuilder, ModuleContext context) {
1064 Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
1065 Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
1066 "Local Name in EnumTypeDefinition QName cannot be NULL!");
1067 Preconditions.checkArgument(typeBuilder != null, "Generated Type Builder reference cannot be NULL!");
1069 final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumName, context);
1070 final String enumTypedefDescription = encodeAngleBrackets(enumTypeDef.getDescription());
1071 enumBuilder.setDescription(enumTypedefDescription);
1072 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
1073 return enumBuilder.toInstance(enumBuilder);
1076 private static boolean isLeafRefSelfReference(final LeafrefTypeDefinition leafref, final SchemaNode parentNode,
1077 final SchemaContext schemaContext) {
1078 final SchemaNode leafRefValueNode;
1079 final RevisionAwareXPath leafRefXPath = leafref.getPathStatement();
1080 final RevisionAwareXPath leafRefStrippedXPath = new RevisionAwareXPathImpl(leafRefXPath.toString()
1081 .replaceAll("\\[(.*?)\\]", ""), leafRefXPath.isAbsolute());
1083 ///// skip leafrefs in augments - they're checked once augments are resolved
1084 final Iterator<QName> iterator = parentNode.getPath().getPathFromRoot().iterator();
1085 boolean isAugmenting = false;
1086 DataNodeContainer current = null;
1087 DataSchemaNode dataChildByName;
1089 while (iterator.hasNext() && !isAugmenting) {
1090 final QName next = iterator.next();
1091 if (current == null) {
1092 dataChildByName = schemaContext.getDataChildByName(next);
1094 dataChildByName = current.getDataChildByName(next);
1096 if (dataChildByName != null) {
1097 isAugmenting = dataChildByName.isAugmenting();
1101 if (dataChildByName instanceof DataNodeContainer) {
1102 current = (DataNodeContainer) dataChildByName;
1110 final Module parentModule = getParentModule(parentNode, schemaContext);
1111 if (!leafRefStrippedXPath.isAbsolute()) {
1112 leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
1113 parentNode, leafRefStrippedXPath);
1115 leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath);
1117 return (leafRefValueNode != null) && leafRefValueNode.equals(parentNode);