Preconditions.checkArgument(module != null, "Failed to resolve xpath: no module found for prefix %s in module %s",
modulePrefix, parentModule.getName());
- // FIXME: Module should have a QNameModule handle
- return QName.create(module.getNamespace(), module.getRevision(), prefixedName.next());
+ return QName.create(module.getQNameModule(), prefixedName.next());
} else {
return QName.create(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
}
* Yang Module
* @param relativeXPath
* Non conditional Revision Aware Relative XPath
- * @param leafrefSchemaPath
- * Schema Path for Leafref
+ * @param actualSchemaNode
+ * actual schema node
* @return list of QName
*/
private static Iterable<QName> resolveRelativeXPath(final SchemaContext context, final Module module,
- final RevisionAwareXPath relativeXPath, final SchemaNode leafrefParentNode) {
+ final RevisionAwareXPath relativeXPath, final SchemaNode actualSchemaNode) {
Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
Preconditions.checkArgument(relativeXPath != null, "Non Conditional Revision Aware XPath cannot be NULL");
Preconditions.checkState(!relativeXPath.isAbsolute(),
"Revision Aware XPath MUST be relative i.e. MUST contains ../, "
+ "for non relative Revision Aware XPath use findDataSchemaNode method");
- Preconditions.checkState(leafrefParentNode.getPath() != null,
+ Preconditions.checkState(actualSchemaNode.getPath() != null,
"Schema Path reference for Leafref cannot be NULL");
final Iterable<String> xpaths = SLASH_SPLITTER.split(relativeXPath.toString());
// Find out how many "parent" components there are
// FIXME: is .contains() the right check here?
+ // FIXME: case ../../node1/node2/../node3/../node4
int colCount = 0;
for (Iterator<String> it = xpaths.iterator(); it.hasNext() && it.next().contains(".."); ) {
++colCount;
}
- final Iterable<QName> parent = leafrefParentNode.getPath().getPathFromRoot();
- return Iterables.concat(Iterables.limit(parent, Iterables.size(parent) - colCount),
+ final Iterable<QName> schemaNodePath = actualSchemaNode.getPath().getPathFromRoot();
+
+ if (Iterables.size(schemaNodePath) - colCount >= 0) {
+ return Iterables.concat(Iterables.limit(schemaNodePath, Iterables.size(schemaNodePath) - colCount),
+ Iterables.transform(Iterables.skip(xpaths, colCount), new Function<String, QName>() {
+ @Override
+ public QName apply(final String input) {
+ return stringPathPartToQName(context, module, input);
+ }
+ }));
+ }
+ return Iterables.concat(schemaNodePath,
Iterables.transform(Iterables.skip(xpaths, colCount), new Function<String, QName>() {
@Override
public QName apply(final String input) {
* Schema Context
* @param schema
* Schema Node
- * @return
+ * @return recursively found type definition this leafref is pointing to or null if the xpath is incorrect (null is there to preserve backwards compatibility)
*/
public static TypeDefinition<?> getBaseTypeForLeafRef(final LeafrefTypeDefinition typeDefinition, final SchemaContext schemaContext, final SchemaNode schema) {
RevisionAwareXPath pathStatement = typeDefinition.getPathStatement();
if(pathStatement.isAbsolute()) {
dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, pathStatement);
} else {
- SchemaPath parentSchemaPath = schema.getPath().getParent();
- SchemaNode parentSchemaNode = SchemaContextUtil.findDataSchemaNode(schemaContext, parentSchemaPath);
- dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule, parentSchemaNode, pathStatement);
+ dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule, schema, pathStatement);
+ }
+
+ // FIXME this is just to preserve backwards compatibility since yangtools do not mind wrong leafref xpaths
+ // and current expected behaviour for such cases is to just use pure string
+ // This should throw an exception about incorrect XPath in leafref
+ if(dataSchemaNode == null) {
+ return null;
}
final TypeDefinition<?> targetTypeDefinition = typeDefinition(dataSchemaNode);