/* (c) 2016 Open Source Geospatial Foundation - all rights reserved * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geogig.geoserver.gwc; import static com.google.common.base.Optional.fromNullable; import org.locationtech.geogig.model.ObjectId; import org.locationtech.geogig.model.Ref; import org.locationtech.geogig.model.RevTree; import org.locationtech.geogig.plumbing.ResolveTreeish; import org.locationtech.geogig.plumbing.diff.PathFilteringDiffConsumer; import org.locationtech.geogig.plumbing.diff.PreOrderDiffWalk; import org.locationtech.geogig.plumbing.diff.PreOrderDiffWalk.Consumer; import org.locationtech.geogig.repository.AbstractGeoGigOp; import org.locationtech.geogig.storage.ObjectDatabase; import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.vividsolutions.jts.geom.Geometry; /** * An operation that computes the "approximate minimal bounds" difference between two {@link RevTree * trees}. * <p> * The "approximate minimal bounds" is defined as the geometry union of the bounds of each * individual difference, with the exception that when a tree node or bucket tree does not exist at * either side of the comparison, the traversal of the existing tree is skipped and its whole bounds * are used instead of adding up the bounds of each individual feature. * <p> * One depth level filtering by tree name is supported through {@link #setTreeNameFilter(String)} in * order to skip root node's children sibling of the tree of interest. * <p> * The tree-ish at the left side of the comparison is set through {@link #setOldVersion(String)}, * and defaults to {@link Ref#HEAD} if not set. * <p> * The tree-ish at the right side of the comparison is set through {@link #setNewVersion(String)}, * and defaults to {@link Ref#WORK_HEAD} if not set. * */ public class MinimalDiffBounds extends AbstractGeoGigOp<Geometry> { private String oldVersion; private String newVersion; private String treeName; public MinimalDiffBounds setOldVersion(String oldTreeish) { this.oldVersion = oldTreeish; return this; } public MinimalDiffBounds setNewVersion(String newTreeish) { this.newVersion = newTreeish; return this; } public MinimalDiffBounds setTreeNameFilter(String treeName) { this.treeName = treeName; return this; } @Override protected Geometry _call() { final String leftRefSpec = fromNullable(oldVersion).or(Ref.HEAD); final String rightRefSpec = fromNullable(newVersion).or(Ref.WORK_HEAD); RevTree left = resolveTree(leftRefSpec); RevTree right = resolveTree(rightRefSpec); ObjectDatabase leftSource = objectDatabase(); ObjectDatabase rightSource = objectDatabase(); PreOrderDiffWalk visitor = new PreOrderDiffWalk(left, right, leftSource, rightSource); MinimalDiffBoundsConsumer boundsBuilder = new MinimalDiffBoundsConsumer(); Consumer consumer = boundsBuilder; if (treeName != null) { consumer = new PathFilteringDiffConsumer(ImmutableList.of(treeName), boundsBuilder); } visitor.walk(consumer); Geometry minimalBounds = boundsBuilder.buildGeometry(); return minimalBounds; } private RevTree resolveTree(String refSpec) { Optional<ObjectId> id = command(ResolveTreeish.class).setTreeish(refSpec).call(); Preconditions.checkState(id.isPresent(), "%s did not resolve to a tree", refSpec); return objectDatabase().getTree(id.get()); } }