/** * Helper to convert a path into an indexed path which uniquely identifies a node * * @param nodeRef * @param path * @return */ private Path createIndexedPath(NodeRef nodeRef, Path path) { // Add indexes for same name siblings // TODO: Look at more efficient approach for (int i = path.size() - 1; i >= 0; i--) { Path.Element pathElement = path.get(i); if (i > 0 && pathElement instanceof Path.ChildAssocElement) { int index = 1; // for xpath index compatibility String searchPath = path.subPath(i).toPrefixString(namespaceService); List<NodeRef> siblings = searchService.selectNodes(nodeRef, searchPath, null, namespaceService, false); if (siblings.size() > 1) { ChildAssociationRef childAssoc = ((Path.ChildAssocElement) pathElement).getRef(); NodeRef childRef = childAssoc.getChildRef(); for (NodeRef sibling : siblings) { if (sibling.equals(childRef)) { childAssoc.setNthSibling(index); break; } index++; } } } } return path; }
/** * Return relative path between from and to references within export root * * @param fromRef from reference * @param toRef to reference * @return path */ private Path createPath(NodeRef rootRef, NodeRef fromRef, NodeRef toRef) { // Check that item exists first if (!nodeService.exists(toRef)) { // return null path return null; } // Check whether item is the root node of the store // If so, always return absolute path if (toRef.equals(nodeService.getRootNode(toRef.getStoreRef()))) { return nodeService.getPath(toRef); } // construct relative path Path rootPath = createIndexedPath(rootRef, nodeService.getPath(rootRef)); Path fromPath = createIndexedPath(fromRef, nodeService.getPath(fromRef)); Path toPath = createIndexedPath(toRef, nodeService.getPath(toRef)); Path relativePath = null; try { // Determine if 'to path' is a category // TODO: This needs to be resolved in a more appropriate manner - special support is // required for categories. for (int i = 0; i < toPath.size(); i++) { Path.Element pathElement = toPath.get(i); if (pathElement.getPrefixedString(namespaceService).equals("cm:categoryRoot")) { Path.ChildAssocElement childPath = (Path.ChildAssocElement) pathElement; relativePath = new Path(); relativePath.append( new Path.ChildAssocElement( new ChildAssociationRef(null, null, null, childPath.getRef().getParentRef()))); relativePath.append(toPath.subPath(i + 1, toPath.size() - 1)); break; } } if (relativePath == null) { // Determine if from node is relative to export tree int i = 0; while (i < rootPath.size() && i < fromPath.size() && rootPath.get(i).equals(fromPath.get(i))) { i++; } if (i == rootPath.size()) { // Determine if to node is relative to export tree i = 0; while (i < rootPath.size() && i < toPath.size() && rootPath.get(i).equals(toPath.get(i))) { i++; } if (i == rootPath.size()) { // build relative path between from and to relativePath = new Path(); for (int p = 0; p < fromPath.size() - i; p++) { relativePath.append(new Path.ParentElement()); } if (i < toPath.size()) { relativePath.append(toPath.subPath(i, toPath.size() - 1)); } } } } if (relativePath == null) { // default to absolute path relativePath = toPath; } } catch (Throwable e) { String msg = "Failed to determine relative path: root path=" + rootPath + "; from path=" + fromPath + "; to path=" + toPath; throw new ExporterException(msg, e); } return relativePath; }