/* Copyright (c) 2013 OpenPlans. All rights reserved.
 * This code is licensed under the BSD New License, available at the root
 * application directory.
 */

package org.geogit.api.plumbing;

import static com.google.common.base.Preconditions.checkState;

import java.util.List;

import javax.annotation.Nullable;

import org.geogit.api.AbstractGeoGitOp;
import org.geogit.api.ObjectId;
import org.geogit.api.RevTree;
import org.geogit.api.plumbing.diff.DiffCountConsumer;
import org.geogit.api.plumbing.diff.DiffObjectCount;
import org.geogit.api.plumbing.diff.DiffTreeVisitor;
import org.geogit.api.plumbing.diff.DiffTreeWalk;
import org.geogit.api.plumbing.diff.PathFilteringDiffConsumer;
import org.geogit.storage.StagingDatabase;

import com.google.common.base.Optional;
import com.google.common.collect.Lists;

/**
 * A faster alternative to count the number of diffs between two trees than walking a
 * {@link DiffTreeWalk} iterator.
 * 
 * @see DiffCountConsumer
 */
public class DiffCount extends AbstractGeoGitOp<DiffObjectCount> {

    private final List<String> pathFilters = Lists.newLinkedList();

    private String oldRefSpec;

    private String newRefSpec;

    public DiffCount setOldVersion(@Nullable String refSpec) {
        this.oldRefSpec = refSpec;
        return this;
    }

    public DiffCount setNewVersion(@Nullable String refSpec) {
        this.newRefSpec = refSpec;
        return this;
    }

    /**
     * @param path the path filter to use during the diff operation
     * @return {@code this}
     */
    public DiffCount addFilter(@Nullable String path) {
        if (path != null) {
            pathFilters.add(path);
        }
        return this;
    }

    /**
     * @param paths list of paths to filter by, if {@code null} or empty, then no filtering is done,
     *        otherwise the list must not contain null elements.
     */
    public DiffCount setFilter(@Nullable List<String> paths) {
        pathFilters.clear();
        if (paths != null) {
            pathFilters.addAll(paths);
        }
        return this;
    }

    @Override
    protected DiffObjectCount _call() {
        checkState(oldRefSpec != null, "old ref spec not provided");
        checkState(newRefSpec != null, "new ref spec not provided");

        final RevTree oldTree = getTree(oldRefSpec);
        final RevTree newTree = getTree(newRefSpec);

        DiffObjectCount diffCount;
        StagingDatabase index = stagingDatabase();
        DiffTreeVisitor visitor = new DiffTreeVisitor(oldTree, newTree, index, index);

        DiffCountConsumer counter = new DiffCountConsumer(index);
        DiffTreeVisitor.Consumer filter = counter;
        if (!pathFilters.isEmpty()) {
            filter = new PathFilteringDiffConsumer(pathFilters, counter);
        }
        visitor.walk(filter);
        diffCount = counter.get();

        return diffCount;
    }

    /**
     * @return the tree referenced by the old ref, or the head of the index.
     */
    private RevTree getTree(String refSpec) {

        final RevTree headTree;
        Optional<ObjectId> resolved = command(ResolveTreeish.class).setTreeish(refSpec).call();
        if (resolved.isPresent() && !resolved.get().isNull()) {
            ObjectId headTreeId = resolved.get();
            headTree = command(RevObjectParse.class).setObjectId(headTreeId).call(RevTree.class)
                    .get();
        } else {
            headTree = RevTree.EMPTY;
        }
        return headTree;
    }

}

@@ -3187,36 +3187,8 @@
 nt()
- && !resolved.get().isNull()
 ) %7B%0A

Remove unnecesary check for null id after 16cb52117 is merged