Skip to content

Commit

Permalink
Add a command for creating arbitrary edges between nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
mikesname committed Mar 27, 2014
1 parent 3b2c374 commit d84d392
Show file tree
Hide file tree
Showing 4 changed files with 182 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ public boolean isReadOnly() {
return false;
}

/**
* Utility to get a parsed command line from some args. This is
* mainly helpful for testing.
* @param args A list of arg strings
* @return The parsed command line
*/
public CommandLine getCmdLine(String[] args) throws ParseException {
setCustomOptions();
return parser.parse(options, args);
}

protected Optional<String> getLogMessage(String msg) {
return msg.trim().isEmpty() ? Optional.<String>absent() : Optional.of(msg);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public CmdEntryPoint() {
mmap.put(PersonalitiesImport.NAME, PersonalitiesImport.class);
mmap.put(DeleteEntities.NAME, DeleteEntities.class);
mmap.put(RdfExport.NAME, RdfExport.class);
mmap.put(RelationAdd.NAME, RelationAdd.class);
// adaptation of UserAdd for adding countries
mmap.put(CountryAdd.NAME, CountryAdd.class);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package eu.ehri.project.commands;

import com.tinkerpop.blueprints.TransactionalGraph;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.frames.FramedGraph;
import eu.ehri.project.core.GraphManager;
import eu.ehri.project.core.GraphManagerFactory;
import eu.ehri.project.exceptions.*;
import eu.ehri.project.models.utils.JavaHandlerUtils;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;

/**
* Add an arbitrary edge between two nodes.
*
*/
public class RelationAdd extends BaseCommand implements Command {

final static String NAME = "add-rel";

/**
* Constructor.
*
*/
public RelationAdd() {
}

@Override
protected void setCustomOptions() {
options.addOption(new Option("u", "unique", false,
"Ensure the out entity only has one relationship of this type"));
options.addOption(new Option("s", "single", false,
"Don't create this relationship if it already exists"));
}

@Override
public String getHelp() {
return "Usage: add-rel [OPTIONS] [-Pkey=value] <source> <rel-name> <target>";
}

@Override
public String getUsage() {
return "Create a relationship between a source and a target";
}

/**
* Add a relationship between two nodes.
*
* @throws eu.ehri.project.exceptions.ItemNotFound
*/
@Override
public int execWithOptions(final FramedGraph<? extends TransactionalGraph> graph,
CommandLine cmdLine) throws ItemNotFound {

GraphManager manager = GraphManagerFactory.getInstance(graph);

if (cmdLine.getArgList().size() < 3)
throw new RuntimeException(getHelp());

String src = (String)cmdLine.getArgList().get(0);
String label = (String)cmdLine.getArgList().get(1);
String dst = (String)cmdLine.getArgList().get(2);

Vertex source = manager.getVertex(src);
Vertex target = manager.getVertex(dst);

try {
if (cmdLine.hasOption("unique")) {
if (!JavaHandlerUtils.addUniqueRelationship(source, target, label)) {
System.err.println("Relationship already exists");
}
} else if (cmdLine.hasOption("single")) {
if (!JavaHandlerUtils.addSingleRelationship(source, target, label)) {
System.err.println("Relationship already exists");
}
} else {
source.addEdge(label, target);
}
graph.getBaseGraph().commit();
} catch (Exception e) {
graph.getBaseGraph().rollback();
throw new RuntimeException(e);
}

return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package eu.ehri.project.commands;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
import eu.ehri.project.models.EntityClass;
import eu.ehri.project.test.AbstractFixtureTest;
import eu.ehri.project.test.GraphTestBase;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.PosixParser;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

/**
* @author Mike Bryant (http://github.com/mikesname)
*/
public class RelationAddTest extends GraphTestBase {

private Vertex mike;
private Vertex linda;
private Vertex reto;
private RelationAdd relationAdd;

@Before
public void setUp() throws Exception {
super.setUp();
relationAdd = new RelationAdd();
mike = manager.createVertex("mike", EntityClass.USER_PROFILE, Maps.<String,Object>newHashMap());
reto = manager.createVertex("reto", EntityClass.USER_PROFILE, Maps.<String,Object>newHashMap());
linda = manager.createVertex("linda", EntityClass.USER_PROFILE, Maps.<String,Object>newHashMap());
}

@Test
public void testAddRelation() throws Exception {
assertEquals(0L, Iterables.size(mike.getVertices(Direction.OUT, "knows")));
CommandLine commandLine = relationAdd.getCmdLine(new String[]{"mike", "knows", "linda"});
int retVal = relationAdd.execWithOptions(graph, commandLine);
assertEquals(0, retVal);
assertEquals(1L, Iterables.size(mike.getVertices(Direction.OUT, "knows")));
assertEquals(1L, Iterables.size(linda.getVertices(Direction.IN, "knows")));

relationAdd.execWithOptions(graph, commandLine);
assertEquals(2L, Iterables.size(mike.getVertices(Direction.OUT, "knows")));
assertEquals(2L, Iterables.size(linda.getVertices(Direction.IN, "knows")));
}

@Test
public void testAddUniqueRelation() throws Exception {
assertEquals(0L, Iterables.size(mike.getVertices(Direction.OUT, "knows")));
CommandLine commandLine = relationAdd.getCmdLine(new String[]{"-u", "mike", "knows", "linda"});
int retVal = relationAdd.execWithOptions(graph, commandLine);
assertEquals(0, retVal);
assertEquals(1L, Iterables.size(mike.getVertices(Direction.OUT, "knows")));
assertEquals(1L, Iterables.size(linda.getVertices(Direction.IN, "knows")));

relationAdd.execWithOptions(graph, commandLine);
assertEquals(1L, Iterables.size(mike.getVertices(Direction.OUT, "knows")));
assertEquals(1L, Iterables.size(linda.getVertices(Direction.IN, "knows")));
}

@Test
public void testAddSingleRelation() throws Exception {
assertEquals(0L, Iterables.size(mike.getVertices(Direction.OUT, "knows")));
CommandLine commandLine1 = relationAdd.getCmdLine(new String[]{"mike", "knows", "linda"});
int retVal = relationAdd.execWithOptions(graph, commandLine1);
assertEquals(0, retVal);
assertEquals(1L, Iterables.size(mike.getVertices(Direction.OUT, "knows")));
assertEquals(1L, Iterables.size(linda.getVertices(Direction.IN, "knows")));

CommandLine commandLine2 = relationAdd.getCmdLine(new String[]{"-s", "mike", "knows", "reto"});
relationAdd.execWithOptions(graph, commandLine2);
assertEquals(1L, Iterables.size(mike.getVertices(Direction.OUT, "knows")));
assertEquals(0L, Iterables.size(linda.getVertices(Direction.IN, "knows")));
assertEquals(1L, Iterables.size(reto.getVertices(Direction.IN, "knows")));
}
}

0 comments on commit d84d392

Please sign in to comment.