Search in sources :

Example 76 with RevFeatureType

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

the class MergeFeatureResource method post.

public void post(Representation entity) {
    InputStream input = null;
    try {
        input = getRequest().getEntity().getStream();
        final GeoGIG ggit = getGeogig(getRequest()).get();
        final Reader body = new InputStreamReader(input);
        final JsonParser parser = new JsonParser();
        final JsonElement conflictJson = parser.parse(body);
        if (conflictJson.isJsonObject()) {
            final JsonObject conflict = conflictJson.getAsJsonObject();
            String featureId = null;
            RevFeature ourFeature = null;
            RevFeatureType ourFeatureType = null;
            RevFeature theirFeature = null;
            RevFeatureType theirFeatureType = null;
            JsonObject merges = null;
            if (conflict.has("path") && conflict.get("path").isJsonPrimitive()) {
                featureId = conflict.get("path").getAsJsonPrimitive().getAsString();
            }
            Preconditions.checkState(featureId != null);
            if (conflict.has("ours") && conflict.get("ours").isJsonPrimitive()) {
                String ourCommit = conflict.get("ours").getAsJsonPrimitive().getAsString();
                Optional<NodeRef> ourNode = parseID(ObjectId.valueOf(ourCommit), featureId, ggit);
                if (ourNode.isPresent()) {
                    Optional<RevObject> object = ggit.command(RevObjectParse.class).setObjectId(ourNode.get().objectId()).call();
                    Preconditions.checkState(object.isPresent() && object.get() instanceof RevFeature);
                    ourFeature = (RevFeature) object.get();
                    object = ggit.command(RevObjectParse.class).setObjectId(ourNode.get().getMetadataId()).call();
                    Preconditions.checkState(object.isPresent() && object.get() instanceof RevFeatureType);
                    ourFeatureType = (RevFeatureType) object.get();
                }
            }
            if (conflict.has("theirs") && conflict.get("theirs").isJsonPrimitive()) {
                String theirCommit = conflict.get("theirs").getAsJsonPrimitive().getAsString();
                Optional<NodeRef> theirNode = parseID(ObjectId.valueOf(theirCommit), featureId, ggit);
                if (theirNode.isPresent()) {
                    Optional<RevObject> object = ggit.command(RevObjectParse.class).setObjectId(theirNode.get().objectId()).call();
                    Preconditions.checkState(object.isPresent() && object.get() instanceof RevFeature);
                    theirFeature = (RevFeature) object.get();
                    object = ggit.command(RevObjectParse.class).setObjectId(theirNode.get().getMetadataId()).call();
                    Preconditions.checkState(object.isPresent() && object.get() instanceof RevFeatureType);
                    theirFeatureType = (RevFeatureType) object.get();
                }
            }
            if (conflict.has("merges") && conflict.get("merges").isJsonObject()) {
                merges = conflict.get("merges").getAsJsonObject();
            }
            Preconditions.checkState(merges != null);
            Preconditions.checkState(ourFeatureType != null || theirFeatureType != null);
            SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder((SimpleFeatureType) (ourFeatureType != null ? ourFeatureType.type() : theirFeatureType.type()));
            ImmutableList<PropertyDescriptor> descriptors = (ourFeatureType == null ? theirFeatureType : ourFeatureType).sortedDescriptors();
            for (Entry<String, JsonElement> entry : merges.entrySet()) {
                int descriptorIndex = getDescriptorIndex(entry.getKey(), descriptors);
                if (descriptorIndex != -1 && entry.getValue().isJsonObject()) {
                    PropertyDescriptor descriptor = descriptors.get(descriptorIndex);
                    JsonObject attributeObject = entry.getValue().getAsJsonObject();
                    if (attributeObject.has("ours") && attributeObject.get("ours").isJsonPrimitive() && attributeObject.get("ours").getAsBoolean()) {
                        featureBuilder.set(descriptor.getName(), ourFeature == null ? null : ourFeature.getValues().get(descriptorIndex).orNull());
                    } else if (attributeObject.has("theirs") && attributeObject.get("theirs").isJsonPrimitive() && attributeObject.get("theirs").getAsBoolean()) {
                        featureBuilder.set(descriptor.getName(), theirFeature == null ? null : theirFeature.getValues().get(descriptorIndex).orNull());
                    } else if (attributeObject.has("value") && attributeObject.get("value").isJsonPrimitive()) {
                        JsonPrimitive primitive = attributeObject.get("value").getAsJsonPrimitive();
                        if (primitive.isString()) {
                            try {
                                Object object = valueFromString(FieldType.forBinding(descriptor.getType().getBinding()), primitive.getAsString());
                                featureBuilder.set(descriptor.getName(), object);
                            } catch (Exception e) {
                                throw new Exception("Unable to convert attribute (" + entry.getKey() + ") to required type: " + descriptor.getType().getBinding().toString());
                            }
                        } else if (primitive.isNumber()) {
                            try {
                                Object value = valueFromNumber(FieldType.forBinding(descriptor.getType().getBinding()), primitive.getAsNumber());
                                featureBuilder.set(descriptor.getName(), value);
                            } catch (Exception e) {
                                throw new Exception("Unable to convert attribute (" + entry.getKey() + ") to required type: " + descriptor.getType().getBinding().toString());
                            }
                        } else if (primitive.isBoolean()) {
                            try {
                                Object value = valueFromBoolean(FieldType.forBinding(descriptor.getType().getBinding()), primitive.getAsBoolean());
                                featureBuilder.set(descriptor.getName(), value);
                            } catch (Exception e) {
                                throw new Exception("Unable to convert attribute (" + entry.getKey() + ") to required type: " + descriptor.getType().getBinding().toString());
                            }
                        } else if (primitive.isJsonNull()) {
                            featureBuilder.set(descriptor.getName(), null);
                        } else {
                            throw new Exception("Unsupported JSON type for attribute value (" + entry.getKey() + ")");
                        }
                    }
                }
            }
            SimpleFeature feature = featureBuilder.buildFeature(NodeRef.nodeFromPath(featureId));
            RevFeature revFeature = RevFeatureBuilder.build(feature);
            ggit.getRepository().stagingDatabase().put(revFeature);
            getResponse().setEntity(new StringRepresentation(revFeature.getId().toString(), MediaType.TEXT_PLAIN));
        }
    } catch (Exception e) {
        throw new RestletException(e.getMessage(), Status.SERVER_ERROR_INTERNAL, e);
    } finally {
        if (input != null)
            Closeables.closeQuietly(input);
    }
}
Also used : JsonPrimitive(com.google.gson.JsonPrimitive) Reader(java.io.Reader) InputStreamReader(java.io.InputStreamReader) JsonObject(com.google.gson.JsonObject) LineString(com.vividsolutions.jts.geom.LineString) MultiLineString(com.vividsolutions.jts.geom.MultiLineString) NodeRef(org.locationtech.geogig.api.NodeRef) StringRepresentation(org.restlet.resource.StringRepresentation) RestletException(org.locationtech.geogig.rest.RestletException) RevFeature(org.locationtech.geogig.api.RevFeature) RevFeatureType(org.locationtech.geogig.api.RevFeatureType) JsonParser(com.google.gson.JsonParser) InputStreamReader(java.io.InputStreamReader) PropertyDescriptor(org.opengis.feature.type.PropertyDescriptor) RevObject(org.locationtech.geogig.api.RevObject) InputStream(java.io.InputStream) Point(com.vividsolutions.jts.geom.Point) MultiPoint(com.vividsolutions.jts.geom.MultiPoint) CommandSpecException(org.locationtech.geogig.web.api.CommandSpecException) RestletException(org.locationtech.geogig.rest.RestletException) IOException(java.io.IOException) SimpleFeature(org.opengis.feature.simple.SimpleFeature) JsonElement(com.google.gson.JsonElement) RevObjectParse(org.locationtech.geogig.api.plumbing.RevObjectParse) JsonObject(com.google.gson.JsonObject) RevObject(org.locationtech.geogig.api.RevObject) GeoGIG(org.locationtech.geogig.api.GeoGIG) SimpleFeatureBuilder(org.geotools.feature.simple.SimpleFeatureBuilder)

Example 77 with RevFeatureType

use of org.locationtech.geogig.api.RevFeatureType 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 78 with RevFeatureType

use of org.locationtech.geogig.api.RevFeatureType 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 79 with RevFeatureType

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

the class ReportMergeScenarioOp method _call.

@Override
protected MergeScenarioReport _call() {
    Optional<ObjectId> ancestor = command(FindCommonAncestor.class).setLeft(toMerge).setRight(mergeInto).call();
    Preconditions.checkState(ancestor.isPresent(), "No ancestor commit could be found.");
    Map<String, DiffEntry> mergeIntoDiffs = Maps.newHashMap();
    MergeScenarioReport report = new MergeScenarioReport();
    Iterator<DiffEntry> diffs = command(DiffTree.class).setOldTree(ancestor.get()).setReportTrees(true).setNewTree(mergeInto.getId()).call();
    while (diffs.hasNext()) {
        DiffEntry diff = diffs.next();
        String path = diff.oldPath() == null ? diff.newPath() : diff.oldPath();
        mergeIntoDiffs.put(path, diff);
    }
    Iterator<DiffEntry> toMergeDiffs = command(DiffTree.class).setOldTree(ancestor.get()).setReportTrees(true).setNewTree(toMerge.getId()).call();
    while (toMergeDiffs.hasNext()) {
        DiffEntry toMergeDiff = toMergeDiffs.next();
        String path = toMergeDiff.oldPath() == null ? toMergeDiff.newPath() : toMergeDiff.oldPath();
        if (mergeIntoDiffs.containsKey(path)) {
            RevCommit ancestorCommit = command(RevObjectParse.class).setRefSpec(ancestor.get().toString()).call(RevCommit.class).get();
            RevTree ancestorTree = command(RevObjectParse.class).setObjectId(ancestorCommit.getTreeId()).call(RevTree.class).get();
            Optional<NodeRef> ancestorVersion = command(FindTreeChild.class).setChildPath(path).setParent(ancestorTree).call();
            ObjectId ancestorVersionId = ancestorVersion.isPresent() ? ancestorVersion.get().getNode().getObjectId() : ObjectId.NULL;
            ObjectId theirs = toMergeDiff.getNewObject() == null ? ObjectId.NULL : toMergeDiff.getNewObject().objectId();
            DiffEntry mergeIntoDiff = mergeIntoDiffs.get(path);
            ObjectId ours = mergeIntoDiff.getNewObject() == null ? ObjectId.NULL : mergeIntoDiff.getNewObject().objectId();
            if (!mergeIntoDiff.changeType().equals(toMergeDiff.changeType())) {
                report.addConflict(new Conflict(path, ancestorVersionId, ours, theirs));
                continue;
            }
            switch(toMergeDiff.changeType()) {
                case ADDED:
                    if (toMergeDiff.getNewObject().equals(mergeIntoDiff.getNewObject())) {
                    // already added in current branch, no need to do anything
                    } else {
                        TYPE type = command(ResolveObjectType.class).setObjectId(toMergeDiff.getNewObject().objectId()).call();
                        if (TYPE.TREE.equals(type)) {
                            boolean conflict = !toMergeDiff.getNewObject().getMetadataId().equals(mergeIntoDiff.getNewObject().getMetadataId());
                            if (conflict) {
                                // In this case, we store the metadata id, not the element id
                                ancestorVersionId = ancestorVersion.isPresent() ? ancestorVersion.get().getMetadataId() : ObjectId.NULL;
                                ours = mergeIntoDiff.getNewObject().getMetadataId();
                                theirs = toMergeDiff.getNewObject().getMetadataId();
                                report.addConflict(new Conflict(path, ancestorVersionId, ours, theirs));
                            }
                        // if the metadata ids match, it means both branches have added the same
                        // tree, maybe with different content, but there is no need to do
                        // anything. The correct tree is already there and the merge can be run
                        // safely, so we do not add it neither as a conflicted change nor as an
                        // unconflicted one
                        } else {
                            report.addConflict(new Conflict(path, ancestorVersionId, ours, theirs));
                        }
                    }
                    break;
                case REMOVED:
                    // removed by both histories => no conflict and no need to do anything
                    break;
                case MODIFIED:
                    TYPE type = command(ResolveObjectType.class).setObjectId(toMergeDiff.getNewObject().objectId()).call();
                    if (TYPE.TREE.equals(type)) {
                        boolean conflict = !toMergeDiff.getNewObject().getMetadataId().equals(mergeIntoDiff.getNewObject().getMetadataId());
                        if (conflict) {
                            // In this case, we store the metadata id, not the element id
                            ancestorVersionId = ancestorVersion.isPresent() ? ancestorVersion.get().getMetadataId() : ObjectId.NULL;
                            ours = mergeIntoDiff.getNewObject().getMetadataId();
                            theirs = toMergeDiff.getNewObject().getMetadataId();
                            report.addConflict(new Conflict(path, ancestorVersionId, ours, theirs));
                        }
                    } else {
                        FeatureDiff toMergeFeatureDiff = command(DiffFeature.class).setOldVersion(Suppliers.ofInstance(toMergeDiff.getOldObject())).setNewVersion(Suppliers.ofInstance(toMergeDiff.getNewObject())).call();
                        FeatureDiff mergeIntoFeatureDiff = command(DiffFeature.class).setOldVersion(Suppliers.ofInstance(mergeIntoDiff.getOldObject())).setNewVersion(Suppliers.ofInstance(mergeIntoDiff.getNewObject())).call();
                        if (toMergeFeatureDiff.conflicts(mergeIntoFeatureDiff)) {
                            report.addConflict(new Conflict(path, ancestorVersionId, ours, theirs));
                        } else {
                            // try to perform automerge
                            if (!toMergeDiff.getNewObject().getMetadataId().equals(mergeIntoDiff.getNewObject().getMetadataId())) {
                                report.addConflict(new Conflict(path, ancestorVersionId, ours, theirs));
                            } else if (!toMergeFeatureDiff.equals(mergeIntoFeatureDiff)) {
                                Feature mergedFeature = command(MergeFeaturesOp.class).setFirstFeature(mergeIntoDiff.getNewObject()).setSecondFeature(toMergeDiff.getNewObject()).setAncestorFeature(mergeIntoDiff.getOldObject()).call();
                                RevFeature revFeature = RevFeatureBuilder.build(mergedFeature);
                                if (revFeature.getId().equals(toMergeDiff.newObjectId())) {
                                    // the resulting merged feature equals the feature to merge from
                                    // the branch, which means that it exists in the repo and there
                                    // is no need to add it
                                    report.addUnconflicted(toMergeDiff);
                                } else {
                                    RevFeatureType featureType = command(RevObjectParse.class).setObjectId(mergeIntoDiff.getNewObject().getMetadataId()).call(RevFeatureType.class).get();
                                    FeatureInfo merged = new FeatureInfo(mergedFeature, featureType, path);
                                    report.addMerged(merged);
                                }
                            }
                        }
                    }
                    break;
            }
        } else {
            // modified in the other branch under it.
            if (ChangeType.REMOVED.equals(toMergeDiff.changeType())) {
                TYPE type = command(ResolveObjectType.class).setObjectId(toMergeDiff.oldObjectId()).call();
                if (TYPE.TREE.equals(type)) {
                    String parentPath = toMergeDiff.oldPath();
                    Set<Entry<String, DiffEntry>> entries = mergeIntoDiffs.entrySet();
                    boolean conflict = false;
                    for (Entry<String, DiffEntry> entry : entries) {
                        if (entry.getKey().startsWith(parentPath)) {
                            if (!ChangeType.REMOVED.equals(entry.getValue().changeType())) {
                                RevCommit ancestorCommit = command(RevObjectParse.class).setRefSpec(ancestor.get().toString()).call(RevCommit.class).get();
                                RevTree ancestorTree = command(RevObjectParse.class).setObjectId(ancestorCommit.getTreeId()).call(RevTree.class).get();
                                Optional<NodeRef> ancestorVersion = command(FindTreeChild.class).setChildPath(path).setParent(ancestorTree).call();
                                ObjectId ancestorVersionId = ancestorVersion.isPresent() ? ancestorVersion.get().getNode().getObjectId() : ObjectId.NULL;
                                ObjectId theirs = toMergeDiff.getNewObject() == null ? ObjectId.NULL : toMergeDiff.getNewObject().objectId();
                                String oursRefSpec = mergeInto.getId().toString() + ":" + parentPath;
                                Optional<ObjectId> ours = command(RevParse.class).setRefSpec(oursRefSpec).call();
                                report.addConflict(new Conflict(path, ancestorVersionId, ours.get(), theirs));
                                conflict = true;
                                break;
                            }
                        }
                    }
                    if (!conflict) {
                        report.addUnconflicted(toMergeDiff);
                    }
                } else {
                    report.addUnconflicted(toMergeDiff);
                }
            } else {
                report.addUnconflicted(toMergeDiff);
            }
        }
    }
    return report;
}
Also used : FeatureInfo(org.locationtech.geogig.api.FeatureInfo) RevFeature(org.locationtech.geogig.api.RevFeature) DiffFeature(org.locationtech.geogig.api.plumbing.DiffFeature) Feature(org.opengis.feature.Feature) 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) TYPE(org.locationtech.geogig.api.RevObject.TYPE) RevFeatureType(org.locationtech.geogig.api.RevFeatureType) DiffEntry(org.locationtech.geogig.api.plumbing.diff.DiffEntry) RevCommit(org.locationtech.geogig.api.RevCommit) ObjectId(org.locationtech.geogig.api.ObjectId) DiffFeature(org.locationtech.geogig.api.plumbing.DiffFeature) FindTreeChild(org.locationtech.geogig.api.plumbing.FindTreeChild) FindCommonAncestor(org.locationtech.geogig.api.plumbing.FindCommonAncestor) RevObjectParse(org.locationtech.geogig.api.plumbing.RevObjectParse) RevTree(org.locationtech.geogig.api.RevTree)

Example 80 with RevFeatureType

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

the class PatchSerializer method write.

public static void write(Writer w, Patch patch) throws IOException {
    StringBuilder sb = new StringBuilder();
    List<RevFeatureType> featureTypes = patch.getFeatureTypes();
    for (RevFeatureType featureType : featureTypes) {
        ObjectWriter<RevObject> writer = factory.createObjectWriter(TYPE.FEATURETYPE);
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        writer.write(featureType, output);
        sb.append(output.toString());
        sb.append('\n');
    }
    TextSerializationFactory factory = new TextSerializationFactory();
    for (FeatureInfo feature : patch.getAddedFeatures()) {
        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 : patch.getRemovedFeatures()) {
        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 : patch.getModifiedFeatures()) {
        sb.append("M\t" + diff.getPath() + "\t" + diff.getOldFeatureType().getId().toString() + "\t" + diff.getNewFeatureType().getId().toString() + "\n");
        sb.append(diff.asText() + "\n");
    }
    for (FeatureTypeDiff diff : patch.getAlteredTrees()) {
        sb.append(diff.toString() + "\n");
    }
    w.write(sb.toString());
    w.flush();
}
Also used : TextSerializationFactory(org.locationtech.geogig.storage.text.TextSerializationFactory) RevObject(org.locationtech.geogig.api.RevObject) FeatureInfo(org.locationtech.geogig.api.FeatureInfo) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException) RevFeature(org.locationtech.geogig.api.RevFeature) RevFeatureType(org.locationtech.geogig.api.RevFeatureType)

Aggregations

RevFeatureType (org.locationtech.geogig.api.RevFeatureType)88 RevFeature (org.locationtech.geogig.api.RevFeature)49 NodeRef (org.locationtech.geogig.api.NodeRef)40 ObjectId (org.locationtech.geogig.api.ObjectId)34 Test (org.junit.Test)31 Optional (com.google.common.base.Optional)28 RevObjectParse (org.locationtech.geogig.api.plumbing.RevObjectParse)26 RevObject (org.locationtech.geogig.api.RevObject)24 RevTree (org.locationtech.geogig.api.RevTree)24 PropertyDescriptor (org.opengis.feature.type.PropertyDescriptor)22 SimpleFeature (org.opengis.feature.simple.SimpleFeature)19 SimpleFeatureType (org.opengis.feature.simple.SimpleFeatureType)17 DiffEntry (org.locationtech.geogig.api.plumbing.diff.DiffEntry)14 ImmutableList (com.google.common.collect.ImmutableList)13 File (java.io.File)13 SimpleFeatureBuilder (org.geotools.feature.simple.SimpleFeatureBuilder)13 FeatureBuilder (org.locationtech.geogig.api.FeatureBuilder)13 List (java.util.List)12 GeoGIG (org.locationtech.geogig.api.GeoGIG)12 AddOp (org.locationtech.geogig.api.porcelain.AddOp)12