+ /**
+ * Returns base type for {@code typeDefinition} which belongs to module specified via {@code qname}. This handle
+ * the case when leafref type isn't specified as type substatement of leaf or leaf-list but is defined in other
+ * module as typedef which is then imported to referenced module.
+ *
+ * <p>
+ * Because {@code typeDefinition} is definied via typedef statement, only absolute path is meaningful.
+ */
+ public static TypeDefinition<?> getBaseTypeForLeafRef(final LeafrefTypeDefinition typeDefinition,
+ final SchemaContext schemaContext, final QName qname) {
+ final RevisionAwareXPath pathStatement = typeDefinition.getPathStatement();
+ final RevisionAwareXPath strippedPathStatement = new RevisionAwareXPathImpl(
+ stripConditionsFromXPathString(pathStatement), pathStatement.isAbsolute());
+ if (!strippedPathStatement.isAbsolute()) {
+ return null;
+ }
+
+ final Optional<Module> parentModule = schemaContext.findModule(qname.getModule());
+ Preconditions.checkArgument(parentModule.isPresent(), "Failed to find parent module for %s", qname);
+
+ final DataSchemaNode dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNode(schemaContext,
+ parentModule.get(), strippedPathStatement);
+ final TypeDefinition<?> targetTypeDefinition = typeDefinition(dataSchemaNode);
+ if (targetTypeDefinition instanceof LeafrefTypeDefinition) {
+ return getBaseTypeForLeafRef((LeafrefTypeDefinition) targetTypeDefinition, schemaContext, dataSchemaNode);
+ }
+
+ return targetTypeDefinition;
+ }
+
+ private static Module findParentModuleOfReferencingType(final SchemaContext schemaContext,
+ final SchemaNode schemaNode) {
+ Preconditions.checkArgument(schemaContext != null, "Schema Context reference cannot be NULL!");
+ Preconditions.checkArgument(schemaNode instanceof TypedDataSchemaNode, "Unsupported node %s", schemaNode);
+
+ TypeDefinition<?> nodeType = ((TypedDataSchemaNode) schemaNode).getType();
+ if (nodeType.getBaseType() != null) {
+ while (nodeType.getBaseType() != null) {
+ nodeType = nodeType.getBaseType();
+ }
+
+ return schemaContext.findModule(nodeType.getQName().getModule()).orElse(null);
+ }
+
+ return SchemaContextUtil.findParentModule(schemaContext, schemaNode);
+ }
+
+ private static final Pattern STRIP_PATTERN = Pattern.compile("\\[[^\\[\\]]*\\]");
+