X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-model-util%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fmodel%2Futil%2FSchemaContextUtil.java;h=7ad5070f195a118faf8590d75e3671208029c578;hb=e704e6a6d1cc4db7ac1e1f53b54ec3bf51aaecc3;hp=c0ac168135eaa73a52ea9b1dbd02284e663c170c;hpb=7ae69e3edccd348635fdba5b2c8560e353da8b7c;p=yangtools.git diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java index c0ac168135..7ad5070f19 100644 --- a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java +++ b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java @@ -9,6 +9,7 @@ package org.opendaylight.yangtools.yang.model.util; import com.google.common.annotations.Beta; import com.google.common.base.Function; +import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; @@ -17,13 +18,16 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.regex.Pattern; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.model.api.ChoiceNode; +import org.opendaylight.yangtools.yang.common.QNameModule; +import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode; import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode; @@ -218,10 +222,10 @@ public final class SchemaContextUtil { Preconditions.checkState(schemaNode.getPath() != null, "Schema Path for Schema Node is not " + "set properly (Schema Path is NULL)"); - final QName qname = Iterables.getFirst(schemaNode.getPath().getPathTowardsRoot(), null); + final QName qname = schemaNode.getPath().getLastComponent(); Preconditions.checkState(qname != null, "Schema Path contains invalid state of path parts. " + - "The Schema Path MUST contain at least ONE QName which defines namespace and Local name of path."); + "The Schema Path MUST contain at least ONE QName which defines namespace and Local name of path."); return context.findModuleByNamespaceAndRevision(qname.getNamespace(), qname.getRevision()); } @@ -246,7 +250,7 @@ public final class SchemaContextUtil { * @return Notification schema or null, if notification is not present in schema context. */ @Beta - public static @Nullable NotificationDefinition getNotificationSchema(@Nonnull final SchemaContext schema,@Nonnull final SchemaPath path) { + @Nullable public static NotificationDefinition getNotificationSchema(@Nonnull final SchemaContext schema, @Nonnull final SchemaPath path) { Preconditions.checkNotNull(schema, "Schema context must not be null."); Preconditions.checkNotNull(path, "Schema path must not be null."); for (final NotificationDefinition potential : schema.getNotifications()) { @@ -265,7 +269,7 @@ public final class SchemaContextUtil { * @return Notification schema or null, if notification is not present in schema context. */ @Beta - public static @Nullable ContainerSchemaNode getRpcDataSchema(@Nonnull final SchemaContext schema,@Nonnull final SchemaPath path) { + @Nullable public static ContainerSchemaNode getRpcDataSchema(@Nonnull final SchemaContext schema, @Nonnull final SchemaPath path) { Preconditions.checkNotNull(schema, "Schema context must not be null."); Preconditions.checkNotNull(path, "Schema path must not be null."); final Iterator it = path.getPathFromRoot().iterator(); @@ -388,8 +392,8 @@ public final class SchemaContextUtil { } } - if (foundNode == null && parent instanceof ChoiceNode) { - foundNode = ((ChoiceNode) parent).getCaseNodeByName(current); + if (foundNode == null && parent instanceof ChoiceSchemaNode) { + foundNode = ((ChoiceSchemaNode) parent).getCaseNodeByName(current); if (foundNode != null && nextPath.iterator().hasNext()) { foundNode = findNodeIn(foundNode, nextPath); } @@ -626,13 +630,23 @@ public final class SchemaContextUtil { RevisionAwareXPath pathStatement = typeDefinition.getPathStatement(); pathStatement = new RevisionAwareXPathImpl(stripConditionsFromXPathString(pathStatement), pathStatement.isAbsolute()); - final Module parentModule = SchemaContextUtil.findParentModule(schemaContext, schema); + SchemaNode baseSchema = schema; + while (baseSchema instanceof DerivableSchemaNode) { + final Optional basePotential = ((DerivableSchemaNode) baseSchema).getOriginal(); + if (basePotential.isPresent()) { + baseSchema = basePotential.get(); + } else { + break; + } + } + + Module parentModule = findParentModuleOfReferencingType(schemaContext, baseSchema); final DataSchemaNode dataSchemaNode; if(pathStatement.isAbsolute()) { dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, pathStatement); } else { - dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule, schema, pathStatement); + dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule, baseSchema, pathStatement); } // FIXME this is just to preserve backwards compatibility since yangtools do not mind wrong leafref xpaths @@ -651,6 +665,77 @@ public final class SchemaContextUtil { } } + private static Module findParentModuleOfReferencingType(final SchemaContext schemaContext, + final SchemaNode schemaNode) { + Preconditions.checkArgument(schemaContext != null, "Schema Context reference cannot be NULL!"); + Preconditions.checkArgument(schemaNode != null, "Schema Node cannot be NULL!"); + TypeDefinition nodeType = null; + + if (schemaNode instanceof LeafSchemaNode) { + nodeType = ((LeafSchemaNode) schemaNode).getType(); + } else if (schemaNode instanceof LeafListSchemaNode) { + nodeType = ((LeafListSchemaNode) schemaNode).getType(); + } + + if (nodeType.getBaseType() != null) { + while (nodeType.getBaseType() != null) { + nodeType = nodeType.getBaseType(); + } + + final QNameModule typeDefModuleQname = nodeType.getQName().getModule(); + return schemaContext.findModuleByNamespaceAndRevision(typeDefModuleQname.getNamespace(), + typeDefModuleQname.getRevision()); + } + + return SchemaContextUtil.findParentModule(schemaContext, schemaNode); + } + + /** + * @deprecated due to expensive lookup + * Returns parent Yang Module for specified Schema Context in which Schema + * Node is declared. If Schema Node is of type 'ExtendedType' it tries to find parent module + * in which the type was originally declared (needed for correct leafref path resolution).
+ * If the Schema Node is not present in Schema Context the + * operation will return null.
+ * If Schema Context or Schema Node contains null references + * the method will throw IllegalArgumentException + * + * @throws IllegalArgumentException + * + * @param schemaContext + * Schema Context + * @param schemaNode + * Schema Node + * @return Yang Module for specified Schema Context and Schema Node, if + * Schema Node is NOT present, the method will returns + * null + */ + @Deprecated + public static Module findParentModuleByType(final SchemaContext schemaContext, final SchemaNode schemaNode) { + Preconditions.checkArgument(schemaContext != null, "Schema Context reference cannot be NULL!"); + Preconditions.checkArgument(schemaNode != null, "Schema Node cannot be NULL!"); + TypeDefinition nodeType = null; + + if (schemaNode instanceof LeafSchemaNode) { + nodeType = ((LeafSchemaNode) schemaNode).getType(); + } else if (schemaNode instanceof LeafListSchemaNode) { + nodeType = ((LeafListSchemaNode) schemaNode).getType(); + } + + if (!BaseTypes.isYangBuildInType(nodeType) && nodeType.getBaseType() != null) { + while (nodeType.getBaseType() != null && !BaseTypes.isYangBuildInType(nodeType.getBaseType())) { + nodeType = nodeType.getBaseType(); + } + + QNameModule typeDefModuleQname = nodeType.getQName().getModule(); + + return schemaContext.findModuleByNamespaceAndRevision(typeDefModuleQname.getNamespace(), + typeDefModuleQname.getRevision()); + } + + return SchemaContextUtil.findParentModule(schemaContext, schemaNode); + } + /** * Returns base type for {@code typeDefinition} which belongs to module specified via {@code qName}. This handle case * when leafref type isn't specified as type substatement of leaf or leaf-list but is defined in other module as typedef @@ -681,6 +766,8 @@ public final class SchemaContextUtil { } } + private static final Pattern STRIP_PATTERN = Pattern.compile("\\[.*\\]"); + /** * Removes conditions from xPath pointed to target node. * @@ -690,7 +777,7 @@ public final class SchemaContextUtil { * */ private static String stripConditionsFromXPathString(final RevisionAwareXPath pathStatement) { - return pathStatement.toString().replaceAll("\\[.*\\]", ""); + return STRIP_PATTERN.matcher(pathStatement.toString()).replaceAll(""); } /**