/* Copyright (c) 2012-2014 Boundless and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Distribution License v1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/edl-v10.html * * Contributors: * Gabriel Roldan (Boundless) - initial implementation */ package org.locationtech.geogig.api.plumbing; import static com.google.common.base.Preconditions.checkNotNull; import org.locationtech.geogig.api.AbstractGeoGigOp; import org.locationtech.geogig.api.Node; import org.locationtech.geogig.api.NodeRef; import org.locationtech.geogig.api.ObjectId; import org.locationtech.geogig.api.Ref; import org.locationtech.geogig.api.RevTree; import org.locationtech.geogig.repository.DepthSearch; import org.locationtech.geogig.storage.ObjectDatabase; import org.locationtech.geogig.storage.StagingDatabase; import com.google.common.base.Optional; import com.google.common.base.Supplier; import com.google.common.base.Suppliers; /** * Finds a {@link Node} by searching the given {@link RevTree} for the given path, returns the * {@link NodeRef} that wraps it. * * @see DepthSearch * @see ResolveTreeish * @see RevObjectParse */ public class FindTreeChild extends AbstractGeoGigOp<Optional<NodeRef>> { private Supplier<RevTree> parent; private String childPath; private String parentPath; private boolean indexDb; /** * @param indexDb whether to look up in the {@link StagingDatabase index db} ({@code true}) or * on the repository's {@link ObjectDatabase object database} (default) * @return {@code this} */ public FindTreeChild setIndex(final boolean indexDb) { this.indexDb = indexDb; return this; } /** * @param tree a supplier that resolves to the tree where to start the search for the nested * child. If not supplied the current HEAD tree is assumed. * @return {@code this} */ public FindTreeChild setParent(Supplier<RevTree> tree) { this.parent = tree; return this; } /** * @param tree the tree to search for the nested child * @return {@code this} */ public FindTreeChild setParent(RevTree tree) { this.parent = Suppliers.ofInstance(tree); return this; } /** * @param parentPath the parent's path. If not given parent is assumed to be a root tree. * @return {@code this} */ public FindTreeChild setParentPath(String parentPath) { this.parentPath = parentPath; return this; } /** * @param childPath the full path of the subtree to look for * @return {@code this} */ public FindTreeChild setChildPath(String childPath) { this.childPath = childPath; return this; } /** * Executes the command. * * @return an {@code Optional} that contains the Node if it was found, or * {@link Optional#absent()} if it wasn't */ @Override protected Optional<NodeRef> _call() { checkNotNull(childPath, "childPath"); final RevTree tree; if (parent == null) { ObjectId rootTreeId = command(ResolveTreeish.class).setTreeish(Ref.HEAD).call().get(); if (rootTreeId.isNull()) { return Optional.absent(); } tree = command(RevObjectParse.class).setObjectId(rootTreeId).call(RevTree.class).get(); } else { tree = parent.get(); } final String path = childPath; final String parentPath = this.parentPath == null ? "" : this.parentPath; final ObjectDatabase target = indexDb ? stagingDatabase() : objectDatabase(); DepthSearch depthSearch = new DepthSearch(target); Optional<NodeRef> childRef = depthSearch.find(tree, parentPath, path); return childRef; } }