Search in sources :

Example 71 with RevObject

use of org.locationtech.geogig.api.RevObject in project GeoGig by boundlessgeo.

the class VerifyPatchOp method _call.

/**
     * 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);
}
Also used : FeatureInfo(org.locationtech.geogig.api.FeatureInfo) NodeRef(org.locationtech.geogig.api.NodeRef) Entry(java.util.Map.Entry) RevFeature(org.locationtech.geogig.api.RevFeature) RevFeatureType(org.locationtech.geogig.api.RevFeatureType) PropertyDescriptor(org.opengis.feature.type.PropertyDescriptor) RevObject(org.locationtech.geogig.api.RevObject) ObjectId(org.locationtech.geogig.api.ObjectId) DepthSearch(org.locationtech.geogig.repository.DepthSearch) RevObjectParse(org.locationtech.geogig.api.plumbing.RevObjectParse) RevObject(org.locationtech.geogig.api.RevObject)

Example 72 with RevObject

use of org.locationtech.geogig.api.RevObject in project GeoGig by boundlessgeo.

the class ReportCommitConflictsOp method _call.

@Override
protected MergeScenarioReport _call() {
    MergeScenarioReport report = new MergeScenarioReport();
    ObjectId parentCommitId = ObjectId.NULL;
    if (commit.getParentIds().size() > 0) {
        parentCommitId = commit.getParentIds().get(0);
    }
    ObjectId parentTreeId = ObjectId.NULL;
    Repository repository = repository();
    if (repository.commitExists(parentCommitId)) {
        parentTreeId = repository.getCommit(parentCommitId).getTreeId();
    }
    // get changes
    Iterator<DiffEntry> diffs = command(DiffTree.class).setOldTree(parentTreeId).setNewTree(commit.getTreeId()).setReportTrees(true).call();
    while (diffs.hasNext()) {
        DiffEntry diff = diffs.next();
        String path = diff.oldPath() == null ? diff.newPath() : diff.oldPath();
        Optional<RevObject> obj = command(RevObjectParse.class).setRefSpec(Ref.HEAD + ":" + path).call();
        switch(diff.changeType()) {
            case ADDED:
                if (obj.isPresent()) {
                    TYPE type = command(ResolveObjectType.class).setObjectId(diff.getNewObject().objectId()).call();
                    if (TYPE.TREE.equals(type)) {
                        NodeRef headVersion = command(FindTreeChild.class).setChildPath(path).setParent(repository.getOrCreateHeadTree()).call().get();
                        if (!headVersion.getMetadataId().equals(diff.getNewObject().getMetadataId())) {
                            report.addConflict(new Conflict(path, ObjectId.NULL, diff.getNewObject().getMetadataId(), headVersion.getMetadataId()));
                        }
                    } else {
                        if (!obj.get().getId().equals(diff.newObjectId())) {
                            report.addConflict(new Conflict(path, ObjectId.NULL, diff.newObjectId(), obj.get().getId()));
                        }
                    }
                } else {
                    report.addUnconflicted(diff);
                }
                break;
            case REMOVED:
                if (obj.isPresent()) {
                    if (obj.get().getId().equals(diff.oldObjectId())) {
                        report.addUnconflicted(diff);
                    } else {
                        report.addConflict(new Conflict(path, diff.oldObjectId(), ObjectId.NULL, obj.get().getId()));
                    }
                }
                break;
            case MODIFIED:
                TYPE type = command(ResolveObjectType.class).setObjectId(diff.getNewObject().objectId()).call();
                if (TYPE.TREE.equals(type)) {
                    // one
                    if (!diff.isChange()) {
                        report.addUnconflicted(diff);
                    }
                } else {
                    String refSpec = Ref.HEAD + ":" + path;
                    obj = command(RevObjectParse.class).setRefSpec(refSpec).call();
                    if (!obj.isPresent()) {
                        // git reports this as a conflict but does not mark as conflicted, just adds
                        // the missing file.
                        // We add it and consider it unconflicted
                        report.addUnconflicted(diff);
                        break;
                    }
                    RevFeature feature = (RevFeature) obj.get();
                    DepthSearch depthSearch = new DepthSearch(repository.objectDatabase());
                    Optional<NodeRef> noderef = depthSearch.find(this.workingTree().getTree(), path);
                    RevFeatureType featureType = command(RevObjectParse.class).setObjectId(noderef.get().getMetadataId()).call(RevFeatureType.class).get();
                    ImmutableList<PropertyDescriptor> descriptors = featureType.sortedDescriptors();
                    FeatureDiff featureDiff = command(DiffFeature.class).setOldVersion(Suppliers.ofInstance(diff.getOldObject())).setNewVersion(Suppliers.ofInstance(diff.getNewObject())).call();
                    Set<Entry<PropertyDescriptor, AttributeDiff>> attrDiffs = featureDiff.getDiffs().entrySet();
                    RevFeature newFeature = command(RevObjectParse.class).setObjectId(diff.newObjectId()).call(RevFeature.class).get();
                    boolean ok = true;
                    for (Iterator<Entry<PropertyDescriptor, AttributeDiff>> iterator = attrDiffs.iterator(); iterator.hasNext() && ok; ) {
                        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);
                                        Optional<Object> newValue = newFeature.getValues().get(i);
                                        if (!newValue.equals(value)) {
                                            // check
                                            if (!attrDiff.canBeAppliedOn(value)) {
                                                ok = false;
                                            }
                                            break;
                                        }
                                    }
                                }
                        }
                    }
                    if (ok) {
                        report.addUnconflicted(diff);
                    } else {
                        report.addConflict(new Conflict(path, diff.oldObjectId(), diff.newObjectId(), obj.get().getId()));
                    }
                }
                break;
        }
    }
    return report;
}
Also used : NodeRef(org.locationtech.geogig.api.NodeRef) FeatureDiff(org.locationtech.geogig.api.plumbing.diff.FeatureDiff) DiffEntry(org.locationtech.geogig.api.plumbing.diff.DiffEntry) Entry(java.util.Map.Entry) RevFeature(org.locationtech.geogig.api.RevFeature) AttributeDiff(org.locationtech.geogig.api.plumbing.diff.AttributeDiff) TYPE(org.locationtech.geogig.api.RevObject.TYPE) RevFeatureType(org.locationtech.geogig.api.RevFeatureType) DiffEntry(org.locationtech.geogig.api.plumbing.diff.DiffEntry) PropertyDescriptor(org.opengis.feature.type.PropertyDescriptor) ObjectId(org.locationtech.geogig.api.ObjectId) RevObject(org.locationtech.geogig.api.RevObject) DiffFeature(org.locationtech.geogig.api.plumbing.DiffFeature) Repository(org.locationtech.geogig.repository.Repository) DepthSearch(org.locationtech.geogig.repository.DepthSearch) RevObjectParse(org.locationtech.geogig.api.plumbing.RevObjectParse) RevObject(org.locationtech.geogig.api.RevObject)

Example 73 with RevObject

use of org.locationtech.geogig.api.RevObject in project GeoGig by boundlessgeo.

the class PreOrderDiffWalk method traverseLeafBucket.

/**
     * Compares a bucket tree (i.e. its size is greater than {@link RevTree#NORMALIZED_SIZE_LIMIT}
     * and hence has been split into buckets) at the right side of the comparison, and a the
     * {@link RevTree#children() children} nodes of a leaf tree at the left side of the comparison.
     * <p>
     * This happens when the right tree is much larger than the left tree
     * <p>
     * This traversal is symmetric to {@link #traverseBucketLeaf} so be careful that any change made
     * to this method shall have a matching change at {@link #traverseBucketLeaf}
     * 
     * @precondition {@code right.buckets().isPresent()}
     */
private void traverseLeafBucket(final Consumer consumer, final Iterator<Node> left, final RevTree right, final int bucketDepth) {
    checkState(right.buckets().isPresent());
    final SortedMap<Integer, Bucket> rightBuckets = right.buckets().get();
    final ListMultimap<Integer, Node> nodesByBucket = splitNodesToBucketsAtDepth(left, bucketDepth);
    final SortedSet<Integer> bucketIndexes = Sets.newTreeSet(Sets.union(rightBuckets.keySet(), nodesByBucket.keySet()));
    // get all buckets at once, to leverage ObjectDatabase optimizations
    final Map<ObjectId, RevObject> bucketTrees;
    bucketTrees = uniqueIndex(rightSource.getAll(transform(rightBuckets.values(), BUCKET_ID)), OBJECT_ID);
    for (Integer bucketIndex : bucketIndexes) {
        Bucket rightBucket = rightBuckets.get(bucketIndex);
        // never returns null, but empty
        List<Node> leftNodes = nodesByBucket.get(bucketIndex);
        if (null == rightBucket) {
            traverseLeafLeaf(consumer, leftNodes.iterator(), Iterators.<Node>emptyIterator());
        } else if (leftNodes.isEmpty()) {
            if (consumer.bucket(bucketIndex, bucketDepth, null, rightBucket)) {
                RevTree rightTree = (RevTree) bucketTrees.get(rightBucket.id());
                // traverseBucketBucket(consumer, RevTree.EMPTY, rightTree, bucketDepth);
                traverseTree(consumer, RevTree.EMPTY, rightTree, bucketDepth + 1);
            }
            consumer.endBucket(bucketIndex, bucketDepth, null, rightBucket);
        } else {
            RevTree rightTree = (RevTree) bucketTrees.get(rightBucket.id());
            if (rightTree.buckets().isPresent()) {
                traverseLeafBucket(consumer, leftNodes.iterator(), rightTree, bucketDepth + 1);
            } else {
                traverseLeafLeaf(consumer, leftNodes.iterator(), rightTree.children());
            }
        }
    }
}
Also used : Bucket(org.locationtech.geogig.api.Bucket) ObjectId(org.locationtech.geogig.api.ObjectId) RevObject(org.locationtech.geogig.api.RevObject) Node(org.locationtech.geogig.api.Node) RevTree(org.locationtech.geogig.api.RevTree)

Example 74 with RevObject

use of org.locationtech.geogig.api.RevObject in project GeoGig by boundlessgeo.

the class PreOrderDiffWalk method traverseBucketLeaf.

/**
     * Compares a bucket tree (i.e. its size is greater than {@link RevTree#NORMALIZED_SIZE_LIMIT}
     * and hence has been split into buckets) at the left side of the comparison, and a the
     * {@link RevTree#children() children} nodes of a leaf tree at the right side of the comparison.
     * <p>
     * This happens when the left tree is much larger than the right tree
     * <p>
     * This traversal is symmetric to {@link #traverseLeafBucket} so be careful that any change made
     * to this method shall have a matching change at {@link #traverseLeafBucket}
     * 
     * @precondition {@code left.buckets().isPresent()}
     */
private void traverseBucketLeaf(final Consumer consumer, final RevTree left, final Iterator<Node> right, final int bucketDepth) {
    checkState(left.buckets().isPresent());
    final SortedMap<Integer, Bucket> leftBuckets = left.buckets().get();
    final ListMultimap<Integer, Node> nodesByBucket = splitNodesToBucketsAtDepth(right, bucketDepth);
    final SortedSet<Integer> bucketIndexes = Sets.newTreeSet(Sets.union(leftBuckets.keySet(), nodesByBucket.keySet()));
    // get all buckets at once, to leverage ObjectDatabase optimizations
    final Map<ObjectId, RevObject> bucketTrees;
    bucketTrees = uniqueIndex(leftSource.getAll(transform(leftBuckets.values(), BUCKET_ID)), OBJECT_ID);
    for (Integer bucketIndex : bucketIndexes) {
        Bucket leftBucket = leftBuckets.get(bucketIndex);
        // never returns null, but empty
        List<Node> rightNodes = nodesByBucket.get(bucketIndex);
        if (null == leftBucket) {
            traverseLeafLeaf(consumer, Iterators.<Node>emptyIterator(), rightNodes.iterator());
        } else if (rightNodes.isEmpty()) {
            if (consumer.bucket(bucketIndex, bucketDepth, leftBucket, null)) {
                RevTree leftTree = (RevTree) bucketTrees.get(leftBucket.id());
                // traverseBucketBucket(consumer, leftTree, RevTree.EMPTY, bucketDepth);
                traverseTree(consumer, leftTree, RevTree.EMPTY, bucketDepth + 1);
            }
            consumer.endBucket(bucketIndex, bucketDepth, leftBucket, null);
        } else {
            RevTree leftTree = (RevTree) bucketTrees.get(leftBucket.id());
            if (leftTree.buckets().isPresent()) {
                traverseBucketLeaf(consumer, leftTree, rightNodes.iterator(), bucketDepth + 1);
            } else {
                traverseLeafLeaf(consumer, leftTree.children(), rightNodes.iterator());
            }
        }
    }
}
Also used : Bucket(org.locationtech.geogig.api.Bucket) ObjectId(org.locationtech.geogig.api.ObjectId) RevObject(org.locationtech.geogig.api.RevObject) Node(org.locationtech.geogig.api.Node) RevTree(org.locationtech.geogig.api.RevTree)

Example 75 with RevObject

use of org.locationtech.geogig.api.RevObject in project GeoGig by boundlessgeo.

the class Patch method toString.

/**
     * This method is not intended to serialize the patch, as it misses some needed information. To
     * serialize the patch, use the {@link PatchSerializer} class instead. Use this method to show
     * patch content in a human-readable format
     */
@Override
public String toString() {
    TextSerializationFactory factory = new TextSerializationFactory();
    StringBuilder sb = new StringBuilder();
    for (FeatureInfo feature : addedFeatures) {
        String path = feature.getPath();
        sb.append("A\t" + path + "\t" + feature.getFeatureType().getId() + "\n");
        ObjectWriter<RevObject> writer = factory.createObjectWriter(TYPE.FEATURE);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        RevFeature revFeature = RevFeatureBuilder.build(feature.getFeature());
        try {
            writer.write(revFeature, output);
        } catch (IOException e) {
        }
        sb.append(output.toString());
        sb.append('\n');
    }
    for (FeatureInfo feature : removedFeatures) {
        String path = feature.getPath();
        sb.append("R\t" + path + "\t" + feature.getFeatureType().getId() + "\n");
        ObjectWriter<RevObject> writer = factory.createObjectWriter(TYPE.FEATURE);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        RevFeature revFeature = RevFeatureBuilder.build(feature.getFeature());
        try {
            writer.write(revFeature, output);
        } catch (IOException e) {
        }
        sb.append(output.toString());
        sb.append('\n');
    }
    for (FeatureDiff diff : modifiedFeatures) {
        sb.append("M\t" + diff.getPath() + /*
                                              * + "\t" + diff.getOldFeatureType().getId().toString()
                                              * + "\t" + diff.getNewFeatureType().getId().toString()
                                              */
        "\n");
        sb.append(diff.toString() + "\n");
    }
    for (FeatureTypeDiff diff : alteredTrees) {
        sb.append(featureTypeDiffAsString(diff) + "\n");
    }
    return sb.toString();
}
Also used : TextSerializationFactory(org.locationtech.geogig.storage.text.TextSerializationFactory) RevObject(org.locationtech.geogig.api.RevObject) FeatureInfo(org.locationtech.geogig.api.FeatureInfo) RevFeature(org.locationtech.geogig.api.RevFeature) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException)

Aggregations

RevObject (org.locationtech.geogig.api.RevObject)84 ObjectId (org.locationtech.geogig.api.ObjectId)51 RevCommit (org.locationtech.geogig.api.RevCommit)30 NodeRef (org.locationtech.geogig.api.NodeRef)22 RevFeatureType (org.locationtech.geogig.api.RevFeatureType)22 RevTree (org.locationtech.geogig.api.RevTree)21 Test (org.junit.Test)18 ArrayList (java.util.ArrayList)17 RevFeature (org.locationtech.geogig.api.RevFeature)17 RevObjectParse (org.locationtech.geogig.api.plumbing.RevObjectParse)16 Feature (org.opengis.feature.Feature)16 IOException (java.io.IOException)15 LinkedList (java.util.LinkedList)15 LogOp (org.locationtech.geogig.api.porcelain.LogOp)14 GeoGIG (org.locationtech.geogig.api.GeoGIG)13 DiffEntry (org.locationtech.geogig.api.plumbing.diff.DiffEntry)11 HashMap (java.util.HashMap)10 PropertyDescriptor (org.opengis.feature.type.PropertyDescriptor)10 Optional (com.google.common.base.Optional)8 ObjectDatabase (org.locationtech.geogig.storage.ObjectDatabase)8