@Test public void testPartialApplication() throws Exception { insert(points1, points2); Patch patch = new Patch(); String pathRemove = NodeRef.appendChild(pointsName, points2.getIdentifier().getID()); patch.addRemovedFeature(pathRemove, points2, RevFeatureType.build(pointsType)); String pathModify = NodeRef.appendChild(pointsName, points1B.getIdentifier().getID()); Map<PropertyDescriptor, AttributeDiff> map = Maps.newHashMap(); Optional<?> oldValue = Optional.fromNullable(points1B.getProperty("extra").getValue()); GenericAttributeDiffImpl diff = new GenericAttributeDiffImpl(oldValue, null); map.put(modifiedPointsType.getDescriptor("extra"), diff); FeatureDiff featureDiff = new FeatureDiff( pathModify, map, RevFeatureType.build(modifiedPointsType), RevFeatureType.build(pointsType)); patch.addModifiedFeature(featureDiff); Patch rejected = geogit.command(ApplyPatchOp.class).setPatch(patch).setApplyPartial(true).call(); assertFalse(rejected.isEmpty()); RevTree root = repo.getWorkingTree().getTree(); assertNotNull(root); Optional<Node> featureBlobId = findTreeChild(root, pathRemove); assertFalse(featureBlobId.isPresent()); // now we take the rejected patch and apply it, and the new rejected should be identical to // it Patch newRejected = geogit.command(ApplyPatchOp.class).setPatch(rejected).setApplyPartial(true).call(); assertEquals(rejected, newRejected); }
@Test public void testReversedPatch() throws Exception { insert(points1, points2); Patch patch = new Patch(); String path = NodeRef.appendChild(pointsName, points1.getIdentifier().getID()); Map<PropertyDescriptor, AttributeDiff> map = Maps.newHashMap(); Optional<?> oldValue = Optional.fromNullable(points1.getProperty("sp").getValue()); GenericAttributeDiffImpl diff = new GenericAttributeDiffImpl(oldValue, Optional.of("new")); map.put(pointsType.getDescriptor("sp"), diff); FeatureDiff feaureDiff = new FeatureDiff( path, map, RevFeatureType.build(pointsType), RevFeatureType.build(pointsType)); patch.addModifiedFeature(feaureDiff); String removedPath = NodeRef.appendChild(pointsName, points2.getIdentifier().getID()); patch.addRemovedFeature(removedPath, points2, RevFeatureType.build(pointsType)); String addedPath = NodeRef.appendChild(pointsName, points3.getIdentifier().getID()); patch.addAddedFeature(addedPath, points3, RevFeatureType.build(pointsType)); geogit.command(ApplyPatchOp.class).setPatch(patch).call(); geogit.command(ApplyPatchOp.class).setPatch(patch.reversed()).call(); RevTree root = repo.getWorkingTree().getTree(); Optional<Node> featureBlobId = findTreeChild(root, removedPath); assertTrue(featureBlobId.isPresent()); featureBlobId = findTreeChild(root, addedPath); assertFalse(featureBlobId.isPresent()); Optional<RevFeature> feature = geogit.command(RevObjectParse.class).setRefSpec("WORK_HEAD:" + path).call(RevFeature.class); assertTrue(feature.isPresent()); assertEquals(oldValue, feature.get().getValues().get(0)); }
private ObjectId writeBack( RevTreeBuilder ancestor, final String ancestorPath, final RevTree childTree, final String childPath, final ObjectDatabase targetDatabase) { final ObjectId treeId = childTree.getId(); targetDatabase.put(childTree); final boolean isDirectChild = NodeRef.isDirectChild(ancestorPath, childPath); if (isDirectChild) { ObjectId metadataId = ObjectId.NULL; ancestor.put(new Node(childPath, treeId, metadataId, TYPE.TREE)); RevTree newAncestor = ancestor.build(); targetDatabase.put(newAncestor); return newAncestor.getId(); } final String parentPath = NodeRef.parentPath(childPath); Optional<Node> parentRef = getTreeChild(ancestor, parentPath); RevTreeBuilder parentBuilder; if (parentRef.isPresent()) { ObjectId parentId = parentRef.get().getObjectId(); parentBuilder = getTree(parentId).builder(targetdb); } else { parentBuilder = RevTree.EMPTY.builder(targetDatabase); } parentBuilder.put(new Node(NodeRef.nodeFromPath(childPath), treeId, ObjectId.NULL, TYPE.TREE)); RevTree parent = parentBuilder.build(); return writeBack(ancestor, ancestorPath, parent, parentPath, targetDatabase); }
/** * Translates a feature pointed by a node from its original feature type to a given one, using * values from those attributes that exist in both original and destination feature type. New * attributes are populated with null values * * @param node The node that points to the feature. No checking is performed to ensure the node * points to a feature instead of other type * @param featureType the destination feature type * @return a feature with the passed feature type and data taken from the input feature */ private Feature alter(NodeRef node, RevFeatureType featureType) { RevFeature oldFeature = command(RevObjectParse.class).setObjectId(node.objectId()).call(RevFeature.class).get(); RevFeatureType oldFeatureType; oldFeatureType = command(RevObjectParse.class) .setObjectId(node.getMetadataId()) .call(RevFeatureType.class) .get(); ImmutableList<PropertyDescriptor> oldAttributes = oldFeatureType.sortedDescriptors(); ImmutableList<PropertyDescriptor> newAttributes = featureType.sortedDescriptors(); ImmutableList<Optional<Object>> oldValues = oldFeature.getValues(); List<Optional<Object>> newValues = Lists.newArrayList(); for (int i = 0; i < newAttributes.size(); i++) { int idx = oldAttributes.indexOf(newAttributes.get(i)); if (idx != -1) { Optional<Object> oldValue = oldValues.get(idx); newValues.add(oldValue); } else { newValues.add(Optional.absent()); } } RevFeature newFeature = RevFeature.build(ImmutableList.copyOf(newValues)); FeatureBuilder featureBuilder = new FeatureBuilder(featureType); Feature feature = featureBuilder.build(node.name(), newFeature); return feature; }
/** Provides for natural ordering of {@code NodeRef}, based on {@link #path()} */ @Override public int compareTo(NodeRef o) { int c = parentPath.compareTo(o.getParentPath()); if (c == 0) { return node.compareTo(o.getNode()); } return c; }
/** * Tests equality over another {@code NodeRef} based on {@link #getParentPath() parent path}, * {@link #getNode() node} name and id, and {@link #getMetadataId()} */ @Override public boolean equals(Object o) { if (!(o instanceof NodeRef)) { return false; } NodeRef r = (NodeRef) o; return parentPath.equals(r.parentPath) && node.equals(r.node) && getMetadataId().equals(r.getMetadataId()); }
@Test public void testModifyFeatureAttributePatch() throws Exception { insert(points1); Patch patch = new Patch(); String path = NodeRef.appendChild(pointsName, points1.getIdentifier().getID()); Map<PropertyDescriptor, AttributeDiff> map = Maps.newHashMap(); Optional<?> oldValue = Optional.fromNullable(points1.getProperty("sp").getValue()); GenericAttributeDiffImpl diff = new GenericAttributeDiffImpl(oldValue, Optional.of("new")); map.put(pointsType.getDescriptor("sp"), diff); FeatureDiff feaureDiff = new FeatureDiff( path, map, RevFeatureType.build(pointsType), RevFeatureType.build(pointsType)); patch.addModifiedFeature(feaureDiff); geogit.command(ApplyPatchOp.class).setPatch(patch).call(); RevTree root = repo.getWorkingTree().getTree(); Optional<Node> featureBlobId = findTreeChild(root, path); assertTrue(featureBlobId.isPresent()); Iterator<DiffEntry> unstaged = repo.getWorkingTree().getUnstaged(pointsName); ArrayList<DiffEntry> diffs = Lists.newArrayList(unstaged); assertEquals(2, diffs.size()); Optional<RevFeature> feature = geogit.command(RevObjectParse.class).setRefSpec("WORK_HEAD:" + path).call(RevFeature.class); assertTrue(feature.isPresent()); ImmutableList<Optional<Object>> values = feature.get().getValues(); assertEquals("new", values.get(0).get()); }
@Test public void testRemovedFeatureDoesNotExists() throws Exception { Patch patch = new Patch(); String path = NodeRef.appendChild(pointsName, points1.getIdentifier().getID()); patch.addRemovedFeature(path, points1, RevFeatureType.build(pointsType)); try { geogit.command(ApplyPatchOp.class).setPatch(patch).call(); fail(); } catch (CannotApplyPatchException e) { assertTrue(true); } }
@Test public void testRemoveFeaturePatch() throws Exception { insert(points1); Patch patch = new Patch(); String path = NodeRef.appendChild(pointsName, points1.getIdentifier().getID()); patch.addRemovedFeature(path, points1, RevFeatureType.build(pointsType)); geogit.command(ApplyPatchOp.class).setPatch(patch).call(); RevTree root = repo.getWorkingTree().getTree(); assertNotNull(root); Optional<Node> featureBlobId = findTreeChild(root, path); assertFalse(featureBlobId.isPresent()); }
@Test public void testAddFeatureWithNonDefaultFeatureType() throws Exception { insert(points2, points3); Patch patch = new Patch(); String path = NodeRef.appendChild(pointsName, points1.getIdentifier().getID()); patch.addAddedFeature(path, points1B, RevFeatureType.build(modifiedPointsType)); geogit.command(ApplyPatchOp.class).setPatch(patch).call(); RevTree root = repo.getWorkingTree().getTree(); assertNotNull(root); Optional<Node> typeTreeId = findTreeChild(root, pointsName); assertEquals(typeTreeId.get().getMetadataId().get(), RevFeatureType.build(pointsType).getId()); RevTree typeTree = repo.getTree(typeTreeId.get().getObjectId()); assertNotNull(typeTree); Optional<Node> featureBlobId = findTreeChild(root, path); assertEquals( RevFeatureType.build(modifiedPointsType).getId(), featureBlobId.get().getMetadataId().orNull()); assertTrue(featureBlobId.isPresent()); path = NodeRef.appendChild(pointsName, points3.getIdentifier().getID()); featureBlobId = findTreeChild(root, path); assertEquals(null, featureBlobId.get().getMetadataId().orNull()); }
@Test public void testModifiedFeatureType() throws Exception { insert(points2, points3, points1B); Patch patch = new Patch(); RevFeatureType oldFeatureType = RevFeatureType.build(pointsType); RevFeatureType featureType = RevFeatureType.build(modifiedPointsType); patch.addFeatureType(featureType); patch.addAlteredTree( new FeatureTypeDiff(pointsName, oldFeatureType.getId(), featureType.getId())); geogit.command(ApplyPatchOp.class).setPatch(patch).call(); RevTree root = repo.getWorkingTree().getTree(); assertNotNull(root); Optional<Node> typeTree = findTreeChild(root, pointsName); assertTrue(typeTree.isPresent()); assertEquals(featureType.getId(), typeTree.get().getMetadataId().get()); Optional<Node> featureNode = findTreeChild(root, NodeRef.appendChild(pointsName, idP2)); assertTrue(featureNode.isPresent()); assertEquals(oldFeatureType.getId(), featureNode.get().getMetadataId().get()); featureNode = findTreeChild(root, NodeRef.appendChild(pointsName, idP1)); assertTrue(featureNode.isPresent()); assertFalse(featureNode.get().getMetadataId().isPresent()); }
@Test public void testAddFeatureAttributePatch() throws Exception { insert(points1); Patch patch = new Patch(); String path = NodeRef.appendChild(pointsName, points1.getIdentifier().getID()); Map<PropertyDescriptor, AttributeDiff> map = Maps.newHashMap(); Optional<?> newValue = Optional.fromNullable(points1B.getProperty("extra").getValue()); GenericAttributeDiffImpl diff = new GenericAttributeDiffImpl(null, newValue); map.put(modifiedPointsType.getDescriptor("extra"), diff); FeatureDiff featureDiff = new FeatureDiff( path, map, RevFeatureType.build(pointsType), RevFeatureType.build(modifiedPointsType)); patch.addModifiedFeature(featureDiff); geogit.command(ApplyPatchOp.class).setPatch(patch).call(); // TODO }
/** * Executes the write back operation. * * @return the {@link ObjectId id} of the resulting new ancestor tree. */ @Override public ObjectId call() { checkNotNull(tree, "child tree not set"); checkNotNull(childPath, "child tree path not set"); String ancestorPath = resolveAncestorPath(); checkArgument( NodeRef.isChild(ancestorPath, childPath), String.format( "child path '%s' is not a child of ancestor path '%s'", childPath, ancestorPath)); RevTree tree = this.tree.get(); checkState(null != tree, "child tree supplier returned null"); ObjectDatabase targetDb = indexDb ? index : odb; RevTreeBuilder root = resolveAncestor(); return writeBack(root, ancestorPath, tree, childPath, targetDb); }
@Test public void testModifiedFeatureDoesNotExists() throws Exception { Patch patch = new Patch(); String path = NodeRef.appendChild(pointsName, points1.getIdentifier().getID()); Map<PropertyDescriptor, AttributeDiff> map = Maps.newHashMap(); Optional<?> oldValue = Optional.fromNullable(points1.getProperty("sp").getValue()); GenericAttributeDiffImpl diff = new GenericAttributeDiffImpl(oldValue, Optional.of("new")); map.put(pointsType.getDescriptor("sp"), diff); FeatureDiff featureDiff = new FeatureDiff( path, map, RevFeatureType.build(pointsType), RevFeatureType.build(pointsType)); patch.addModifiedFeature(featureDiff); try { geogit.command(ApplyPatchOp.class).setPatch(patch).call(); fail(); } catch (CannotApplyPatchException e) { assertTrue(true); } }
@Test public void testRemoveFeatureAttributePatch() throws Exception { insert(points1B); Patch patch = new Patch(); String path = NodeRef.appendChild(pointsName, points1B.getIdentifier().getID()); Map<PropertyDescriptor, AttributeDiff> map = Maps.newHashMap(); Optional<?> oldValue = Optional.fromNullable(points1B.getProperty("extra").getValue()); GenericAttributeDiffImpl diff = new GenericAttributeDiffImpl(oldValue, null); map.put(modifiedPointsType.getDescriptor("extra"), diff); FeatureDiff featureDiff = new FeatureDiff( path, map, RevFeatureType.build(modifiedPointsType), RevFeatureType.build(pointsType)); patch.addModifiedFeature(featureDiff); geogit.command(ApplyPatchOp.class).setPatch(patch).call(); Optional<RevFeature> feature = geogit.command(RevObjectParse.class).setRefSpec("WORK_HEAD:" + path).call(RevFeature.class); assertTrue(feature.isPresent()); ImmutableList<Optional<Object>> values = feature.get().getValues(); assertEquals(points1.getProperties().size(), values.size()); assertFalse(values.contains("ExtraString")); }
/** * Returns the full path from the root tree to the object this ref points to * * <p>This is a derived property, shortcut for <code> * {@link #getParentPath()} + "/" + getNode().getName() </code> */ public String path() { return NodeRef.appendChild(parentPath, node.getName()); }
/** * Executes the import operation using the parameters that have been specified. Features will be * added to the working tree, and a new working tree will be constructed. Either {@code all} or * {@code table}, but not both, must be set prior to the import process. * * @return RevTree the new working tree */ @SuppressWarnings("deprecation") @Override public RevTree call() { // check preconditions and get the actual list of type names to import final String[] typeNames = checkPreconditions(); ProgressListener progressListener = getProgressListener(); progressListener.started(); // use a local variable not to alter the command's state boolean overwrite = this.overwrite; if (alter) { overwrite = false; } final WorkingTree workTree = getWorkTree(); final boolean destPathProvided = destPath != null; if (destPathProvided && overwrite) { // we delete the previous tree to honor the overwrite setting, but then turn it // to false. Otherwise, each table imported will overwrite the previous ones and // only the last one will be imported. try { workTree.delete(destPath); } catch (Exception e) { throw new GeoToolsOpException(e, StatusCode.UNABLE_TO_INSERT); } overwrite = false; } int tableCount = 0; for (String typeName : typeNames) { { tableCount++; String tableName = String.format("%-16s", typeName); if (typeName.length() > 16) { tableName = tableName.substring(0, 13) + "..."; } progressListener.setDescription( "Importing " + tableName + " (" + tableCount + "/" + typeNames.length + ")... "); } FeatureSource featureSource = getFeatureSource(typeName); SimpleFeatureType featureType = (SimpleFeatureType) featureSource.getSchema(); final String fidPrefix = featureType.getTypeName() + "."; String path; if (destPath == null) { path = featureType.getTypeName(); } else { NodeRef.checkValidPath(destPath); path = destPath; featureType = createForceFeatureType(featureType, path); } featureSource = new ForceTypeAndFidFeatureSource<FeatureType, Feature>( featureSource, featureType, fidPrefix); ProgressListener taskProgress = subProgress(100.f / typeNames.length); if (overwrite) { try { workTree.delete(path); workTree.createTypeTree(path, featureType); } catch (Exception e) { throw new GeoToolsOpException(e, StatusCode.UNABLE_TO_INSERT); } } if (alter) { // first we modify the feature type and the existing features, if needed workTree.updateTypeTree(path, featureType); Iterator<Feature> transformedIterator = transformFeatures(featureType, path); try { final Integer collectionSize = collectionSize(featureSource); workTree.insert(path, transformedIterator, taskProgress, null, collectionSize); } catch (Exception e) { throw new GeoToolsOpException(StatusCode.UNABLE_TO_INSERT); } } try { insert(workTree, path, featureSource, taskProgress); } catch (Exception e) { throw new GeoToolsOpException(e, StatusCode.UNABLE_TO_INSERT); } } progressListener.progress(100.f); progressListener.complete(); return workTree.getTree(); }