# HG changeset patch # User ymh # Date 1363483496 -3600 # Node ID 1723936b3836130c616c56374a34a496938030b7 # Parent 5e7a8805d9f60154890112bf4cfec4ddf56bcfef - Add recursive delete for project - correct copy - add unit tests diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/main/java/org/iri_research/renkan/models/Edge.java --- a/server/src/main/java/org/iri_research/renkan/models/Edge.java Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/main/java/org/iri_research/renkan/models/Edge.java Sun Mar 17 02:24:56 2013 +0100 @@ -7,6 +7,7 @@ import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Field; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; @@ -32,7 +33,7 @@ } public Edge(Edge edge, Node from, Node to, String projectId) { - this(UUID.randomUUID().toString(), edge.title, edge.description, edge.uri, edge.color, edge.from, edge.to, edge.createdBy, projectId); + this(UUID.randomUUID().toString(), edge.title, edge.description, edge.uri, edge.color, from, to, edge.createdBy, projectId); } public Edge(Edge edge) { @@ -59,6 +60,11 @@ return createdBy; } + @JsonIgnore + public Node getFromNode() { + return this.from; + } + public String getFrom() { if(this.from != null) { return this.from.id; @@ -68,6 +74,11 @@ } } + @JsonIgnore + public Node getToNode() { + return this.to; + } + public String getTo() { if(this.to != null) { return this.to.id; diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/main/java/org/iri_research/renkan/models/ProjectRevision.java --- a/server/src/main/java/org/iri_research/renkan/models/ProjectRevision.java Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/main/java/org/iri_research/renkan/models/ProjectRevision.java Sun Mar 17 02:24:56 2013 +0100 @@ -35,6 +35,11 @@ super(); } + public ProjectRevision(String title, String description, + String uri, Project project, int revision, Date created) { + this(null, title, description, uri, project, revision,created); + } + public ProjectRevision(ObjectId id, String title, String description, String uri, Project project, int revision, Date created) { super(id, title, description, uri, null); diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/main/java/org/iri_research/renkan/repositories/ProjectRevisionsRepositoryImpl.java --- a/server/src/main/java/org/iri_research/renkan/repositories/ProjectRevisionsRepositoryImpl.java Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectRevisionsRepositoryImpl.java Sun Mar 17 02:24:56 2013 +0100 @@ -13,7 +13,6 @@ @Override public ProjectRevision getProjectRevision(Project project, int revision) { ProjectRevision pr = new ProjectRevision( - null, project.getTitle(), project.getDescription(), project.getUri(), diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java --- a/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryCustom.java Sun Mar 17 02:24:56 2013 +0100 @@ -8,6 +8,11 @@ public int getRevCounter(String projectId); public Map getCountBySpace(); + + public void deleteRecursive(String projectId); + public void deleteRecursive(Project project); + public void deleteRecursive(Iterable projects); + public Project copy(Project p, String newTitle); } diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java --- a/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/main/java/org/iri_research/renkan/repositories/ProjectsRepositoryImpl.java Sun Mar 17 02:24:56 2013 +0100 @@ -1,9 +1,11 @@ package org.iri_research.renkan.repositories; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; import org.iri_research.renkan.models.Project; +import org.iri_research.renkan.models.ProjectRevision; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.stereotype.Component; @@ -25,6 +27,9 @@ @Autowired private EdgesRepository edgesRepository; + + @Autowired + private ProjectRevisionsRepository projectRevisionsRepository; private class GroupResult { @@ -67,10 +72,40 @@ Project res = new Project(p); res.setTitle(newTitle); - this.nodesRepository.save(p.getNodes()); - this.edgesRepository.save(p.getEdges()); + this.nodesRepository.save(res.getNodes()); + this.edgesRepository.save(res.getEdges()); return this.projectsRepository.save(res); } + @Override + public void deleteRecursive(String projectId) { + this.deleteRecursive(this.projectsRepository.findOne(projectId)); + } + + @Override + public void deleteRecursive(Project project) { + this.deleteRecursive(Arrays.asList(new Project[] {project})); + } + + @Override + public void deleteRecursive(Iterable projects) { + + for(Project p: projects) { + if( p == null) { + continue; + } + + ProjectRevision pr = this.projectRevisionsRepository.getProjectRevision(p, this.projectsRepository.getRevCounter(p.getId())); + this.projectRevisionsRepository.save(pr); + + //delete edges + this.edgesRepository.delete(p.getEdges()); + //delete nodes + this.nodesRepository.delete(p.getNodes()); + //delete project + this.projectsRepository.delete(p); + } + } + } diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/main/java/org/iri_research/renkan/rest/ProjectsResource.java --- a/server/src/main/java/org/iri_research/renkan/rest/ProjectsResource.java Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/main/java/org/iri_research/renkan/rest/ProjectsResource.java Sun Mar 17 02:24:56 2013 +0100 @@ -49,7 +49,11 @@ @Override protected List getObjectListFieldList() { return Arrays.asList(this.baseObjectListFieldList); - } + } - + @Override + protected void doDeleteObject(String objectId) { + this.projectsRepository.deleteRecursive(objectId); + } + } diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/main/java/org/iri_research/renkan/rest/RenkanResource.java --- a/server/src/main/java/org/iri_research/renkan/rest/RenkanResource.java Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/main/java/org/iri_research/renkan/rest/RenkanResource.java Sun Mar 17 02:24:56 2013 +0100 @@ -51,6 +51,10 @@ abstract protected void prepareObject(T obj); + protected void doDeleteObject(ID objectId) { + this.getRepository().delete(objectId); + } + @GET @Path("{id : [a-zA-Z\\-0-9]+}") @Produces(MediaType.APPLICATION_JSON + ";charset=utf-8") @@ -73,8 +77,8 @@ public Response deleteObject(@PathParam("id") ID objectId) { this.logger.debug("DeleteObject : id " + objectId); - - this.getRepository().delete(objectId); + this.doDeleteObject(objectId); + return Response.ok(this.uriInfo.getAbsolutePathBuilder().build().toString() + " deleted").build(); } diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/main/webapp/static/js/corenkan.js --- a/server/src/main/webapp/static/js/corenkan.js Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/main/webapp/static/js/corenkan.js Sun Mar 17 02:24:56 2013 +0100 @@ -55,12 +55,12 @@ this.collab = coweb.initCollab({id : "renkan_" + id}); - this.collab.subscribeStateResponse(this, "onStateResponse"); - this.collab.subscribeSync("project", this, "onRemoteProjectChange"); this.collab.subscribeSync("user", this, "onRemoteUserChange"); this.collab.subscribeSync("node", this, "onRemoteNodeChange"); this.collab.subscribeSync("edge", this, "onRemoteEdgeChange"); + + this.collab.subscribeStateResponse(this, "onStateResponse"); }; @@ -104,7 +104,7 @@ obj = json.parse(state); console.log("State response", obj); obj['_id'] = obj['id']; - this.project.set(obj); + this.project.set(obj, {silent: true}); }; function prepareValues(obj,c) { @@ -299,7 +299,7 @@ id: obj.id, _type: "project", _project_id: obj.id, - _user_id : (this.project.current_user!=null)?this.project.current_user.id:null + _user_id : (that.project.current_user!=null)?that.project.current_user.id:null }; values[field] = c; that.collab.sendSync("project", values); diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/test/java/org/iri_research/renkan/test/repositories/ProjectsRepositoryTest.java --- a/server/src/test/java/org/iri_research/renkan/test/repositories/ProjectsRepositoryTest.java Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/test/java/org/iri_research/renkan/test/repositories/ProjectsRepositoryTest.java Sun Mar 17 02:24:56 2013 +0100 @@ -10,9 +10,11 @@ import org.iri_research.renkan.models.Edge; import org.iri_research.renkan.models.Node; import org.iri_research.renkan.models.Project; +import org.iri_research.renkan.models.ProjectRevision; import org.iri_research.renkan.models.Space; import org.iri_research.renkan.repositories.EdgesRepository; import org.iri_research.renkan.repositories.NodesRepository; +import org.iri_research.renkan.repositories.ProjectRevisionsRepository; import org.iri_research.renkan.repositories.ProjectsRepository; import org.iri_research.renkan.repositories.SpacesRepository; import org.junit.After; @@ -32,6 +34,7 @@ import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; +import com.mongodb.DBRef; @RunWith(SpringJUnit4ClassRunner.class) @@ -55,6 +58,9 @@ private EdgesRepository edgesRepository; @Autowired + private ProjectRevisionsRepository projectRevisionsRepository; + + @Autowired private MongoTemplate mongoTemplate; private ArrayList testProjects = new ArrayList(); @@ -112,6 +118,7 @@ logger.debug("Teardown"); edgesRepository.deleteAll(); nodesRepository.deleteAll(); + projectRevisionsRepository.deleteAll(); projectsRepository.deleteAll(); spacesRepository.deleteAll(); } @@ -228,11 +235,174 @@ Assert.assertEquals("The project must be found", 1, resFind.count()); - for(DBObject obj: coll.find(filter)) { + for(DBObject obj: resFind) { Assert.assertEquals("id must be equal", newProject.getId(), obj.get("_id")); Assert.assertEquals("title must be must be copy_project", "copy_project", obj.get("title")); Assert.assertEquals("space_id must be must be same than copyProject", this.copyProject.getSpaceId(), obj.get("space_id")); } + + + filter = new BasicDBObject(); + filter.put("project_id", newProject.getId()); + + DBCollection nodesColl = mongoTemplate.getCollection(mongoTemplate.getCollectionName(Node.class)); + resFind = nodesColl.find(filter); + + Assert.assertEquals("Must have 3 nodes", this.copyProject.getNodes().size(), resFind.count()); + + for(DBObject obj: resFind) { + // find node with same title in copy project + Node originalNode = null; + for(Node n: this.copyProject.getNodes()) { + if(n.getTitle().equals(obj.get("title"))) { + originalNode = n; + break; + } + } + + Assert.assertNotNull("Must fincd original Node", originalNode); + + //color, desc, id diff, uri, created_by, image, position, diff projectif, size + Assert.assertNotSame("id must be differents", originalNode.getId(), obj.get("_id")); + Assert.assertNotSame("project id must be differents", originalNode.getProjectId(), obj.get("project_id")); + + Assert.assertEquals("same color", originalNode.getColor(), obj.get("color")); + Assert.assertEquals("same desc", originalNode.getDescription(), obj.get("description")); + Assert.assertEquals("same uri", originalNode.getUri(), obj.get("uri")); + Assert.assertEquals("same image", originalNode.getImage(), obj.get("image")); + Assert.assertEquals("same position", originalNode.getPosition().getX(), ((DBObject)obj.get("position")).get("x")); + Assert.assertEquals("same position", originalNode.getPosition().getY(), ((DBObject)obj.get("position")).get("y")); + Assert.assertEquals("same size", originalNode.getSize(), obj.get("size")); + + } + + DBCollection edgesColl = mongoTemplate.getCollection(mongoTemplate.getCollectionName(Edge.class)); + resFind = edgesColl.find(filter); + + Assert.assertEquals("Must have 3 edges", this.copyProject.getEdges().size(), resFind.count()); + + for(DBObject obj: resFind) { + // find node with same title in copy project + Edge originalEdge = null; + for(Edge e: this.copyProject.getEdges()) { + if(e.getTitle().equals(obj.get("title"))) { + originalEdge = e; + break; + } + } + + Assert.assertNotNull("Must find original Node", originalEdge); + + //color, desc, id diff, uri, created_by, image, position, diff projectif, size + Assert.assertFalse("id must be differents", originalEdge.getId().equals(obj.get("_id"))); + Assert.assertFalse("project id must be differents", originalEdge.getProjectId().equals(obj.get("project_id"))); + + Assert.assertEquals("same color", originalEdge.getColor(), obj.get("color")); + Assert.assertEquals("same desc", originalEdge.getDescription(), obj.get("description")); + Assert.assertEquals("same uri", originalEdge.getUri(), obj.get("uri")); + + + // get FromNode + DBObject fromNode = nodesColl.findOne(((DBRef)obj.get("from")).getId()); + Assert.assertNotNull("fromNode must exits ", fromNode); + Assert.assertFalse("must be different from node", originalEdge.getFrom().equals(fromNode.get("_id"))); + Assert.assertEquals("same from title", originalEdge.getFromNode().getTitle(), fromNode.get("title")); + + DBObject toNode = nodesColl.findOne(((DBRef)obj.get("to")).getId()); + Assert.assertNotNull("toNode must exits", toNode); + Assert.assertFalse("must be different to node", originalEdge.getTo().equals(toNode.get("_id"))); + Assert.assertEquals("same to title", originalEdge.getToNode().getTitle(), toNode.get("title")); + + } + } + + @Test + public void testDeleteRecursive() { + + List nodes= copyProject.getNodes(); + List edges= copyProject.getEdges(); + + this.projectsRepository.deleteRecursive(copyProject); + + DBObject filter = new BasicDBObject(); + filter.put("_id", copyProject.getId()); + + DBCollection coll = mongoTemplate.getCollection(mongoTemplate.getCollectionName(Project.class)); + DBCursor resFind = coll.find(filter); + + Assert.assertEquals("The project must not be found", 0, resFind.count()); + + filter = new BasicDBObject(); + filter.put("project_id", copyProject.getId()); + + DBCollection nodesColl = mongoTemplate.getCollection(mongoTemplate.getCollectionName(Node.class)); + resFind = nodesColl.find(filter); + + Assert.assertEquals("no nodes left", 0, resFind.count()); + + for(Node n: nodes) { + DBObject nobj = nodesColl.findOne(n.getId()); + Assert.assertNull("node should be deleted", nobj); + } + + + DBCollection edgesColl = mongoTemplate.getCollection(mongoTemplate.getCollectionName(Edge.class)); + resFind = edgesColl.find(filter); + + Assert.assertEquals("no edges left", 0, resFind.count()); + + for(Edge e: edges) { + DBObject eobj = edgesColl.findOne(e.getId()); + Assert.assertNull("edge should be deleted", eobj); + } + + } + + @SuppressWarnings("unchecked") + @Test + public void testDeleteRecursiveProjectRevision() { + + List nodes= copyProject.getNodes(); + List edges= copyProject.getEdges(); + + int revCounter = copyProject.getRevCounter(); + + this.projectsRepository.deleteRecursive(copyProject); + + DBCollection coll = mongoTemplate.getCollection(mongoTemplate.getCollectionName(ProjectRevision.class)); + + DBObject filter = new BasicDBObject(); + filter.put("project", new DBRef(mongoTemplate.getDb(), "projects", copyProject.getId())); + filter.put("revision", new Integer(revCounter)); + + DBObject revision = coll.findOne(filter); + + Assert.assertNotNull("Must find revision", revision); + + for(DBObject nobj: ((Iterable)revision.get("nodes"))) { + Node node = null; + for(Node n: nodes) { + if(n.getId().equals(nobj.get("_id"))) { + node = n; + break; + } + } + Assert.assertNotNull("Node must be in the original list", node); + Assert.assertEquals("Nodes must have same title", node.getTitle(), nobj.get("title")); + } + + for(DBObject eobj: ((Iterable)revision.get("edges"))) { + Edge edge = null; + for(Edge e: edges) { + if(e.getId().equals(eobj.get("_id"))) { + edge = e; + break; + } + } + Assert.assertNotNull("Edge must be in the original list", edge); + Assert.assertEquals("Edges must have same title", edge.getTitle(), eobj.get("title")); + } + } } diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/test/java/org/iri_research/renkan/test/rest/ProjectRestTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/server/src/test/java/org/iri_research/renkan/test/rest/ProjectRestTest.java Sun Mar 17 02:24:56 2013 +0100 @@ -0,0 +1,171 @@ +package org.iri_research.renkan.test.rest; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.UUID; + +import org.iri_research.renkan.models.Edge; +import org.iri_research.renkan.models.Node; +import org.iri_research.renkan.models.Project; +import org.iri_research.renkan.models.Space; +import org.iri_research.renkan.repositories.EdgesRepository; +import org.iri_research.renkan.repositories.NodesRepository; +import org.iri_research.renkan.repositories.ProjectRevisionsRepository; +import org.iri_research.renkan.repositories.ProjectsRepository; +import org.iri_research.renkan.repositories.SpacesRepository; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.geo.Point; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.web.context.ContextLoaderListener; + +import com.mongodb.BasicDBObject; +import com.mongodb.DBCollection; +import com.mongodb.DBCursor; +import com.mongodb.DBObject; +import com.sun.jersey.api.client.WebResource; +import com.sun.jersey.spi.spring.container.servlet.SpringServlet; +import com.sun.jersey.test.framework.AppDescriptor; +import com.sun.jersey.test.framework.JerseyTest; +import com.sun.jersey.test.framework.WebAppDescriptor; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration("rest-context.xml") +public class ProjectRestTest extends JerseyTest { + + private Logger logger = LoggerFactory.getLogger(ProjectRestTest.class); + + @Autowired + private ProjectsRepository projectsRepository; + + @Autowired + private SpacesRepository spacesRepository; + + @Autowired + private NodesRepository nodesRepository; + + @Autowired + private EdgesRepository edgesRepository; + + @Autowired + private ProjectRevisionsRepository projectRevisionsRepository; + + @Autowired + private MongoTemplate mongoTemplate; + + private Project testProject; + private List testNodes = new ArrayList(); + private List testEdges = new ArrayList<>(); + + private Date creationDate = new Date(); + + private String spaceId = UUID.randomUUID().toString(); + + public ProjectRestTest() { + } + + @Override + protected AppDescriptor configure() { + return new WebAppDescriptor.Builder("org.iri_research.renkan.rest") + .contextPath("rest") + .contextParam("contextConfigLocation", "classpath:/org/iri_research/renkan/test/rest/rest-context.xml") + .initParam("com.sun.jersey.config.property.packages", "org.iri_research.renkan.rest;com.fasterxml.jackson.jaxrs") + .servletClass(SpringServlet.class) + .contextListenerClass(ContextLoaderListener.class) + .build(); + }; + + @Before + public void setup() { + + logger.debug("Setup"); + Space testSpace = new Space(this.spaceId, "test space", "Test space", null, null, null, "test_user", null, this.creationDate); + testSpace = spacesRepository.save(testSpace); + testProject = new Project(testSpace.getId(), UUID.randomUUID().toString(), "test", "desc", "http://localhost:8080/rest/projects/id", this.creationDate); + + for(int i=0;i<3;i++) { + Node node = new Node("Node"+i, "Node"+i, "Node "+i, "http://renkan.org/nodes/node"+i, "#ffff0"+i, "test_user", new Point(0, i), "http://renkan.org/images/node"+i, i, testProject.getId()); + node = this.nodesRepository.save(node); + testProject.getNodes().add(node); + this.testNodes.add(node); + } + + for(int i=0;i<3;i++) { + Edge edge = new Edge("Node"+i, "Node"+i, "Node "+i, "http://renkan.org/edges/edge"+i, "#ffff0"+i, this.testNodes.get((i+2)%3), this.testNodes.get(i), "test_user", testProject.getId()); + edge = this.edgesRepository.save(edge); + testProject.getEdges().add(edge); + this.testEdges.add(edge); + } + + this.projectsRepository.save(testProject); + + } + + @After + public void teardown() { + logger.debug("Teardown"); + edgesRepository.deleteAll(); + nodesRepository.deleteAll(); + projectRevisionsRepository.deleteAll(); + projectsRepository.deleteAll(); + spacesRepository.deleteAll(); + } + + + @Test + public void testDeleteProject() { + + List nodes= testProject.getNodes(); + List edges= testProject.getEdges(); + + WebResource webResource = this.resource(); + String respString = webResource.path("projects").path(testProject.getId()).delete(String.class); + + Assert.assertTrue("Response text must contain deleted", respString.contains("deleted")); + Assert.assertTrue("Response text must contain id", respString.contains(this.testProject.getId())); + + DBObject filter = new BasicDBObject(); + filter.put("_id", testProject.getId()); + + DBCollection coll = mongoTemplate.getCollection(mongoTemplate.getCollectionName(Project.class)); + DBCursor resFind = coll.find(filter); + + Assert.assertEquals("The project must not be found", 0, resFind.count()); + + filter = new BasicDBObject(); + filter.put("project_id", testProject.getId()); + + DBCollection nodesColl = mongoTemplate.getCollection(mongoTemplate.getCollectionName(Node.class)); + resFind = nodesColl.find(filter); + + Assert.assertEquals("no nodes left", 0, resFind.count()); + + for(Node n: nodes) { + DBObject nobj = nodesColl.findOne(n.getId()); + Assert.assertNull("node should be deleted", nobj); + } + + + DBCollection edgesColl = mongoTemplate.getCollection(mongoTemplate.getCollectionName(Edge.class)); + resFind = edgesColl.find(filter); + + Assert.assertEquals("no edges left", 0, resFind.count()); + + for(Edge e: edges) { + DBObject eobj = edgesColl.findOne(e.getId()); + Assert.assertNull("edge should be deleted", eobj); + } + + } + + +} diff -r 5e7a8805d9f6 -r 1723936b3836 server/src/test/java/org/iri_research/renkan/test/rest/SpaceRestTest.java --- a/server/src/test/java/org/iri_research/renkan/test/rest/SpaceRestTest.java Sat Mar 16 04:37:05 2013 +0100 +++ b/server/src/test/java/org/iri_research/renkan/test/rest/SpaceRestTest.java Sun Mar 17 02:24:56 2013 +0100 @@ -81,7 +81,7 @@ @After public void teardown() { - //spacesRepository.deleteAll(); + spacesRepository.deleteAll(); }