+ private static List<QName> createWalkablePath(final Iterable<QName> schemaNodePath, final SchemaContext context,
+ final int colCount) {
+ final List<Integer> indexToRemove = new ArrayList<>();
+ List<QName> schemaNodePathRet = Lists.newArrayList(schemaNodePath);
+ for (int j = 0, i = schemaNodePathRet.size() - 1; i >= 0 && j != colCount; i--, j++) {
+ final SchemaNode nodeIn = findTargetNode(context, schemaNodePathRet);
+ if (nodeIn instanceof CaseSchemaNode || nodeIn instanceof ChoiceSchemaNode) {
+ indexToRemove.add(i);
+ j--;
+ }
+ schemaNodePathRet.remove(i);
+ }
+ schemaNodePathRet = Lists.newArrayList(schemaNodePath);
+ for (int i : indexToRemove) {
+ schemaNodePathRet.remove(i);
+ }
+ return schemaNodePathRet;
+ }
+
+ private static SchemaNode resolveDerefPath(final SchemaContext context, final Module module,
+ final SchemaNode actualSchemaNode, final String xpath) {
+ final int paren = xpath.indexOf(')', 6);
+ checkArgument(paren != -1, "Cannot find matching parentheses in %s", xpath);
+
+ final String derefArg = xpath.substring(6, paren).strip();
+ // Look up the node which we need to reference
+ final SchemaNode derefTarget = findTargetNode(context, resolveRelativePath(context, module, actualSchemaNode,
+ doSplitXPath(derefArg)));
+ checkArgument(derefTarget != null, "Cannot find deref(%s) target node %s in context of %s", derefArg,
+ actualSchemaNode);
+ checkArgument(derefTarget instanceof TypedDataSchemaNode, "deref(%s) resolved to non-typed %s", derefArg,
+ derefTarget);
+
+ // We have a deref() target, decide what to do about it
+ final TypeDefinition<?> targetType = ((TypedDataSchemaNode) derefTarget).getType();
+ if (targetType instanceof InstanceIdentifierTypeDefinition) {
+ // Static inference breaks down, we cannot determine where this points to
+ // FIXME: dedicated exception, users can recover from it, derive from IAE
+ throw new UnsupportedOperationException("Cannot infer instance-identifier reference " + targetType);
+ }
+
+ // deref() is define only for instance-identifier and leafref types, handle the latter
+ checkArgument(targetType instanceof LeafrefTypeDefinition, "Illegal target type %s", targetType);
+
+ final PathExpression targetPath = ((LeafrefTypeDefinition) targetType).getPathStatement();
+ LOG.debug("Derefencing path {}", targetPath);
+
+ final SchemaNode deref = targetPath.isAbsolute()
+ ? findTargetNode(context, actualSchemaNode.getQName().getModule(),
+ ((LocationPathSteps) targetPath.getSteps()).getLocationPath())
+ : findDataSchemaNodeForRelativeXPath(context, module, actualSchemaNode, targetPath);
+ if (deref == null) {
+ LOG.debug("Path {} could not be derefenced", targetPath);
+ return null;
+ }