Package org.locationtech.geogig.remote

Source Code of org.locationtech.geogig.remote.FilteredDiffIterator

/* Copyright (c) 2013-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:
* Johnathan Garrett (LMN Solutions) - initial implementation
*/
package org.locationtech.geogig.remote;

import java.util.Iterator;

import org.locationtech.geogig.api.NodeRef;
import org.locationtech.geogig.api.ObjectId;
import org.locationtech.geogig.api.RepositoryFilter;
import org.locationtech.geogig.api.RevFeatureType;
import org.locationtech.geogig.api.RevObject;
import org.locationtech.geogig.api.RevObject.TYPE;
import org.locationtech.geogig.api.plumbing.RevObjectParse;
import org.locationtech.geogig.api.plumbing.diff.DiffEntry;
import org.locationtech.geogig.repository.Repository;

import com.google.common.collect.AbstractIterator;

/**
* An implementation of a {@link DiffEntry} iterator that filters entries based on a provided
* {@link RepositoryFilter}.
*/
public abstract class FilteredDiffIterator extends AbstractIterator<DiffEntry> {

    protected boolean filtered = false;

    private Iterator<DiffEntry> source;

    private Repository sourceRepo;

    private RepositoryFilter repoFilter;

    public final boolean wasFiltered() {
        return filtered;
    }

    /**
     * @return {@code true} if a side effect of consuming this iterator is that the objects it
     *         refers to are automatically added to the local objects database
     */
    public abstract boolean isAutoIngesting();

    /**
     * Constructs a new {@code FilteredDiffIterator}.
     *
     * @param source the unfiltered iterator
     * @param sourceRepo the repository where objects are stored
     * @param repoFilter the filter to use
     */
    public FilteredDiffIterator(Iterator<DiffEntry> source, Repository sourceRepo,
            RepositoryFilter repoFilter) {
        this.source = source;
        this.sourceRepo = sourceRepo;
        this.repoFilter = repoFilter;
        filtered = false;
    }

    /**
     * Compute the next {@link DiffEntry} that matches our {@link RepositoryFilter}.
     */
    protected DiffEntry computeNext() {
        while (source.hasNext()) {
            DiffEntry input = source.next();

            // HACK: ignore diff entries reporting a change to a tree, the feature changes will come
            // next and the new tree is built from them. I'm not totally sure this is the best way
            // to handle this situation but the unit tests are written expecting this behavior
            // probably as a side effect of a bug in TreeDiffEntryIterator (used to be called by
            // DiffTree) that doesn't report tree changes even is setReportTrees(true) was set.
            if (input.isChange() && input.getOldObject().getType().equals(TYPE.TREE)) {
                continue;
            }
            NodeRef oldObject = filter(input.getOldObject());
            NodeRef newObject;
            if (oldObject != null) {
                newObject = input.getNewObject();
                if (newObject != null) {
                    // we are tracking this object, but we still need to process the new object
                    RevObject object = sourceRepo.command(RevObjectParse.class)
                            .setObjectId(newObject.getNode().getObjectId()).call().get();

                    RevObject metadata = null;
                    if (newObject.getMetadataId() != ObjectId.NULL) {
                        metadata = sourceRepo.command(RevObjectParse.class)
                                .setObjectId(newObject.getMetadataId()).call().get();
                    }
                    processObject(object);
                    processObject(metadata);
                }
            } else {
                newObject = filter(input.getNewObject());
            }

            if (oldObject == null && newObject == null) {
                filtered = true;
                continue;
            }

            return new DiffEntry(oldObject, newObject);
        }
        return endOfData();
    }

    private NodeRef filter(NodeRef node) {
        if (node == null) {
            return null;
        }

        RevObject object = sourceRepo.objectDatabase().get(node.objectId());

        RevObject metadata = null;
        if (!node.getMetadataId().isNull()) {
            metadata = sourceRepo.objectDatabase().get(node.getMetadataId());
        }
        if (node.getType() == TYPE.FEATURE) {
            if (trackingObject(object.getId())) {
                // We are already tracking this object, continue to do so
                return node;
            }

            RevFeatureType revFeatureType = (RevFeatureType) metadata;

            if (!repoFilter.filterObject(revFeatureType, node.getParentPath(), object)) {
                return null;
            }

        }
        processObject(object);
        processObject(metadata);
        return node;
    }

    /**
     * An overridable method for hinting that the given object should be tracked, regardless of
     * whether or not it matches the filter.
     *
     * @param objectId the id of the object
     * @return true if the object should be tracked, false if it should only be tracked if it
     *         matches the filter
     */
    protected boolean trackingObject(ObjectId objectId) {
        return true;
    }

    /**
     * An overridable method to process all objects that match the filter.
     *
     * @param object the object to process
     */
    protected void processObject(RevObject object) {

    }

}
TOP

Related Classes of org.locationtech.geogig.remote.FilteredDiffIterator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.