Package org.locationtech.geogig.api.plumbing.diff

Source Code of org.locationtech.geogig.api.plumbing.diff.VerifyPatchOp

/* 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:
* Victor Olaya (Boundless) - initial implementation
*/
package org.locationtech.geogig.api.plumbing.diff;

import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import org.locationtech.geogig.api.AbstractGeoGigOp;
import org.locationtech.geogig.api.FeatureInfo;
import org.locationtech.geogig.api.NodeRef;
import org.locationtech.geogig.api.ObjectId;
import org.locationtech.geogig.api.Ref;
import org.locationtech.geogig.api.RevFeature;
import org.locationtech.geogig.api.RevFeatureBuilder;
import org.locationtech.geogig.api.RevFeatureType;
import org.locationtech.geogig.api.RevObject;
import org.locationtech.geogig.api.plumbing.RevObjectParse;
import org.locationtech.geogig.repository.DepthSearch;
import org.locationtech.geogig.repository.WorkingTree;
import org.opengis.feature.type.PropertyDescriptor;

import com.google.common.base.Objects;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;

/**
* Verifies if a patch can be applied to the current working tree
*
* @see WorkingTree
* @see Patch
*/
public class VerifyPatchOp extends AbstractGeoGigOp<VerifyPatchResults> {

    private Patch patch;

    private boolean reverse;

    /**
     * Sets the patch to verify
     *
     * @param patch the patch to verify
     * @return {@code this}
     */
    public VerifyPatchOp setPatch(Patch patch) {
        this.patch = patch;
        return this;
    }

    /**
     * Sets whether to verify the original patch or its reversed version
     *
     * @param reverse true if the patch should be verified in its reversed version
     * @return {@code this}
     */
    public VerifyPatchOp setReverse(boolean reverse) {
        this.reverse = reverse;
        return this;
    }

    /**
     * Executes the verify command
     *
     * @return the result of checking if the patch can be applied
     */
    protected VerifyPatchResults _call() throws RuntimeException {
        Preconditions.checkArgument(patch != null, "No patch file provided");

        Patch patch = reverse ? this.patch.reversed() : this.patch;

        Patch toApply = new Patch();
        Patch toReject = new Patch();
        for (RevFeatureType ft : patch.getFeatureTypes()) {
            toApply.addFeatureType(ft);
            toReject.addFeatureType(ft);
        }
        String path;
        Optional<RevObject> obj;
        List<FeatureDiff> diffs = patch.getModifiedFeatures();
        for (FeatureDiff diff : diffs) {
            path = diff.getPath();
            String refSpec = Ref.WORK_HEAD + ":" + path;
            obj = command(RevObjectParse.class).setRefSpec(refSpec).call();
            if (!obj.isPresent()) {
                toReject.addModifiedFeature(diff);
                break;
            }
            RevFeature feature = (RevFeature) obj.get();
            DepthSearch depthSearch = new DepthSearch(stagingDatabase());
            Optional<NodeRef> noderef = depthSearch.find(workingTree().getTree(), path);
            RevFeatureType featureType = command(RevObjectParse.class)
                    .setObjectId(noderef.get().getMetadataId()).call(RevFeatureType.class).get();
            ImmutableList<PropertyDescriptor> descriptors = featureType.sortedDescriptors();
            Set<Entry<PropertyDescriptor, AttributeDiff>> attrDiffs = diff.getDiffs().entrySet();
            boolean ok = true;
            for (Iterator<Entry<PropertyDescriptor, AttributeDiff>> iterator = attrDiffs.iterator(); iterator
                    .hasNext();) {
                Entry<PropertyDescriptor, AttributeDiff> entry = iterator.next();
                AttributeDiff attrDiff = entry.getValue();
                PropertyDescriptor descriptor = entry.getKey();
                switch (attrDiff.getType()) {
                case ADDED:
                    if (descriptors.contains(descriptor)) {
                        ok = false;
                    }
                    break;
                case REMOVED:
                case MODIFIED:
                    if (!descriptors.contains(descriptor)) {
                        ok = false;
                        break;
                    }
                    for (int i = 0; i < descriptors.size(); i++) {
                        if (descriptors.get(i).equals(descriptor)) {
                            Optional<Object> value = feature.getValues().get(i);
                            if (!attrDiff.canBeAppliedOn(value)) {
                                ok = false;
                            }
                            break;
                        }
                    }
                }
            }
            if (!ok) {
                toReject.addModifiedFeature(diff);
            } else {
                toApply.addModifiedFeature(diff);
            }
        }
        List<FeatureInfo> added = patch.getAddedFeatures();
        for (FeatureInfo feature : added) {
            String refSpec = Ref.WORK_HEAD + ":" + feature.getPath();
            obj = command(RevObjectParse.class).setRefSpec(refSpec).call();
            if (obj.isPresent()) {
                toReject.addAddedFeature(feature.getPath(), feature.getFeature(),
                        feature.getFeatureType());
            } else {
                toApply.addAddedFeature(feature.getPath(), feature.getFeature(),
                        feature.getFeatureType());
            }

        }
        List<FeatureInfo> removed = patch.getRemovedFeatures();
        for (FeatureInfo feature : removed) {
            String refSpec = Ref.WORK_HEAD + ":" + feature.getPath();
            obj = command(RevObjectParse.class).setRefSpec(refSpec).call();
            if (!obj.isPresent()) {
                toReject.addRemovedFeature(feature.getPath(), feature.getFeature(),
                        feature.getFeatureType());
            } else {
                RevFeature revFeature = (RevFeature) obj.get();
                DepthSearch depthSearch = new DepthSearch(stagingDatabase());
                Optional<NodeRef> noderef = depthSearch.find(workingTree().getTree(),
                        feature.getPath());
                RevFeatureType revFeatureType = command(RevObjectParse.class)
                        .setObjectId(noderef.get().getMetadataId()).call(RevFeatureType.class)
                        .get();
                RevFeature patchRevFeature = RevFeatureBuilder.build(feature.getFeature());
                if (revFeature.equals(patchRevFeature)
                        && revFeatureType.equals(feature.getFeatureType())) {
                    toApply.addRemovedFeature(feature.getPath(), feature.getFeature(),
                            feature.getFeatureType());
                } else {
                    toReject.addRemovedFeature(feature.getPath(), feature.getFeature(),
                            feature.getFeatureType());
                }
            }
        }
        ImmutableList<FeatureTypeDiff> alteredTrees = patch.getAlteredTrees();
        for (FeatureTypeDiff diff : alteredTrees) {
            DepthSearch depthSearch = new DepthSearch(stagingDatabase());
            Optional<NodeRef> noderef = depthSearch.find(workingTree().getTree(), diff.getPath());
            ObjectId metadataId = noderef.isPresent() ? noderef.get().getMetadataId()
                    : ObjectId.NULL;
            if (Objects.equal(metadataId, diff.getOldFeatureType())) {
                toApply.addAlteredTree(diff);
            } else {
                toReject.addAlteredTree(diff);
            }
        }

        return new VerifyPatchResults(toApply, toReject);

    }

}
TOP

Related Classes of org.locationtech.geogig.api.plumbing.diff.VerifyPatchOp

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.