@Override protected RevTree _call() { checkArgument(root != null, "root tree not provided"); if (childTreeRemoves.isEmpty() && childTreeUpdates.isEmpty()) { return root; } // all the current child trees of root final MutableTree mutableRoot = load(root); MutableTree updatedRoot = mutableRoot.clone(); this.childTreeRemoves.forEach((path) -> { updatedRoot.removeChild(path); }); this.childTreeUpdates.values().forEach((r) -> { updatedRoot.forceChild(r.getParentPath(), r.getNode()); }); ObjectDatabase db = objectDatabase(); RevTree newRoot = updatedRoot.build(db); return newRoot; }
public static MutableTree createFromRefs(final ObjectId rootId, final Supplier<Iterator<NodeRef>> refs) { return createFromRefs(rootId, refs.get()); }
public MutableTree getChild(final List<String> path) throws IllegalArgumentException { Preconditions.checkArgument(!path.isEmpty()); String directChildName = path.get(0); MutableTree child = childTrees.get(directChildName); if (child == null) { throw new IllegalArgumentException(String.format("No child named %s exists: %s", directChildName, childTrees.keySet())); } if (path.size() == 1) { return child; } return child.getChild(path.subList(1, path.size())); }
@Override public MutableTree clone() { MutableTree clone = new MutableTree(node); for (MutableTree child : this.childTrees.values()) { clone.childTrees.put(child.getNode().getName(), child.clone()); } return clone; } }
private RevTree createFromRefs(ObjectDatabase targetDb, NodeRef... treeRefs) { MutableTree mutableTree = MutableTree.createFromRefs(RevTree.EMPTY_TREE_ID, treeRefs); RevTree tree = mutableTree.build(targetDb); return tree; }
@Test public void testSet() { Node node = treeNode("roads", id("a11"), id("d1")); root.setChild("", node); assertEquals(node, root.getChild("roads").getNode()); node = treeNode("stores", id("a51"), id("d3")); root.setChild("buildings", node); assertEquals(node, root.getChild("buildings/stores").getNode()); }
Node leftNode = leftTree.getNode(); ObjectId leftOid = leftNode.getObjectId(); return leftOid; final MutableTree oldLeftTree = treeDifference.getLeftTree().clone(); Preconditions.checkState(oldLeftTree.equals(treeDifference.getLeftTree())); final RevTree newRoot = newLeftTree.build(repositoryDatabase);
@Test public void testRemoveNested() { assertNotNull(root.getChild("roads/highways")); assertNotNull(root.getChild("roads/streets")); assertNull(root.removeChild("nonExistent")); assertNotNull(root.removeChild("roads/streets")); assertNotNull(root.getChild("roads")); assertNotNull(root.getChild("roads/highways")); ex.expect(IllegalArgumentException.class); ex.expectMessage("No child named streets exists"); root.getChild("roads/streets"); }
/** * Finds tree pointers that point to the same tree (path and object id) on the left and right * sides of the comparison but have different {@link NodeRef#getMetadataId() metadata ids} */ public Map<NodeRef, NodeRef> findPureMetadataChanges() { SortedMap<String, MutableTree> leftEntries = leftTree.getChildrenAsMap(); SortedMap<String, MutableTree> rightEntries = rightTree.getChildrenAsMap(); Map<NodeRef, NodeRef> matches = Maps.newTreeMap(); for (Map.Entry<String, MutableTree> e : leftEntries.entrySet()) { final String nodePath = e.getKey(); final MutableTree leftTree = e.getValue(); final Node leftNode = leftTree.getNode(); @Nullable final MutableTree rightTree = rightEntries.get(nodePath); final Node rightNode = rightTree == null ? null : rightTree.getNode(); if (leftNode.equals(rightNode)) { final Optional<ObjectId> leftMetadata = leftNode.getMetadataId(); final Optional<ObjectId> rightMetadata = rightNode.getMetadataId(); if (!leftMetadata.equals(rightMetadata)) { String parentPath = NodeRef.parentPath(nodePath); NodeRef leftRef = new NodeRef(leftNode, parentPath, ObjectId.NULL); NodeRef rightRef = new NodeRef(rightNode, parentPath, ObjectId.NULL); matches.put(leftRef, rightRef); } } } return matches; }
public void setChild(final List<String> parentPath, final Node node) { MutableTree parent; MutableTree child; if (parentPath.isEmpty()) { parent = this; } else { parent = getChild(parentPath); } child = parent.childTrees.get(node.getName()); if (child == null) { child = new MutableTree(node); parent.childTrees.put(node.getName(), child); } else { child.setNode(node); } }
public static MutableTree createFromPaths(final ObjectId rootId, final Map<String, NodeRef> entries) { List<NodeRef> refsByDepth = Lists.newArrayList(entries.values()); Collections.sort(refsByDepth, DEEPEST_LAST_COMPARATOR); Node rootNode = Node.create(ROOT, rootId, ObjectId.NULL, TYPE.TREE, null); MutableTree root = new MutableTree(rootNode); Envelope bounds = new Envelope(); for (NodeRef entry : refsByDepth) { Node node = entry.getNode(); node.expand(bounds); String parentPath = entry.getParentPath(); root.setChild(parentPath, node); } // recreate root node with the appropriate bounds rootNode = Node.create(ROOT, rootId, ObjectId.NULL, TYPE.TREE, bounds); root.setNode(rootNode); return root; }
/** * A renamed tree is recognized by checking if a tree on the right points to the same object * that a tree on the left that doesn't exist anymore on the right. * <p> * Left entries are the original ones, and right entries are the new ones. * </p> * * @param treeDifference * @param ignoreList */ private void handleRenames(TreeDifference treeDifference, Set<String> ignoreList) { final SortedMap<NodeRef, NodeRef> renames = treeDifference.findRenames(); for (Map.Entry<NodeRef, NodeRef> e : renames.entrySet()) { NodeRef oldValue = e.getKey(); NodeRef newValue = e.getValue(); String newPath = newValue.path(); if (ignoreList.contains(newPath)) { continue; } ignoreList.add(newPath); if (!filterMatchesOrIsParent(newPath)) { continue;// filter doesn't apply to the renamed tree as a whole } LOGGER.trace("Handling rename of {} as {}", oldValue.path(), newPath); MutableTree leftTree = treeDifference.getLeftTree(); leftTree.removeChild(oldValue.path()); leftTree.setChild(newValue.getParentPath(), newValue.getNode()); } }
public void setChild(String parentPath, Node node) { List<String> parentSteps = split(parentPath); setChild(parentSteps, node); }
private void asMap(String parentPath, TreeMap<String, MutableTree> target) { for (MutableTree childTree : this.childTrees.values()) { String childTreePath = NodeRef.appendChild(parentPath, childTree.getNode().getName()); target.put(childTreePath, childTree); childTree.asMap(childTreePath, target); } }
private void handleDeletedTrees(TreeDifference treeDifference, Set<String> ignoreList) { SortedSet<NodeRef> deletes = treeDifference.findDeletes(); for (NodeRef ref : deletes) { String path = ref.path(); if (ignoreList.contains(path)) { continue; } ignoreList.add(path); if (!filterMatchesOrIsParent(path)) { if (filterApplies(path, treeDifference.getRightTree())) { // can't optimize RevTree newTree = applyChanges(ref, null); Node newNode = Node.tree(ref.name(), newTree.getId(), ref.getMetadataId()); MutableTree leftTree = treeDifference.getLeftTree(); leftTree.forceChild(ref.getParentPath(), newNode); } } else { MutableTree leftTree = treeDifference.getLeftTree(); leftTree.removeChild(path); } } }
private void handleNewTrees(TreeDifference treeDifference, Set<String> ignoreList) { SortedSet<NodeRef> newTrees = treeDifference.findNewTrees(); for (NodeRef ref : newTrees) { final String path = ref.path(); if (ignoreList.contains(path)) { continue; } ignoreList.add(path); if (!filterMatchesOrIsParent(path)) { MutableTree rightTree = treeDifference.getRightTree(); if (filterApplies(path, rightTree)) { // can't optimize RevTree newTree = applyChanges(null, ref); Node newNode = Node.tree(ref.name(), newTree.getId(), ref.getMetadataId()); MutableTree leftTree = treeDifference.getLeftTree(); leftTree.forceChild(ref.getParentPath(), newNode); } } else { LOGGER.trace("Creating new tree {}", path); MutableTree leftTree = treeDifference.getLeftTree(); String parentPath = ref.getParentPath(); Node node = ref.getNode(); leftTree.setChild(parentPath, node); } } }
private SortedMap<NodeRef, NodeRef> findRenames( SortedMapDifference<String, MutableTree> difference) { SortedMap<String, MutableTree> entriesOnlyOnLeft = difference.entriesOnlyOnLeft(); SortedMap<String, MutableTree> entriesOnlyOnRight = difference.entriesOnlyOnRight(); SortedMap<NodeRef, NodeRef> matches = newTreeMap(); for (Map.Entry<String, MutableTree> right : entriesOnlyOnRight.entrySet()) { for (Map.Entry<String, MutableTree> left : entriesOnlyOnLeft.entrySet()) { Node leftNode = left.getValue().getNode(); Node rightNode = right.getValue().getNode(); if (rightNode.getObjectId().equals(leftNode.getObjectId())) { String leftParent = NodeRef.parentPath(left.getKey()); String rightParent = NodeRef.parentPath(right.getKey()); NodeRef leftRef = new NodeRef(leftNode, leftParent, ObjectId.NULL); NodeRef rightRef = new NodeRef(rightNode, rightParent, ObjectId.NULL); matches.put(leftRef, rightRef); } } } return matches; }
public void forceChild(final String parentPath, final Node treeNode) { ImmutableList<String> parentSteps = NodeRef.split(parentPath); MutableTree parent = this; for (String name : parentSteps) { MutableTree child = parent.childTrees.get(name); if (child == null) { child = new MutableTree(name); parent.childTrees.put(name, child); } parent = child; } MutableTree tree = parent.childTrees.get(treeNode.getName()); if (tree == null) { tree = new MutableTree(treeNode); parent.childTrees.put(treeNode.getName(), tree); } else { tree.setNode(treeNode); } }
public RevTree build(ObjectStore store) { final ObjectId treeId = this.node.getObjectId(); final RevTree original = EMPTY_TREE_ID.equals(treeId) ? EMPTY : store.getTree(treeId); RevTreeBuilder builder = RevTreeBuilder.builder(store, original); ImmutableList<Node> currentTrees = original.trees(); currentTrees.forEach(builder::remove); for (MutableTree childTree : this.childTrees.values()) { childTree.build(store); Node newNode = childTree.node; builder.put(newNode); } final Node oldNode = this.node; RevTree newTree = builder.build(); Envelope newBounds = SpatialOps.boundsOf(newTree); Node newNode = oldNode.update(newTree.getId(), newBounds); this.node = newNode; return newTree; }