package org.opendaylight.yangtools.yang.model.util;
import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
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;
-import java.util.Arrays;
+import java.util.Collections;
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;
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.");
RevisionAwareXPath pathStatement = typeDefinition.getPathStatement();
pathStatement = new RevisionAwareXPathImpl(stripConditionsFromXPathString(pathStatement), pathStatement.isAbsolute());
- SchemaNode baseSchema = schema;
- while (baseSchema instanceof DerivableSchemaNode) {
- final Optional<? extends SchemaNode> basePotential = ((DerivableSchemaNode) baseSchema).getOriginal();
- if (basePotential.isPresent()) {
- baseSchema = basePotential.get();
- } else {
- break;
+ final DataSchemaNode dataSchemaNode;
+ if (pathStatement.isAbsolute()) {
+ SchemaNode baseSchema = schema;
+ while (baseSchema instanceof DerivableSchemaNode) {
+ final Optional<? extends SchemaNode> basePotential = ((DerivableSchemaNode) baseSchema).getOriginal();
+ if (basePotential.isPresent()) {
+ baseSchema = basePotential.get();
+ } else {
+ break;
+ }
}
- }
- Module parentModule = findParentModuleByType(schemaContext, baseSchema);
-
- final DataSchemaNode dataSchemaNode;
- if(pathStatement.isAbsolute()) {
- dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, pathStatement);
+ Module parentModule = findParentModuleOfReferencingType(schemaContext, baseSchema);
+ dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule,
+ pathStatement);
} else {
- dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule, baseSchema, pathStatement);
+ Module parentModule = findParentModule(schemaContext, schema);
+ dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext,
+ parentModule, schema, pathStatement);
}
// FIXME this is just to preserve backwards compatibility since yangtools do not mind wrong leafref xpaths
}
}
+ 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 instanceof ExtendedType) {
+ while (nodeType.getBaseType() instanceof ExtendedType) {
+ nodeType = nodeType.getBaseType();
+ }
+
+ QNameModule typeDefModuleQname = nodeType.getQName().getModule();
+ return schemaContext.findModuleByNamespaceAndRevision(typeDefModuleQname.getNamespace(),
+ typeDefModuleQname.getRevision());
+ } else 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). <br>
* Schema Node is NOT present, the method will returns
* <code>null</code>
*/
+ @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!");
nodeType = ((LeafListSchemaNode) schemaNode).getType();
}
- if (nodeType instanceof ExtendedType) {
- while (nodeType.getBaseType() instanceof ExtendedType) {
+ if (!BaseTypes.isYangBuildInType(nodeType) && nodeType.getBaseType() != null) {
+ while (nodeType.getBaseType() != null && !BaseTypes.isYangBuildInType(nodeType.getBaseType())) {
nodeType = nodeType.getBaseType();
}
}
}
+ private static final Pattern STRIP_PATTERN = Pattern.compile("\\[[^\\[\\]]*\\]");
+
/**
* Removes conditions from xPath pointed to target node.
*
* @return string representation of xPath without conditions
*
*/
- private static String stripConditionsFromXPathString(final RevisionAwareXPath pathStatement) {
- return pathStatement.toString().replaceAll("\\[.*\\]", "");
+ @VisibleForTesting
+ static String stripConditionsFromXPathString(final RevisionAwareXPath pathStatement) {
+ return STRIP_PATTERN.matcher(pathStatement.toString()).replaceAll("");
}
/**
* a node representing LeafSchemaNode
* @return concrete type definition of node value
*/
- private static TypeDefinition<? extends Object> typeDefinition(final LeafSchemaNode node) {
+ private static TypeDefinition<?> typeDefinition(final LeafSchemaNode node) {
TypeDefinition<?> baseType = node.getType();
while (baseType.getBaseType() != null) {
baseType = baseType.getBaseType();
* a node representing LeafListSchemaNode
* @return concrete type definition of node value
*/
- private static TypeDefinition<? extends Object> typeDefinition(final LeafListSchemaNode node) {
+ private static TypeDefinition<?> typeDefinition(final LeafListSchemaNode node) {
TypeDefinition<?> baseType = node.getType();
while (baseType.getBaseType() != null) {
baseType = baseType.getBaseType();
* a node representing DataSchemaNode
* @return concrete type definition of node value
*/
- private static TypeDefinition<? extends Object> typeDefinition(final DataSchemaNode node) {
+ private static TypeDefinition<?> typeDefinition(final DataSchemaNode node) {
if (node instanceof LeafListSchemaNode) {
return typeDefinition((LeafListSchemaNode) node);
} else if (node instanceof LeafSchemaNode) {
return typeDefinition((LeafSchemaNode) node);
} else {
- throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object> asList(node).toString());
+ throw new IllegalArgumentException("Unhandled parameter types: " + Collections.<Object>singletonList(node).toString());
}
}
}