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 java.util.Objects.requireNonNull;
12 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.encodeAngleBrackets;
13 import static org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil.packageNameWithNamespacePrefix;
14 import static org.opendaylight.mdsal.binding.javav2.generator.util.Types.getOuterClassPackageName;
15 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.addStringRegExAsConstant;
16 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.baseTypeDefForExtendedType;
17 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.getAllTypedefs;
18 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.getParentModule;
19 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.makeSerializable;
20 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.provideGeneratedTOFromExtendedType;
21 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.provideTypeForEnum;
22 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.resolveRegExpressionsFromTypedef;
23 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.sortTypeDefinitionAccordingDepth;
24 import static org.opendaylight.mdsal.binding.javav2.generator.yang.types.TypeGenHelper.wrapJavaTypeIntoTO;
25 import static org.opendaylight.mdsal.binding.javav2.util.BindingMapping.getRootPackageName;
26 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNode;
27 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findDataSchemaNodeForRelativeXPath;
28 import static org.opendaylight.yangtools.yang.model.util.SchemaContextUtil.findParentModule;
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;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.HashMap;
38 import java.util.Iterator;
39 import java.util.List;
41 import java.util.Objects;
42 import java.util.Optional;
44 import java.util.regex.Matcher;
45 import java.util.regex.Pattern;
47 import org.opendaylight.mdsal.binding.javav2.generator.context.ModuleContext;
48 import org.opendaylight.mdsal.binding.javav2.generator.spi.TypeProvider;
49 import org.opendaylight.mdsal.binding.javav2.generator.util.BindingGeneratorUtil;
50 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifier;
51 import org.opendaylight.mdsal.binding.javav2.generator.util.JavaIdentifierNormalizer;
52 import org.opendaylight.mdsal.binding.javav2.generator.util.Types;
53 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedPropertyBuilderImpl;
54 import org.opendaylight.mdsal.binding.javav2.generator.util.generated.type.builder.GeneratedTOBuilderImpl;
55 import org.opendaylight.mdsal.binding.javav2.model.api.AccessModifier;
56 import org.opendaylight.mdsal.binding.javav2.model.api.Enumeration;
57 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedProperty;
58 import org.opendaylight.mdsal.binding.javav2.model.api.GeneratedTransferObject;
59 import org.opendaylight.mdsal.binding.javav2.model.api.Restrictions;
60 import org.opendaylight.mdsal.binding.javav2.model.api.Type;
61 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.EnumBuilder;
62 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedPropertyBuilder;
63 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTOBuilder;
64 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.GeneratedTypeBuilderBase;
65 import org.opendaylight.mdsal.binding.javav2.model.api.type.builder.MethodSignatureBuilder;
66 import org.opendaylight.mdsal.binding.javav2.spec.runtime.BindingNamespaceType;
67 import org.opendaylight.mdsal.binding.javav2.util.BindingMapping;
68 import org.opendaylight.yangtools.yang.common.QName;
69 import org.opendaylight.yangtools.yang.common.Revision;
70 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
71 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
72 import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
73 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
74 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
75 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
76 import org.opendaylight.yangtools.yang.model.api.Module;
77 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
78 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
79 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
80 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
81 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
82 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
83 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition.Bit;
84 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
85 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
86 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
87 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
88 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
89 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
90 import org.opendaylight.yangtools.yang.model.util.ModuleDependencySort;
91 import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
92 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
93 import org.slf4j.Logger;
94 import org.slf4j.LoggerFactory;
97 public final class TypeProviderImpl implements TypeProvider {
99 private static final Logger LOG = LoggerFactory.getLogger(TypeProviderImpl.class);
100 private static final Pattern NUMBERS_PATTERN = Pattern.compile("[0-9]+\\z");
103 * Contains the schema data red from YANG files.
105 private final SchemaContext schemaContext;
108 * Map<moduleName, Map<moduleDate, Map<typeName, type>>>.
110 private final Map<String, Map<Optional<Revision>, Map<String, Type>>> genTypeDefsContextMap;
113 * Map which maps schema paths to JAVA <code>Type</code>.
115 private final Map<SchemaPath, Type> referencedTypes;
118 * Map for additional types e.g unions.
120 private final Map<Module, Set<Type>> additionalTypes;
123 * Creates new instance of class <code>TypeProviderImpl</code>.
125 * @param schemaContext contains the schema data red from YANG files
126 * @throws IllegalArgumentException if <code>schemaContext</code> equal null.
128 public TypeProviderImpl(final SchemaContext schemaContext) {
129 this.schemaContext = schemaContext;
130 this.genTypeDefsContextMap = new HashMap<>();
131 this.referencedTypes = new HashMap<>();
132 this.additionalTypes = new HashMap<>();
133 resolveTypeDefsFromContext();
137 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode,
138 final ModuleContext context) {
139 return javaTypeForSchemaDefinitionType(type, parentNode, null, context);
143 * Converts schema definition type <code>typeDefinition</code> to JAVA
146 * @param type type definition which is converted to JAVA type
147 * @throws IllegalArgumentException <ul>
148 * <li>if <code>typeDefinition</code> equal null</li>
149 * <li>if QName of <code>typeDefinition</code> equal null</li>
150 * <li>if name of <code>typeDefinition</code> equal null</li>
154 public Type javaTypeForSchemaDefinitionType(final TypeDefinition<?> type, final SchemaNode parentNode,
155 final Restrictions restrictions, final ModuleContext context) {
156 return javaTypeForSchemaDefType(type, parentNode, restrictions, context);
160 public String getTypeDefaultConstruction(final LeafSchemaNode node) {
165 public String getConstructorPropertyName(final SchemaNode node) {
170 public String getParamNameFromType(final TypeDefinition<?> type) {
174 public Map<String, Map<Optional<Revision>, Map<String, Type>>> getGenTypeDefsContextMap() {
175 return this.genTypeDefsContextMap;
179 * Passes through all modules and through all its type definitions and
180 * convert it to generated types.
183 * The modules are firstly sorted by mutual dependencies. The modules are
184 * sequentially passed. All type definitions of a module are at the
185 * beginning sorted so that type definition with less amount of references
186 * to other type definition are processed first.<br />
187 * For each module is created mapping record in the map
188 * {@link TypeProviderImpl#genTypeDefsContextMap genTypeDefsContextMap}
189 * which map current module name to the map which maps type names to
190 * returned types (generated types).
192 private void resolveTypeDefsFromContext() {
194 final Set<Module> modules = schemaContext.getModules();
195 Preconditions.checkArgument(modules != null, "Set of Modules cannot be NULL!");
196 final List<Module> modulesSortedByDependency = ModuleDependencySort.sort(modules);
198 for (final Module module : modulesSortedByDependency) {
199 Map<Optional<Revision>, Map<String, Type>> dateTypeMap = genTypeDefsContextMap.get(module.getName());
200 if (dateTypeMap == null) {
201 dateTypeMap = new HashMap<>();
203 dateTypeMap.put(module.getRevision(), Collections.emptyMap());
204 genTypeDefsContextMap.put(module.getName(), dateTypeMap);
207 modulesSortedByDependency.stream().filter(Objects::nonNull).forEach(module -> {
208 ModuleContext context = new ModuleContext();
209 final String basePackageName = packageNameWithNamespacePrefix(getRootPackageName(module),
210 BindingNamespaceType.Typedef);
211 final List<TypeDefinition<?>> typeDefinitions = getAllTypedefs(module);
212 for (TypeDefinition<?> typedef : sortTypeDefinitionAccordingDepth(typeDefinitions)) {
213 typedefToGeneratedType(basePackageName, module, typedef, context);
219 * Converts <code>typeDefinition</code> to concrete JAVA <code>Type</code>.
221 * @param typeDefinition type definition which should be converted to JAVA
223 * @return JAVA <code>Type</code> which represents
224 * <code>typeDefinition</code>
225 * @throws IllegalArgumentException <ul>
226 * <li>if <code>typeDefinition</code> equal null</li>
227 * <li>if Q name of <code>typeDefinition</code></li>
228 * <li>if name of <code>typeDefinition</code></li>
231 public Type generatedTypeForExtendedDefinitionType(final TypeDefinition<?> typeDefinition,
232 final SchemaNode parentNode) {
233 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
234 Preconditions.checkArgument(typeDefinition.getQName().getLocalName() != null,
235 "Type Definitions Local Name cannot be NULL!");
237 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
238 if (!(baseTypeDef instanceof LeafrefTypeDefinition) && !(baseTypeDef instanceof IdentityrefTypeDefinition)) {
239 final Module module = findParentModule(this.schemaContext, parentNode);
241 if (module != null) {
242 final Map<Optional<Revision>, Map<String, Type>> modulesByDate =
243 this.genTypeDefsContextMap.get(module.getName());
244 final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
245 if (genTOs != null) {
246 return genTOs.get(typeDefinition.getQName().getLocalName());
254 * Puts <code>refType</code> to map with key <code>refTypePath</code>.
256 * @param refTypePath schema path used as the map key
257 * @param refType type which represents the map value
258 * @throws IllegalArgumentException <ul>
259 * <li>if <code>refTypePath</code> equal null</li>
260 * <li>if <code>refType</code> equal null</li>
263 public void putReferencedType(final SchemaPath refTypePath, final Type refType) {
264 Preconditions.checkArgument(refTypePath != null,
265 "Path reference of Enumeration Type Definition cannot be NULL!");
266 Preconditions.checkArgument(refType != null, "Reference to Enumeration Type cannot be NULL!");
267 this.referencedTypes.put(refTypePath, refType);
271 * Converts <code>typeDef</code> which should be of the type
272 * <code>BitsTypeDefinition</code> to <code>GeneratedTOBuilder</code>.
275 * All the bits of the typeDef are added to returning generated TO as
278 * @param basePackageName string with name of package to which the module belongs
279 * @param typeDef type definition from which is the generated TO builder created
280 * @param typeDefName string with the name for generated TO builder
281 * @return generated TO builder which represents <code>typeDef</code>
282 * @throws IllegalArgumentException <ul>
283 * <li>if <code>typeDef</code> equals null</li>
284 * <li>if <code>basePackageName</code> equals null</li>
287 @SuppressWarnings({"rawtypes", "unchecked"})
288 public GeneratedTOBuilder provideGeneratedTOBuilderForBitsTypeDefinition(final String basePackageName,
289 final TypeDefinition<?> typeDef, final
290 String typeDefName, final String
292 final ModuleContext context) {
294 Preconditions.checkArgument(typeDef != null, "typeDef cannot be NULL!");
295 Preconditions.checkArgument(basePackageName != null, "Base Package Name cannot be NULL!");
297 if (typeDef instanceof BitsTypeDefinition) {
298 final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) typeDef;
300 final GeneratedTOBuilderImpl genTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName,
301 true, false, context);
302 final String typedefDescription = encodeAngleBrackets(typeDef.getDescription().orElse(null));
304 genTOBuilder.setDescription(typedefDescription);
305 typeDef.getReference().ifPresent(genTOBuilder::setReference);
306 genTOBuilder.setSchemaPath((List) typeDef.getPath().getPathFromRoot());
307 genTOBuilder.setModuleName(moduleName);
308 genTOBuilder.setBaseType(typeDef);
310 final List<Bit> bitList = bitsTypeDefinition.getBits();
311 GeneratedPropertyBuilder genPropertyBuilder;
312 for (final Bit bit : bitList) {
313 final String name = bit.getName();
314 genPropertyBuilder = genTOBuilder.addProperty(
315 JavaIdentifierNormalizer.normalizeSpecificIdentifier(name, JavaIdentifier.METHOD));
316 genPropertyBuilder.setReadOnly(true);
317 genPropertyBuilder.setReturnType(BaseYangTypes.BOOLEAN_TYPE);
319 genTOBuilder.addEqualsIdentity(genPropertyBuilder);
320 genTOBuilder.addHashIdentity(genPropertyBuilder);
321 genTOBuilder.addToStringProperty(genPropertyBuilder);
330 * Converts <code>typedef</code> to generated TO with
331 * <code>typeDefName</code>. Every union type from <code>typedef</code> is
332 * added to generated TO builder as property.
334 * @param basePackageName string with name of package to which the module belongs
335 * @param typedef type definition which should be of type
336 * <code>UnionTypeDefinition</code>
337 * @param typeDefName string with name for generated TO
338 * @return generated TO builder which represents <code>typedef</code>
339 * @throws NullPointerException <ul>
340 * <li>if <code>basePackageName</code> is null</li>
341 * <li>if <code>typedef</code> is null</li>
342 * <li>if QName of <code>typedef</code> is null</li>
345 @SuppressWarnings({"rawtypes", "unchecked"})
346 public List<GeneratedTOBuilder> provideGeneratedTOBuildersForUnionTypeDef(final String basePackageName,
347 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode,
348 final ModuleContext context) {
349 requireNonNull(basePackageName, "Base Package Name cannot be NULL!");
350 requireNonNull(typedef, "Type Definition cannot be NULL!");
351 requireNonNull(typedef.getQName(), "Type definition QName cannot be NULL!");
353 final List<GeneratedTOBuilder> generatedTOBuilders = new ArrayList<>();
354 final List<TypeDefinition<?>> unionTypes = typedef.getTypes();
355 final Module module = findParentModule(schemaContext, parentNode);
357 final GeneratedTOBuilderImpl unionGenTOBuilder;
358 unionGenTOBuilder = new GeneratedTOBuilderImpl(basePackageName, typeDefName, true, false,
360 final String typedefDescription = encodeAngleBrackets(typedef.getDescription().orElse(null));
361 unionGenTOBuilder.setDescription(typedefDescription);
362 typedef.getReference().ifPresent(unionGenTOBuilder::setReference);
363 unionGenTOBuilder.setSchemaPath((List) typedef.getPath().getPathFromRoot());
364 unionGenTOBuilder.setModuleName(module.getName());
366 generatedTOBuilders.add(unionGenTOBuilder);
367 unionGenTOBuilder.setIsUnion(true);
368 final Map<String, String> expressions = new HashMap<>();
369 for (final TypeDefinition<?> unionType : unionTypes) {
370 final String unionTypeName = unionType.getQName().getLocalName();
371 if (unionType.getBaseType() != null) {
372 resolveExtendedSubtypeAsUnion(unionGenTOBuilder, unionType, expressions, parentNode);
373 } else if (unionType instanceof UnionTypeDefinition) {
374 generatedTOBuilders.add(resolveUnionSubtypeAsUnion(unionGenTOBuilder, (UnionTypeDefinition) unionType,
375 unionGenTOBuilder.getFullyQualifiedName(), parentNode, context));
376 } else if (unionType instanceof EnumTypeDefinition) {
377 final Enumeration enumeration = addInnerEnumerationToTypeBuilder((EnumTypeDefinition) unionType,
378 unionTypeName, unionGenTOBuilder, context);
379 updateUnionTypeAsProperty(unionGenTOBuilder, enumeration, unionTypeName);
381 final Type javaType = javaTypeForSchemaDefType(unionType, parentNode, null, context);
382 updateUnionTypeAsProperty(unionGenTOBuilder, javaType, unionTypeName);
385 if (!expressions.isEmpty()) {
386 addStringRegExAsConstant(unionGenTOBuilder, expressions);
389 //storeGenTO(typedef, unionGenTOBuilder, parentNode);
391 return generatedTOBuilders;
394 public Map<Module, Set<Type>> getAdditionalTypes() {
395 return this.additionalTypes;
398 public static void addUnitsToGenTO(final GeneratedTOBuilder to, final String units) {
399 if (!Strings.isNullOrEmpty(units)) {
400 to.addConstant(Types.STRING, "_UNITS", "\"" + units + "\"");
401 final GeneratedPropertyBuilder prop = new GeneratedPropertyBuilderImpl("UNITS");
402 prop.setReturnType(Types.STRING);
403 to.addToStringProperty(prop);
407 private Type javaTypeForSchemaDefType(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
408 final Restrictions restrictions, final ModuleContext context) {
409 Preconditions.checkArgument(typeDefinition != null, "Type Definition cannot be NULL!");
410 final String typedefName = typeDefinition.getQName().getLocalName();
411 Preconditions.checkArgument(typedefName != null, "Type Definitions Local Name cannot be NULL!");
413 // Deal with base types
414 if (typeDefinition.getBaseType() == null) {
415 // We have to deal with differing handling of decimal64. The old parser used a fixed Decimal64 type
416 // and generated an enclosing ExtendedType to hold any range constraints. The new parser instantiates
417 // a base type which holds these constraints.
418 if (typeDefinition instanceof DecimalTypeDefinition) {
419 final Type ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition,
420 parentNode, restrictions, context);
426 // Deal with leafrefs/identityrefs
427 Type ret = javaTypeForLeafrefOrIdentityRef(typeDefinition, parentNode, context);
432 ret = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(typeDefinition, parentNode,
435 LOG.debug("Failed to resolve Java type for {}", typeDefinition);
441 Type returnType = javaTypeForExtendedType(typeDefinition, context);
442 if (restrictions != null && !restrictions.isEmpty() && returnType instanceof GeneratedTransferObject) {
443 final GeneratedTransferObject gto = (GeneratedTransferObject) returnType;
444 final Module module = findParentModule(schemaContext, parentNode);
445 final Module module1 = findParentModule(schemaContext, typeDefinition);
446 final String basePackageName = BindingMapping.getRootPackageName(module);
447 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, typeDefinition
448 .getPath(), BindingNamespaceType.Typedef);
449 final String genTOName =
450 JavaIdentifierNormalizer.normalizeSpecificIdentifier(typedefName, JavaIdentifier.CLASS);
451 final String name = packageName + "." + genTOName;
452 if (module.equals(module1) && !returnType.getFullyQualifiedName().equals(name)) {
453 returnType = shadedTOWithRestrictions(gto, restrictions, context);
460 * Return JAVA <code>Type</code> representation of <code>typedef</code>.
461 * @param basePackageName string with name of package to which the module belongs
462 * @param module string with the name of the module for to which the
463 * <code>typedef</code> belongs
464 * @param typedef type definition of the node for which should be creted JAVA
465 * <code>Type</code> (usually generated TO)
466 * @return JAVA <code>Type</code> representation of <code>typedef</code> or
467 * <code>null</code> value if <code>basePackageName</code> or
468 * <code>modulName</code> or <code>typedef</code> or Q name of
469 * <code>typedef</code> equals <code>null</code>
471 private Type typedefToGeneratedType(final String basePackageName, final Module module,
472 final TypeDefinition<?> typedef, final ModuleContext context) {
473 final String moduleName = module.getName();
474 final Optional<Revision> moduleRevision = module.getRevision();
475 if (basePackageName != null && moduleName != null && typedef != null) {
476 final String typedefName = typedef.getQName().getLocalName();
477 final TypeDefinition<?> innerTypeDefinition = typedef.getBaseType();
478 if (!(innerTypeDefinition instanceof LeafrefTypeDefinition)
479 && !(innerTypeDefinition instanceof IdentityrefTypeDefinition)) {
481 if (innerTypeDefinition.getBaseType() != null) {
482 returnType = provideGeneratedTOFromExtendedType(typedef, innerTypeDefinition, basePackageName,
483 module.getName(), schemaContext, genTypeDefsContextMap, context);
484 } else if (innerTypeDefinition instanceof UnionTypeDefinition) {
485 final GeneratedTOBuilder genTOBuilder = provideGeneratedTOBuilderForUnionTypeDef(basePackageName,
486 (UnionTypeDefinition) innerTypeDefinition, typedefName, typedef, context);
487 genTOBuilder.setTypedef(true);
488 genTOBuilder.setIsUnion(true);
489 addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null));
490 makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
491 returnType = genTOBuilder.toInstance();
492 } else if (innerTypeDefinition instanceof EnumTypeDefinition) {
493 // enums are automatically Serializable
494 final EnumTypeDefinition enumTypeDef = (EnumTypeDefinition) innerTypeDefinition;
495 // TODO units for typedef enum
496 returnType = provideTypeForEnum(enumTypeDef, typedefName, typedef, schemaContext, context);
497 } else if (innerTypeDefinition instanceof BitsTypeDefinition) {
498 final BitsTypeDefinition bitsTypeDefinition = (BitsTypeDefinition) innerTypeDefinition;
499 final GeneratedTOBuilder genTOBuilder =
500 provideGeneratedTOBuilderForBitsTypeDefinition(
501 basePackageName, bitsTypeDefinition, typedefName, module.getName(), context);
502 genTOBuilder.setTypedef(true);
503 addUnitsToGenTO(genTOBuilder, typedef.getUnits().orElse(null));
504 makeSerializable((GeneratedTOBuilderImpl) genTOBuilder);
505 returnType = genTOBuilder.toInstance();
507 final Type javaType = javaTypeForSchemaDefType(innerTypeDefinition, typedef, null,
509 returnType = wrapJavaTypeIntoTO(basePackageName, typedef, javaType, module.getName(), context);
511 if (returnType != null) {
512 final Map<Optional<Revision>, Map<String, Type>> modulesByDate =
513 genTypeDefsContextMap.get(moduleName);
514 Map<String, Type> typeMap = modulesByDate.get(moduleRevision);
515 if (typeMap != null) {
516 if (typeMap.isEmpty()) {
517 typeMap = new HashMap<>(4);
518 modulesByDate.put(moduleRevision, typeMap);
520 typeMap.put(typedefName, returnType);
530 * Returns JAVA <code>Type</code> for instances of the type
531 * <code>ExtendedType</code>.
533 * @param typeDefinition type definition which is converted to JAVA <code>Type</code>
534 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
536 private Type javaTypeForExtendedType(final TypeDefinition<?> typeDefinition, final ModuleContext context) {
538 final String typedefName = typeDefinition.getQName().getLocalName();
539 final TypeDefinition<?> baseTypeDef = baseTypeDefForExtendedType(typeDefinition);
540 Type returnType = javaTypeForLeafrefOrIdentityRef(baseTypeDef, typeDefinition, context);
541 if (returnType == null) {
542 final Module module = findParentModule(schemaContext, typeDefinition);
543 final Restrictions r = BindingGeneratorUtil.getRestrictions(typeDefinition);
544 if (module != null) {
545 final Map<Optional<Revision>, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(module
547 final Map<String, Type> genTOs = modulesByDate.get(module.getRevision());
548 if (genTOs != null) {
549 returnType = genTOs.get(typedefName);
551 if (returnType == null) {
552 returnType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(
553 baseTypeDef, typeDefinition, r, context);
561 * Returns JAVA <code>Type</code> for instances of the type
562 * <code>LeafrefTypeDefinition</code> or
563 * <code>IdentityrefTypeDefinition</code>.
565 * @param typeDefinition type definition which is converted to JAVA <code>Type</code>
566 * @return JAVA <code>Type</code> instance for <code>typeDefinition</code>
568 private Type javaTypeForLeafrefOrIdentityRef(final TypeDefinition<?> typeDefinition, final SchemaNode parentNode,
569 final ModuleContext context) {
570 if (typeDefinition instanceof LeafrefTypeDefinition) {
571 final LeafrefTypeDefinition leafref = (LeafrefTypeDefinition) typeDefinition;
572 Preconditions.checkArgument(!isLeafRefSelfReference(leafref, parentNode, schemaContext),
573 "Leafref %s is referencing itself, incoming StackOverFlowError detected.", leafref);
574 return provideTypeForLeafref(leafref, parentNode, context);
575 } else if (typeDefinition instanceof IdentityrefTypeDefinition) {
576 final IdentityrefTypeDefinition idref = (IdentityrefTypeDefinition) typeDefinition;
577 return provideTypeForIdentityref(idref, schemaContext);
584 * Converts <code>leafrefType</code> to JAVA <code>Type</code>.
587 * The path of <code>leafrefType</code> is followed to find referenced node
588 * and its <code>Type</code> is returned.
590 * @param leafrefType leafref type definition for which is the type sought
591 * @return JAVA <code>Type</code> of data schema node which is referenced in
592 * <code>leafrefType</code>
593 * @throws IllegalArgumentException <ul>
594 * <li>if <code>leafrefType</code> equal null</li>
595 * <li>if path statement of <code>leafrefType</code> equal null</li>
598 public Type provideTypeForLeafref(final LeafrefTypeDefinition leafrefType, final SchemaNode parentNode,
599 final ModuleContext context) {
600 Type returnType = null;
601 Preconditions.checkArgument(leafrefType != null, "Leafref Type Definition reference cannot be NULL!");
603 Preconditions.checkArgument(leafrefType.getPathStatement() != null,
604 "The Path Statement for Leafref Type Definition cannot be NULL!");
606 final RevisionAwareXPath xpath = leafrefType.getPathStatement();
607 final String strXPath = xpath.toString();
608 if (strXPath != null) {
609 if (strXPath.indexOf('[') == -1) {
611 final SchemaNode actualParentSchemaNode;
612 if (parentNode instanceof DerivableSchemaNode && ((DerivableSchemaNode) parentNode).isAddedByUses()) {
613 final Optional<? extends SchemaNode> originalNode = ((DerivableSchemaNode) parentNode)
615 Preconditions.checkArgument(originalNode.isPresent(), "originalNode can not be null.");
616 actualParentSchemaNode = originalNode.get();
617 module = findParentModule(schemaContext, originalNode.get());
619 actualParentSchemaNode = parentNode;
620 module = findParentModule(schemaContext, parentNode);
622 Preconditions.checkArgument(module != null, "Failed to find module for parent %s", parentNode);
624 final SchemaNode dataNode;
625 if (xpath.isAbsolute()) {
626 dataNode = findDataSchemaNode(schemaContext, module, xpath);
628 dataNode = findDataSchemaNodeForRelativeXPath(schemaContext, module, actualParentSchemaNode, xpath);
630 Preconditions.checkArgument(dataNode != null, "Failed to find leafref target: %s in module %s (%s)",
631 strXPath, getParentModule(parentNode, schemaContext).getName(), parentNode.getQName()
634 if (leafContainsEnumDefinition(dataNode)) {
635 returnType = this.referencedTypes.get(dataNode.getPath());
636 } else if (leafListContainsEnumDefinition(dataNode)) {
637 returnType = Types.listTypeFor(this.referencedTypes.get(dataNode.getPath()));
639 returnType = resolveTypeFromDataSchemaNode(dataNode, context);
642 returnType = Types.typeForClass(Object.class);
645 Preconditions.checkArgument(returnType != null, "Failed to find leafref target: %s in module %s (%s)",
646 strXPath, getParentModule(parentNode, schemaContext).getName(), parentNode.getQName().getModule());
651 * Checks if <code>dataNode</code> is <code>LeafSchemaNode</code> and if it
652 * so then checks if it is of type <code>EnumTypeDefinition</code>.
654 * @param dataNode data schema node for which is checked if it is leaf and if it
656 * @return boolean value
658 * <li>true - if <code>dataNode</code> is leaf of type enumeration</li>
659 * <li>false - other cases</li>
662 private static boolean leafContainsEnumDefinition(final SchemaNode dataNode) {
663 if (dataNode instanceof LeafSchemaNode) {
664 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
665 //CompatUtils is not used here anymore
666 if (leaf.getType() instanceof EnumTypeDefinition) {
674 * Checks if <code>dataNode</code> is <code>LeafListSchemaNode</code> and if
675 * it so then checks if it is of type <code>EnumTypeDefinition</code>.
677 * @param dataNode data schema node for which is checked if it is leaflist and if
679 * @return boolean value
681 * <li>true - if <code>dataNode</code> is leaflist of type
683 * <li>false - other cases</li>
686 private static boolean leafListContainsEnumDefinition(final SchemaNode dataNode) {
687 if (dataNode instanceof LeafListSchemaNode) {
688 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
689 if (leafList.getType() instanceof EnumTypeDefinition) {
697 * Converts <code>dataNode</code> to JAVA <code>Type</code>.
699 * @param dataNode contains information about YANG type
700 * @return JAVA <code>Type</code> representation of <code>dataNode</code>
702 private Type resolveTypeFromDataSchemaNode(final SchemaNode dataNode, final ModuleContext context) {
703 Type returnType = null;
704 if (dataNode != null) {
705 if (dataNode instanceof LeafSchemaNode) {
706 final LeafSchemaNode leaf = (LeafSchemaNode) dataNode;
707 //not using CompatUtils here anymore
708 final TypeDefinition<?> type = leaf.getType();
709 returnType = javaTypeForSchemaDefType(type, leaf, null, context);
710 } else if (dataNode instanceof LeafListSchemaNode) {
711 final LeafListSchemaNode leafList = (LeafListSchemaNode) dataNode;
712 returnType = javaTypeForSchemaDefType(leafList.getType(), leafList, null, context);
719 * Seeks for identity reference <code>idref</code> the JAVA
720 * <code>type</code>.<br />
725 * If identy which is referenced via <code>idref</code> has name <b>Idn</b>
726 * then returning type is <b>{@code Class<? extends Idn>}</b></i>
728 * @param idref identityref type definition for which JAVA <code>Type</code>
730 * @return JAVA <code>Type</code> of the identity which is refrenced through
733 private static Type provideTypeForIdentityref(final IdentityrefTypeDefinition idref,
734 final SchemaContext schemaContext) {
735 //TODO: incompatibility with Binding spec v2, get first or only one
736 final QName baseIdQName = idref.getIdentities().iterator().next().getQName();
737 final Module module = schemaContext.findModule(baseIdQName.getModule()).orElse(null);
738 IdentitySchemaNode identity = null;
739 for (final IdentitySchemaNode id : module.getIdentities()) {
740 if (id.getQName().equals(baseIdQName)) {
744 Preconditions.checkArgument(identity != null, "Target identity '" + baseIdQName + "' do not exists");
746 final String basePackageName = BindingMapping.getRootPackageName(module);
747 final String packageName = BindingGeneratorUtil.packageNameForGeneratedType(basePackageName, identity.getPath(),
748 BindingNamespaceType.Identity);
750 final String genTypeName = JavaIdentifierNormalizer.normalizeSpecificIdentifier(identity.getQName()
752 JavaIdentifier.CLASS);
754 final Type baseType = Types.typeForClass(Class.class);
755 final Type paramType = Types.wildcardTypeFor(packageName, genTypeName, true, true, null);
756 return Types.parameterizedTypeFor(baseType, paramType);
759 private static GeneratedTransferObject shadedTOWithRestrictions(final GeneratedTransferObject gto,
760 final Restrictions restrictions, final ModuleContext context) {
761 final GeneratedTOBuilder gtob = new GeneratedTOBuilderImpl(gto.getPackageName(), gto.getName(), context);
762 final GeneratedTransferObject parent = gto.getSuperType();
763 if (parent != null) {
764 gtob.setExtendsType(parent);
766 gtob.setRestrictions(restrictions);
767 for (final GeneratedProperty gp : gto.getProperties()) {
768 final GeneratedPropertyBuilder gpb = gtob.addProperty(gp.getName());
769 gpb.setValue(gp.getValue());
770 gpb.setReadOnly(gp.isReadOnly());
771 gpb.setAccessModifier(gp.getAccessModifier());
772 gpb.setReturnType(gp.getReturnType());
773 gpb.setFinal(gp.isFinal());
774 gpb.setStatic(gp.isStatic());
776 return gtob.toInstance();
780 * Adds a new property with the name <code>propertyName</code> and with type
781 * <code>type</code> to <code>unonGenTransObject</code>.
783 * @param unionGenTransObject generated TO to which should be property added
784 * @param type JAVA <code>type</code> of the property which should be added
785 * to <code>unionGentransObject</code>
786 * @param propertyName string with name of property which should be added to
787 * <code>unionGentransObject</code>
789 private static void updateUnionTypeAsProperty(final GeneratedTOBuilder unionGenTransObject, final Type type,
790 final String propertyName) {
791 if (unionGenTransObject != null && type != null && !unionGenTransObject.containsProperty(propertyName)) {
792 final GeneratedPropertyBuilder propBuilder = unionGenTransObject
793 .addProperty(JavaIdentifierNormalizer.normalizeSpecificIdentifier(propertyName, JavaIdentifier
795 propBuilder.setReturnType(type);
797 unionGenTransObject.addEqualsIdentity(propBuilder);
798 unionGenTransObject.addHashIdentity(propBuilder);
799 unionGenTransObject.addToStringProperty(propBuilder);
804 * Wraps code which handle case when union subtype is also of the type
805 * <code>UnionType</code>.
808 * In this case the new generated TO is created for union subtype (recursive
809 * call of method {@link #provideGeneratedTOBuilderForUnionTypeDef(String, UnionTypeDefinition, String, SchemaNode,
810 * SchemaContext, Map, ModuleContext)}
811 * provideGeneratedTOBuilderForUnionTypeDef} and in parent TO builder
812 * <code>parentUnionGenTOBuilder</code> is created property which type is
813 * equal to new generated TO.
815 * @param parentUnionGenTOBuilder generated TO builder to which is the property with the child
816 * union subtype added
817 * @param basePackageName string with the name of the module package
818 * @param unionSubtype type definition which represents union subtype
819 * @return list of generated TO builders. The number of the builders can be bigger one due to recursive call of
820 * <code>provideGeneratedTOBuildersForUnionTypeDef</code> method.
822 private GeneratedTOBuilder resolveUnionSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
823 final UnionTypeDefinition unionSubtype, final String basePackageName, final SchemaNode parentNode,
824 final ModuleContext context) {
825 final String newTOBuilderName = provideAvailableNameForGenTOBuilder(parentUnionGenTOBuilder.getName());
826 final GeneratedTOBuilder subUnionGenTOBUilder = provideGeneratedTOBuilderForUnionTypeDef(
827 basePackageName, unionSubtype, newTOBuilderName, parentNode, context);
829 final GeneratedPropertyBuilder propertyBuilder;
830 propertyBuilder = parentUnionGenTOBuilder.addProperty(
831 JavaIdentifierNormalizer.normalizeSpecificIdentifier(newTOBuilderName, JavaIdentifier.METHOD));
832 propertyBuilder.setReturnType(subUnionGenTOBUilder);
833 parentUnionGenTOBuilder.addEqualsIdentity(propertyBuilder);
834 parentUnionGenTOBuilder.addToStringProperty(propertyBuilder);
836 return subUnionGenTOBUilder;
840 * Converts output list of generated TO builders to one TO builder (first
841 * from list) which contains the remaining builders as its enclosing TO.
843 * @param basePackageName string with name of package to which the module belongs
844 * @param typedef type definition which should be of type
845 * <code>UnionTypeDefinition</code>
846 * @param typeDefName string with name for generated TO
847 * @return generated TO builder with the list of enclosed generated TO builders
849 public GeneratedTOBuilder provideGeneratedTOBuilderForUnionTypeDef(final String basePackageName,
850 final UnionTypeDefinition typedef, final String typeDefName, final SchemaNode parentNode,
851 final ModuleContext context) {
853 final List<GeneratedTOBuilder> builders = provideGeneratedTOBuildersForUnionTypeDef(basePackageName,
854 typedef, typeDefName, parentNode, context);
855 Preconditions.checkState(!builders.isEmpty(), "No GeneratedTOBuilder objects generated from union %s", typedef);
857 final GeneratedTOBuilder resultTOBuilder = builders.remove(0);
858 for (final GeneratedTOBuilder genTOBuilder : builders) {
859 resultTOBuilder.addEnclosingTransferObject(genTOBuilder);
862 final GeneratedPropertyBuilder genPropBuilder;
864 genPropBuilder = resultTOBuilder.addProperty("value").setReturnType(Types.CHAR_ARRAY).setReadOnly(false);
865 resultTOBuilder.addEqualsIdentity(genPropBuilder);
866 resultTOBuilder.addHashIdentity(genPropBuilder);
867 resultTOBuilder.addToStringProperty(genPropBuilder);
869 provideGeneratedTOBuilderForUnionBuilder(findParentModule(schemaContext, parentNode), resultTOBuilder);
871 return resultTOBuilder;
875 private GeneratedTOBuilder provideGeneratedTOBuilderForUnionBuilder(final Module parentModule,
876 final GeneratedTOBuilder genTOBuilder) {
877 final String outerCls = Types.getOuterClassName(genTOBuilder);
878 final StringBuilder name;
879 if (outerCls != null) {
880 name = new StringBuilder(outerCls);
882 name = new StringBuilder();
884 name.append(genTOBuilder.getName());
885 name.append("Builder");
886 final GeneratedTOBuilderImpl unionBuilder = new GeneratedTOBuilderImpl(getOuterClassPackageName(genTOBuilder),
887 name.toString(), true);
888 unionBuilder.setIsUnionBuilder(true);
890 final MethodSignatureBuilder method = unionBuilder.addMethod("getDefaultInstance");
891 method.setReturnType(genTOBuilder);
892 method.addParameter(Types.STRING, "defaultValue");
893 method.setAccessModifier(AccessModifier.PUBLIC);
894 method.setStatic(true);
896 final Set<Type> types = this.getAdditionalTypes().get(parentModule);
898 this.getAdditionalTypes().put(parentModule,
899 Sets.newHashSet(unionBuilder.toInstance()));
901 types.add(unionBuilder.toInstance());
908 * Wraps code which handle case when union subtype is of the type
909 * <code>ExtendedType</code>.
912 * If TO for this type already exists it is used for the creation of the
913 * property in <code>parentUnionGenTOBuilder</code>. In other case the base
914 * type is used for the property creation.
916 * @param parentUnionGenTOBuilder generated TO builder in which new property is created
917 * @param unionSubtype type definition of the <code>ExtendedType</code> type which
918 * represents union subtype
919 * @param expressions map of strings with the regular expressions
920 * @param parentNode parent Schema Node for Extended Subtype
922 private void resolveExtendedSubtypeAsUnion(final GeneratedTOBuilder parentUnionGenTOBuilder,
923 final TypeDefinition<?> unionSubtype, final Map<String, String> expressions, final SchemaNode parentNode) {
924 final String unionTypeName = unionSubtype.getQName().getLocalName();
925 final Type genTO = findGenTO(unionTypeName, unionSubtype, schemaContext, genTypeDefsContextMap);
927 updateUnionTypeAsProperty(parentUnionGenTOBuilder, genTO, unionTypeName);
931 final TypeDefinition<?> baseType = baseTypeDefForExtendedType(unionSubtype);
932 if (unionTypeName.equals(baseType.getQName().getLocalName())) {
933 final Type javaType = BaseYangTypes.BASE_YANG_TYPES_PROVIDER.javaTypeForSchemaDefinitionType(baseType,
935 if (javaType != null) {
936 updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType, unionTypeName);
938 } else if (baseType instanceof LeafrefTypeDefinition) {
939 final Type javaType = javaTypeForSchemaDefinitionType(baseType,
941 boolean typeExist = false;
942 for (final GeneratedPropertyBuilder generatedPropertyBuilder : parentUnionGenTOBuilder
944 final Type origType = ((GeneratedPropertyBuilderImpl) generatedPropertyBuilder).getReturnType();
945 if (origType != null && javaType != null && javaType == origType) {
950 if (!typeExist && javaType != null) {
951 updateUnionTypeAsProperty(parentUnionGenTOBuilder, javaType,
952 javaType.getName() + parentUnionGenTOBuilder.getName() + "Value");
955 if (baseType instanceof StringTypeDefinition) {
956 expressions.putAll(resolveRegExpressionsFromTypedef(unionSubtype));
961 * Returns string which contains the same value as <code>name</code> but
962 * integer suffix is incremented by one. If <code>name</code> contains no
963 * number suffix then number 1 is added.
965 * @param name string with name of augmented node
966 * @return string with the number suffix incremented by one (or 1 is added)
968 private static String provideAvailableNameForGenTOBuilder(final String name) {
969 final Matcher mtch = NUMBERS_PATTERN.matcher(name);
971 final int newSuffix = Integer.valueOf(name.substring(mtch.start())) + 1;
972 return name.substring(0, mtch.start()) + newSuffix;
979 * Searches for generated TO for <code>searchedTypeDef</code> type
980 * definition in {@link #genTypeDefsContextMap genTypeDefsContextMap}.
982 * @param searchedTypeName string with name of <code>searchedTypeDef</code>
983 * @return generated TO for <code>searchedTypeDef</code> or
984 * <code>null</code> it it doesn't exist
986 private static Type findGenTO(final String searchedTypeName, final SchemaNode parentNode,
987 final SchemaContext schemaContext, final Map<String, Map<Optional<Revision>,
988 Map<String, Type>>> genTypeDefsContextMap) {
990 final Module typeModule = findParentModule(schemaContext, parentNode);
991 if (typeModule != null && typeModule.getName() != null) {
992 final Map<Optional<Revision>, Map<String, Type>> modulesByDate = genTypeDefsContextMap.get(typeModule
994 final Map<String, Type> genTOs = modulesByDate.get(typeModule.getRevision());
995 if (genTOs != null) {
996 return genTOs.get(searchedTypeName);
1003 * Adds enumeration to <code>typeBuilder</code>. The enumeration data are
1004 * taken from <code>enumTypeDef</code>.
1006 * @param enumTypeDef enumeration type definition is source of enumeration data for
1007 * <code>typeBuilder</code>
1008 * @param enumName string with the name of enumeration
1009 * @param typeBuilder generated type builder to which is enumeration added
1010 * @return enumeration type which contains enumeration data form
1011 * <code>enumTypeDef</code>
1012 * @throws IllegalArgumentException <ul>
1013 * <li>if <code>enumTypeDef</code> equals null</li>
1014 * <li>if enum values of <code>enumTypeDef</code> equal null</li>
1015 * <li>if Q name of <code>enumTypeDef</code> equal null</li>
1016 * <li>if name of <code>enumTypeDef</code> equal null</li>
1017 * <li>if name of <code>typeBuilder</code> equal null</li>
1020 private static Enumeration addInnerEnumerationToTypeBuilder(final EnumTypeDefinition enumTypeDef,
1021 final String enumName, final
1022 GeneratedTypeBuilderBase<?> typeBuilder, final
1023 ModuleContext context) {
1024 Preconditions.checkArgument(enumTypeDef != null, "EnumTypeDefinition reference cannot be NULL!");
1025 Preconditions.checkArgument(enumTypeDef.getQName().getLocalName() != null,
1026 "Local Name in EnumTypeDefinition QName cannot be NULL!");
1027 Preconditions.checkArgument(typeBuilder != null, "Generated Type Builder reference cannot be NULL!");
1029 final EnumBuilder enumBuilder = typeBuilder.addEnumeration(enumName, context);
1030 final String enumTypedefDescription = encodeAngleBrackets(enumTypeDef.getDescription().orElse(null));
1031 enumBuilder.setDescription(enumTypedefDescription);
1032 enumBuilder.updateEnumPairsFromEnumTypeDef(enumTypeDef);
1033 return enumBuilder.toInstance(enumBuilder);
1036 private static boolean isLeafRefSelfReference(final LeafrefTypeDefinition leafref, final SchemaNode parentNode,
1037 final SchemaContext schemaContext) {
1038 final SchemaNode leafRefValueNode;
1039 final RevisionAwareXPath leafRefXPath = leafref.getPathStatement();
1040 final RevisionAwareXPath leafRefStrippedXPath = new RevisionAwareXPathImpl(leafRefXPath.toString()
1041 .replaceAll("\\[(.*?)\\]", ""), leafRefXPath.isAbsolute());
1043 ///// skip leafrefs in augments - they're checked once augments are resolved
1044 final Iterator<QName> iterator = parentNode.getPath().getPathFromRoot().iterator();
1045 boolean isAugmenting = false;
1046 DataNodeContainer current = null;
1047 DataSchemaNode dataChildByName;
1049 while (iterator.hasNext() && !isAugmenting) {
1050 final QName next = iterator.next();
1051 if (current == null) {
1052 dataChildByName = schemaContext.getDataChildByName(next);
1054 dataChildByName = current.getDataChildByName(next);
1056 if (dataChildByName != null) {
1057 isAugmenting = dataChildByName.isAugmenting();
1061 if (dataChildByName instanceof DataNodeContainer) {
1062 current = (DataNodeContainer) dataChildByName;
1070 final Module parentModule = getParentModule(parentNode, schemaContext);
1071 if (!leafRefStrippedXPath.isAbsolute()) {
1072 leafRefValueNode = SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule,
1073 parentNode, leafRefStrippedXPath);
1075 leafRefValueNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, leafRefStrippedXPath);
1077 return leafRefValueNode != null && leafRefValueNode.equals(parentNode);