X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fsal%2Fyang-prototype%2Fyang%2Fyang-model-util%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fyang%2Fmodel%2Futil%2FSchemaContextUtil.java;h=1d702c26d842d27af07b52ab1d7fb49112df8195;hb=refs%2Fchanges%2F03%2F703%2F1;hp=8554f682198f73c95f78eb3f5cdf413131e4e2f9;hpb=7923d2e9a833908f0d98d37fdad30c1b8c72c98a;p=controller.git diff --git a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java index 8554f68219..1d702c26d8 100644 --- a/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java +++ b/opendaylight/sal/yang-prototype/yang/yang-model-util/src/main/java/org/opendaylight/controller/yang/model/util/SchemaContextUtil.java @@ -7,251 +7,526 @@ */ package org.opendaylight.controller.yang.model.util; +import java.net.URI; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Set; import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.ContainerSchemaNode; -import org.opendaylight.controller.yang.model.api.DataNodeContainer; -import org.opendaylight.controller.yang.model.api.DataSchemaNode; -import org.opendaylight.controller.yang.model.api.ListSchemaNode; -import org.opendaylight.controller.yang.model.api.Module; -import org.opendaylight.controller.yang.model.api.ModuleImport; -import org.opendaylight.controller.yang.model.api.RevisionAwareXPath; -import org.opendaylight.controller.yang.model.api.SchemaContext; -import org.opendaylight.controller.yang.model.api.SchemaNode; -import org.opendaylight.controller.yang.model.api.SchemaPath; +import org.opendaylight.controller.yang.model.api.*; +/** + * The Schema Context Util contains support methods for searching through Schema Context modules for specified schema + * nodes via Schema Path or Revision Aware XPath. The Schema Context Util is designed as mixin, + * so it is not instantiable. + * + * @author Lukas Sedlak + */ public final class SchemaContextUtil { - private final SchemaContext context; - - public SchemaContextUtil(final SchemaContext context) { - this.context = context; - } - - public SchemaContext getContext() { - return context; + private SchemaContextUtil() { } - - public DataSchemaNode findDataSchemaNode(final SchemaPath schemaPath) { - if (schemaPath != null) { - final Module module = resolveModuleFromSchemaPath(schemaPath); - final Queue prefixedPath = schemaPathToQueuedPath(schemaPath); - - if ((module != null) && (prefixedPath != null)) { - return findSchemaNodeForGivenPath(module, prefixedPath); - } + + /** + * Method attempts to find DataSchemaNode in Schema Context via specified Schema Path. The returned + * DataSchemaNode from method will be the node at the end of the SchemaPath. If the DataSchemaNode is not present + * in the Schema Context the method will return null. + *
+ * In case that Schema Context or Schema Path are not specified correctly (i.e. contains null + * values) the method will return IllegalArgumentException. + * + * @throws IllegalArgumentException + * + * @param context + * Schema Context + * @param schemaPath + * Schema Path to search for + * @return DataSchemaNode from the end of the Schema Path or + * null if the Node is not present. + */ + public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final SchemaPath schemaPath) { + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (schemaPath == null) { + throw new IllegalArgumentException("Schema Path reference cannot be NULL"); + } + + final Module module = resolveModuleFromSchemaPath(context, schemaPath); + final Queue prefixedPath = new LinkedList<>(schemaPath.getPath()); + + if ((module != null) && (prefixedPath != null)) { + return findSchemaNodeForGivenPath(context, module, prefixedPath); } return null; } - - public DataSchemaNode findDataSchemaNode(final Module module, + + /** + * Method attempts to find DataSchemaNode inside of provided Schema Context and Yang Module accordingly to + * Non-conditional Revision Aware XPath. The specified Module MUST be present in Schema Context otherwise the + * operation would fail and return null. + *
+ * The Revision Aware XPath MUST be specified WITHOUT the conditional statement (i.e. without [cond]) in path, + * because in this state the Schema Context is completely unaware of data state and will be not able to properly + * resolve XPath. If the XPath contains condition the method will return IllegalArgumentException. + *
+ * In case that Schema Context or Module or Revision Aware XPath contains null references the method + * will throw IllegalArgumentException + *
+ * If the Revision Aware XPath is correct and desired Data Schema Node is present in Yang module or in depending + * module in Schema Context the method will return specified Data Schema Node, otherwise the operation will fail + * and method will return null. + * + * @throws IllegalArgumentException + * + * @param context Schema Context + * @param module Yang Module + * @param nonCondXPath Non Conditional Revision Aware XPath + * @return Returns Data Schema Node for specified Schema Context for given Non-conditional Revision Aware XPath, + * or null if the DataSchemaNode is not present in Schema Context. + */ + public static DataSchemaNode findDataSchemaNode(final SchemaContext context, final Module module, final RevisionAwareXPath nonCondXPath) { - if (nonCondXPath != null) { - final String strXPath = nonCondXPath.toString(); + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (module == null) { + throw new IllegalArgumentException("Module reference cannot be NULL!"); + } + if (nonCondXPath == null) { + throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!"); + } - if (strXPath != null) { - if (strXPath.matches(".*//[.* | .*//].*")) { - // TODO: function to escape conditions in path - } - if (nonCondXPath.isAbsolute()) { - final Queue queuedPath = xpathToQueuedPath(strXPath); - if (queuedPath != null) { - final DataSchemaNode dataNode = findSchemaNodeForGivenPath( - module, queuedPath); - return dataNode; - } + final String strXPath = nonCondXPath.toString(); + if (strXPath != null) { + if (strXPath.contains("[")) { + throw new IllegalArgumentException("Revision Aware XPath cannot contains condition!"); + } + if (nonCondXPath.isAbsolute()) { + final Queue qnamedPath = xpathToQNamePath(context, module, strXPath); + if (qnamedPath != null) { + final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamedPath); + return dataNode; } } } return null; } - public DataSchemaNode findDataSchemaNodeForRelativeXPath( - final Module module, final SchemaNode actualSchemaNode, - final RevisionAwareXPath relativeXPath) { - if ((actualSchemaNode != null) && (relativeXPath != null) - && !relativeXPath.isAbsolute()) { + /** + * Method attempts to find DataSchemaNode inside of provided Schema Context and Yang Module accordingly to + * Non-conditional relative Revision Aware XPath. The specified Module MUST be present in Schema Context otherwise + * the operation would fail and return null. + *
+ * The relative Revision Aware XPath MUST be specified WITHOUT the conditional statement (i.e. without [cond]) in + * path, because in this state the Schema Context is completely unaware of data state and will be not able to + * properly resolve XPath. If the XPath contains condition the method will return IllegalArgumentException. + *
+ * The Actual Schema Node MUST be specified correctly because from this Schema Node will search starts. If the + * Actual Schema Node is not correct the operation will simply fail, because it will be unable to find desired + * DataSchemaNode. + *
+ * In case that Schema Context or Module or Actual Schema Node or relative Revision Aware XPath contains + * null references the method will throw IllegalArgumentException + *
+ * If the Revision Aware XPath doesn't have flag isAbsolute == false the method will + * throw IllegalArgumentException. + *
+ * If the relative Revision Aware XPath is correct and desired Data Schema Node is present in Yang module or in + * depending module in Schema Context the method will return specified Data Schema Node, + * otherwise the operation will fail + * and method will return null. + * + * @throws IllegalArgumentException + * + * @param context Schema Context + * @param module Yang Module + * @param actualSchemaNode Actual Schema Node + * @param relativeXPath Relative Non Conditional Revision Aware XPath + * @return DataSchemaNode if is present in specified Schema Context for given relative Revision Aware XPath, + * otherwise will return null. + */ + public static DataSchemaNode findDataSchemaNodeForRelativeXPath(final SchemaContext context, final Module module, + final SchemaNode actualSchemaNode, final RevisionAwareXPath relativeXPath) { + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (module == null) { + throw new IllegalArgumentException("Module reference cannot be NULL!"); + } + if (actualSchemaNode == null) { + throw new IllegalArgumentException("Actual Schema Node reference cannot be NULL!"); + } + if (relativeXPath == null) { + throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!"); + } + if (relativeXPath.isAbsolute()) { + throw new IllegalArgumentException("Revision Aware XPath MUST be relative i.e. MUST contains ../, " + + "for non relative Revision Aware XPath use findDataSchemaNode method!"); + } - final SchemaPath actualNodePath = actualSchemaNode.getPath(); - if (actualNodePath != null) { - final Queue queuedPath = resolveRelativeXPath( - relativeXPath, actualNodePath); + final SchemaPath actualNodePath = actualSchemaNode.getPath(); + if (actualNodePath != null) { + final Queue qnamePath = resolveRelativeXPath(context, module, relativeXPath, actualNodePath); - if (queuedPath != null) { - final DataSchemaNode dataNode = findSchemaNodeForGivenPath( - module, queuedPath); - return dataNode; - } + if (qnamePath != null) { + final DataSchemaNode dataNode = findSchemaNodeForGivenPath(context, module, qnamePath); + return dataNode; + } + } + return null; + } + + /** + * Retrieve information from Schema Path and returns the module reference to which Schema Node belongs. The + * search for correct Module is based on namespace within the last item in Schema Path. If schema context + * contains module with namespace specified in last item of Schema Path, then operation will returns Module + * reference, otherwise returns null + *
+ * If Schema Context or Schema Node contains null references the method will throw IllegalArgumentException + * + * @throws IllegalArgumentException + * + * @param context Schema Context + * @param schemaPath Schema Path + * @return Module reference for given Schema Path if module is present in Schema Context, + * otherwise returns null + */ + private static Module resolveModuleFromSchemaPath(final SchemaContext context, final SchemaPath schemaPath) { + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (schemaPath == null) { + throw new IllegalArgumentException("Schema Path reference cannot be NULL"); + } + + final List path = schemaPath.getPath(); + if (!path.isEmpty()) { + final QName qname = path.get(path.size() - 1); + + if ((qname != null) && (qname.getNamespace() != null)) { + return context.findModuleByNamespace(qname.getNamespace()); } } return null; } - - public Module resolveModuleFromSchemaPath(final SchemaPath schemaPath) { - if ((schemaPath != null) && (schemaPath.getPath() != null)) { - final QName qname = schemaPath.getPath().get(0); + /** + * Returns the Yang Module from specified Schema Context in which the TypeDefinition is declared. If the + * TypeDefinition si not present in Schema Context then the method will return null + * + * If Schema Context or TypeDefinition contains null references the method will throw IllegalArgumentException + * + * @throws IllegalArgumentException + * + * @param context Schema Context + * @param type Type Definition + * @return Yang Module in which the TypeDefinition is declared, if is not present, returns null. + */ + public static Module findParentModuleForTypeDefinition(final SchemaContext context, final TypeDefinition type) { + final SchemaPath schemaPath = type.getPath(); + if (schemaPath == null) { + throw new IllegalArgumentException("Schema Path reference cannot be NULL"); + } + final List qnamedPath = schemaPath.getPath(); + if (qnamedPath == null || qnamedPath.isEmpty()) { + throw new IllegalStateException("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."); + } + + if (type instanceof ExtendedType) { + final QName qname = qnamedPath.get(qnamedPath.size() - 1); + if ((qname != null) && (qname.getNamespace() != null)) { + return context.findModuleByNamespace(qname.getNamespace()); + } + } else { + final QName qname = qnamedPath.get(qnamedPath.size() - 2); if ((qname != null) && (qname.getNamespace() != null)) { - return context - .findModuleByNamespace(qname.getNamespace()); + return context.findModuleByNamespace(qname.getNamespace()); } } return null; } - + /** - * Search which starts from root of Module. - * - * @param module - * @param prefixedPath - * @return + * Returns parent Yang Module for specified Schema Context in which Schema Node is declared. 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 context 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 */ - private DataSchemaNode findSchemaNodeForGivenPath(final Module module, - final Queue prefixedPath) { - if ((module != null) && (prefixedPath != null)) { - DataNodeContainer nextContainer = module; - final String modulePrefix = module.getPrefix(); - - String childNodeName = null; - DataSchemaNode schemaNode = null; - while ((nextContainer != null) && (prefixedPath.size() > 0)) { - childNodeName = prefixedPath.poll(); - if (childNodeName.contains(":")) { - final String[] prefixedChildNode = childNodeName.split(":"); - if ((modulePrefix != null) - && modulePrefix.equals(prefixedChildNode[0])) { - - childNodeName = prefixedChildNode[1]; - } else { - final Module nextModule = resolveModuleForPrefix( - prefixedChildNode[0], module); - final Queue nextModulePrefixedPath = new LinkedList(); - nextModulePrefixedPath.add(childNodeName); - nextModulePrefixedPath.addAll(prefixedPath); - prefixedPath.clear(); + public static Module findParentModule(final SchemaContext context, final SchemaNode schemaNode) { + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (schemaNode == null) { + throw new IllegalArgumentException("Schema Node cannot be NULL!"); + } - schemaNode = findSchemaNodeForGivenPath(nextModule, - nextModulePrefixedPath); + final SchemaPath schemaPath = schemaNode.getPath(); + if (schemaPath == null) { + throw new IllegalStateException("Schema Path for Schema Node is not " + + "set properly (Schema Path is NULL)"); + } + final List qnamedPath = schemaPath.getPath(); + if (qnamedPath == null || qnamedPath.isEmpty()) { + throw new IllegalStateException("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."); + } + final QName qname = qnamedPath.get(qnamedPath.size() - 1); + return context.findModuleByNamespace(qname.getNamespace()); + } - return schemaNode; - } - } + /** + * Method will attempt to find DataSchemaNode from specified Module and Queue of QNames through the Schema + * Context. The QNamed path could be defined across multiple modules in Schema Context so the method is called + * recursively. If the QNamed path contains QNames that are not part of any Module or Schema Context Path the + * operation will fail and returns null + *
+ * If Schema Context, Module or Queue of QNames refers to null values, + * the method will throws IllegalArgumentException + * + * @throws IllegalArgumentException + * + * @param context Schema Context + * @param module Yang Module + * @param qnamedPath Queue of QNames + * @return DataSchemaNode if is present in Module(s) for specified Schema Context and given QNamed Path, + * otherwise will return null. + */ + private static DataSchemaNode findSchemaNodeForGivenPath(final SchemaContext context, final Module module, + final Queue qnamedPath) { + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (module == null) { + throw new IllegalArgumentException("Module reference cannot be NULL!"); + } + if (module.getNamespace() == null) { + throw new IllegalArgumentException("Namespace for Module cannot contains NULL reference!"); + } + if (qnamedPath == null || qnamedPath.isEmpty()) { + throw new IllegalStateException("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."); + } + + DataNodeContainer nextNode = module; + final URI moduleNamespace = module.getNamespace(); - schemaNode = nextContainer.getDataChildByName(childNodeName); - if (schemaNode instanceof ContainerSchemaNode) { - nextContainer = (ContainerSchemaNode) schemaNode; - } else if (schemaNode instanceof ListSchemaNode) { - nextContainer = (ListSchemaNode) schemaNode; - } else { + QName childNodeQName; + DataSchemaNode schemaNode = null; + while ((nextNode != null) && !qnamedPath.isEmpty()) { + childNodeQName = qnamedPath.peek(); + if (childNodeQName != null) { + final URI childNodeNamespace = childNodeQName.getNamespace(); + + schemaNode = nextNode.getDataChildByName(childNodeQName); + if (schemaNode != null) { + if (schemaNode instanceof ContainerSchemaNode) { + nextNode = (ContainerSchemaNode) schemaNode; + } else if (schemaNode instanceof ListSchemaNode) { + nextNode = (ListSchemaNode) schemaNode; + } else if (schemaNode instanceof ChoiceNode) { + final ChoiceNode choice = (ChoiceNode) schemaNode; + qnamedPath.poll(); + if (!qnamedPath.isEmpty()) { + childNodeQName = qnamedPath.peek(); + nextNode = choice.getCaseNodeByName(childNodeQName); + schemaNode = (DataSchemaNode) nextNode; + } + } else { + nextNode = null; + } + } else if (!childNodeNamespace.equals(moduleNamespace)) { + final Module nextModule = context.findModuleByNamespace(childNodeNamespace); + schemaNode = findSchemaNodeForGivenPath(context, nextModule, qnamedPath); return schemaNode; } + qnamedPath.poll(); } } - return null; + return schemaNode; } - private Module resolveModuleForPrefix(final String prefix, - final Module parent) { - if ((prefix != null) && (parent != null)) { - final Set imports = parent.getImports(); - - if (imports != null) { - for (final ModuleImport impModule : imports) { - final String impModPrefix = impModule.getPrefix(); - if ((impModPrefix != null) && prefix.equals(impModPrefix)) { - return resolveModuleFromContext(prefix, - impModule.getModuleName()); - } - } + /** + * Transforms string representation of XPath to Queue of QNames. The XPath is split by "/" and for each part of + * XPath is assigned correct module in Schema Path. + *
+ * If Schema Context, Parent Module or XPath string contains null values, + * the method will throws IllegalArgumentException + * + * @throws IllegalArgumentException + * + * @param context Schema Context + * @param parentModule Parent Module + * @param xpath XPath String + * @return + */ + private static Queue xpathToQNamePath(final SchemaContext context, final Module parentModule, + final String xpath) { + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (parentModule == null) { + throw new IllegalArgumentException("Parent Module reference cannot be NULL!"); + } + if (xpath == null) { + throw new IllegalArgumentException("XPath string reference cannot be NULL!"); + } + + final Queue path = new LinkedList<>(); + final String[] prefixedPath = xpath.split("/"); + for (int i = 0; i < prefixedPath.length; ++i) { + if (!prefixedPath[i].isEmpty()) { + path.add(stringPathPartToQName(context, parentModule, prefixedPath[i])); } } - return null; + return path; } - private Module resolveModuleFromContext(final String prefix, - final String moduleName) { - final Set modules = context.getModules(); + /** + * Transforms part of Prefixed Path as java String to QName. + *
+ * If the string contains module prefix separated by ":" (i.e. mod:container) this module is provided from from + * Parent Module list of imports. If the Prefixed module is present in Schema Context the QName can be + * constructed. + *
+ * If the Prefixed Path Part does not contains prefix the Parent's Module namespace is taken for construction of + * QName. + *
+ * If Schema Context, Parent Module or Prefixed Path Part refers to null the method will throw + * IllegalArgumentException + * + * @throws IllegalArgumentException + * + * @param context Schema Context + * @param parentModule Parent Module + * @param prefixedPathPart Prefixed Path Part string + * @return QName from prefixed Path Part String. + */ + private static QName stringPathPartToQName(final SchemaContext context, final Module parentModule, + final String prefixedPathPart) { + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (parentModule == null) { + throw new IllegalArgumentException("Parent Module reference cannot be NULL!"); + } + if (prefixedPathPart == null) { + throw new IllegalArgumentException("Prefixed Path Part cannot be NULL!"); + } - if ((prefix != null) && (moduleName != null) && (modules != null)) { - for (Module module : modules) { - if ((module != null) && prefix.equals(module.getPrefix()) - && moduleName.equals(module.getName())) { - return module; - } + if (prefixedPathPart.contains(":")) { + final String[] prefixedName = prefixedPathPart.split(":"); + final Module module = resolveModuleForPrefix(context, parentModule, prefixedName[0]); + if (module != null) { + return new QName(module.getNamespace(), module.getRevision(), prefixedName[1]); } + } else { + return new QName(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart); } return null; } - private Queue xpathToQueuedPath(final String xpath) { - final Queue retQueue = new LinkedList(); - if ((xpath != null)) { - final String[] prefixedPath = xpath.split("/"); + /** + * Method will attempt to resolve and provide Module reference for specified module prefix. Each Yang module + * could contains multiple imports which MUST be associated with corresponding module prefix. The method simply + * looks into module imports and returns the module that is bounded with specified prefix. If the prefix is not + * present in module or the prefixed module is not present in specified Schema Context, + * the method will return null. + *
+ * If String prefix is the same as prefix of the specified Module the reference to this module is returned. + *
+ * If Schema Context, Module or Prefix are referring to null the method will return + * IllegalArgumentException + * + * @throws IllegalArgumentException + * + * @param context Schema Context + * @param module Yang Module + * @param prefix Module Prefix + * @return Module for given prefix in specified Schema Context if is present, otherwise returns null + */ + private static Module resolveModuleForPrefix(final SchemaContext context, final Module module, final String prefix) { + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (module == null) { + throw new IllegalArgumentException("Module reference cannot be NULL!"); + } + if (prefix == null) { + throw new IllegalArgumentException("Prefix string cannot be NULL!"); + } - if (prefixedPath != null) { - for (int i = 0; i < prefixedPath.length; ++i) { - if (!prefixedPath[i].isEmpty()) { - retQueue.add(prefixedPath[i]); - } - } - } + if (prefix.equals(module.getPrefix())) { + return module; } - return retQueue; - } - - private Queue schemaPathToQueuedPath(final SchemaPath schemaPath) { - final Queue retQueue = new LinkedList(); - if ((schemaPath != null) && (schemaPath.getPath() != null)) { - final List listPath = schemaPath.getPath(); - - for (final QName qname : listPath) { - if (qname != null) { - final String prefix = qname.getPrefix(); - final String localName = qname.getLocalName(); - - final StringBuilder builder = new StringBuilder(); - if (prefix != null) { - builder.append(prefix); - builder.append(":"); - } - builder.append(localName); - retQueue.add(builder.toString()); - } + + final Set imports = module.getImports(); + for (final ModuleImport mi : imports) { + if (prefix.equals(mi.getPrefix())) { + return context.findModuleByName(mi.getModuleName(), mi.getRevision()); } } - return retQueue; + return null; } - - private Queue resolveRelativeXPath( - final RevisionAwareXPath relativeXPath, - final SchemaPath leafrefSchemaPath) { - final Queue absolutePath = new LinkedList(); - - if ((relativeXPath != null) && !relativeXPath.isAbsolute() - && (leafrefSchemaPath != null)) { - final String strXPath = relativeXPath.toString(); - if (strXPath != null) { - final String[] xpaths = strXPath.split("/"); - - if (xpaths != null) { - int colCount = 0; - while (xpaths[colCount].contains("..")) { - ++colCount; + + /** + * @throws IllegalArgumentException + * + * @param context Schema Context + * @param module Yang Module + * @param relativeXPath Non conditional Revision Aware Relative XPath + * @param leafrefSchemaPath Schema Path for Leafref + * @return + */ + private static Queue resolveRelativeXPath(final SchemaContext context, final Module module, + final RevisionAwareXPath relativeXPath, final SchemaPath leafrefSchemaPath) { + final Queue absolutePath = new LinkedList<>(); + if (context == null) { + throw new IllegalArgumentException("Schema Context reference cannot be NULL!"); + } + if (module == null) { + throw new IllegalArgumentException("Module reference cannot be NULL!"); + } + if (relativeXPath == null) { + throw new IllegalArgumentException("Non Conditional Revision Aware XPath cannot be NULL!"); + } + if (relativeXPath.isAbsolute()) { + throw new IllegalArgumentException("Revision Aware XPath MUST be relative i.e. MUST contains ../, " + + "for non relative Revision Aware XPath use findDataSchemaNode method!"); + } + if (leafrefSchemaPath == null) { + throw new IllegalArgumentException("Schema Path reference for Leafref cannot be NULL!"); + } + + final String strXPath = relativeXPath.toString(); + if (strXPath != null) { + final String[] xpaths = strXPath.split("/"); + if (xpaths != null) { + int colCount = 0; + while (xpaths[colCount].contains("..")) { + ++colCount; + } + final List path = leafrefSchemaPath.getPath(); + if (path != null) { + int lenght = path.size() - colCount - 1; + for (int i = 0; i < lenght; ++i) { + absolutePath.add(path.get(i)); } - final List path = leafrefSchemaPath.getPath(); - if (path != null) { - int lenght = path.size() - colCount; - for (int i = 0; i < lenght; ++i) { - absolutePath.add(path.get(i).getLocalName()); - } - for (int i = colCount; i < xpaths.length; ++i) { - absolutePath.add(xpaths[i]); - } + for (int i = colCount; i < xpaths.length; ++i) { + absolutePath.add(stringPathPartToQName(context, module, xpaths[i])); } } }