Cleaning up a bit
This commit is contained in:
@@ -1,155 +1,222 @@
|
||||
package org.neo4j.rest.graphdb;
|
||||
|
||||
import com.sun.jersey.api.client.ClientResponse;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.traversal.*;
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Path;
|
||||
import org.neo4j.graphdb.RelationshipExpander;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.neo4j.graphdb.traversal.BranchOrderingPolicy;
|
||||
import org.neo4j.graphdb.traversal.Evaluator;
|
||||
import org.neo4j.graphdb.traversal.PruneEvaluator;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.graphdb.traversal.Traverser;
|
||||
import org.neo4j.graphdb.traversal.UniquenessFactory;
|
||||
import org.neo4j.helpers.Predicate;
|
||||
import org.neo4j.kernel.Traversal;
|
||||
import org.neo4j.kernel.Uniqueness;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 02.02.11
|
||||
*/
|
||||
public class RestTraversal implements RestTraversalDescription {
|
||||
public class RestTraversal implements RestTraversalDescription
|
||||
{
|
||||
|
||||
private static final String FULLPATH = "fullpath";
|
||||
private final Map<String, Object> description=new HashMap<String, Object>();
|
||||
private final Map<String, Object> description = new HashMap<String, Object>();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public String toString()
|
||||
{
|
||||
return description.toString();
|
||||
}
|
||||
|
||||
public TraversalDescription uniqueness(UniquenessFactory uniquenessFactory) {
|
||||
return uniqueness(uniquenessFactory,null);
|
||||
public TraversalDescription uniqueness( UniquenessFactory uniquenessFactory )
|
||||
{
|
||||
return uniqueness( uniquenessFactory, null );
|
||||
}
|
||||
|
||||
public TraversalDescription uniqueness(UniquenessFactory uniquenessFactory, Object value) {
|
||||
String uniqueness = restify(uniquenessFactory);
|
||||
add("uniqueness",value==null ? uniqueness : toMap("name",uniqueness, "value", value));
|
||||
public TraversalDescription uniqueness( UniquenessFactory uniquenessFactory, Object value )
|
||||
{
|
||||
String uniqueness = restify( uniquenessFactory );
|
||||
add( "uniqueness", value == null ? uniqueness : toMap( "name", uniqueness, "value", value ) );
|
||||
return null;
|
||||
}
|
||||
|
||||
private String restify(UniquenessFactory uniquenessFactory) {
|
||||
if (uniquenessFactory instanceof Uniqueness) {
|
||||
return ((Uniqueness)uniquenessFactory).name().toLowerCase().replace("_"," ");
|
||||
private String restify( UniquenessFactory uniquenessFactory )
|
||||
{
|
||||
if ( uniquenessFactory instanceof Uniqueness )
|
||||
{
|
||||
return ( (Uniqueness)uniquenessFactory ).name().toLowerCase().replace( "_", " " );
|
||||
}
|
||||
throw new UnsupportedOperationException("Only values of "+Uniqueness.class+" are supported");
|
||||
throw new UnsupportedOperationException( "Only values of " + Uniqueness.class + " are supported" );
|
||||
}
|
||||
|
||||
public TraversalDescription prune(PruneEvaluator pruneEvaluator) {
|
||||
Integer maxDepth= getMaxDepthValueOrNull(pruneEvaluator);
|
||||
if (maxDepth!=null) {
|
||||
return maxDepth(maxDepth);
|
||||
public TraversalDescription prune( PruneEvaluator pruneEvaluator )
|
||||
{
|
||||
Integer maxDepth = getMaxDepthValueOrNull( pruneEvaluator );
|
||||
if ( maxDepth != null )
|
||||
{
|
||||
return maxDepth( maxDepth );
|
||||
}
|
||||
throw new UnsupportedOperationException("Only max depth supported");
|
||||
throw new UnsupportedOperationException( "Only max depth supported" );
|
||||
}
|
||||
|
||||
private Integer getMaxDepthValueOrNull(PruneEvaluator pruneEvaluator) {
|
||||
try {
|
||||
final Field depthField = pruneEvaluator.getClass().getDeclaredField("val$depth");
|
||||
depthField.setAccessible(true);
|
||||
return (Integer) depthField.get(pruneEvaluator);
|
||||
} catch (Exception e) {
|
||||
private Integer getMaxDepthValueOrNull( PruneEvaluator pruneEvaluator )
|
||||
{
|
||||
try
|
||||
{
|
||||
final Field depthField = pruneEvaluator.getClass().getDeclaredField( "val$depth" );
|
||||
depthField.setAccessible( true );
|
||||
return (Integer)depthField.get( pruneEvaluator );
|
||||
} catch ( Exception e )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public TraversalDescription filter(Predicate<Path> pathPredicate) {
|
||||
if (pathPredicate == Traversal.returnAll()) return add("return filter",toMap("language","builtin", "name","all"));
|
||||
if (pathPredicate == Traversal.returnAllButStartNode()) return add("return filter",toMap("language","builtin", "name","all but start node"));
|
||||
throw new UnsupportedOperationException("Only builtin paths supported");
|
||||
public TraversalDescription filter( Predicate<Path> pathPredicate )
|
||||
{
|
||||
if ( pathPredicate == Traversal.returnAll() )
|
||||
{
|
||||
return add( "return filter", toMap( "language", "builtin", "name", "all" ) );
|
||||
}
|
||||
if ( pathPredicate == Traversal.returnAllButStartNode() )
|
||||
{
|
||||
return add( "return filter", toMap( "language", "builtin", "name", "all but start node" ) );
|
||||
}
|
||||
throw new UnsupportedOperationException( "Only builtin paths supported" );
|
||||
}
|
||||
|
||||
public TraversalDescription evaluator(Evaluator evaluator) {
|
||||
public TraversalDescription evaluator( Evaluator evaluator )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public TraversalDescription prune(ScriptLanguage language, String code) {
|
||||
return add("prune evaluator",toMap("language",language.name().toLowerCase(),"body",code ));
|
||||
public TraversalDescription prune( ScriptLanguage language, String code )
|
||||
{
|
||||
return add( "prune evaluator", toMap( "language", language.name().toLowerCase(), "body", code ) );
|
||||
}
|
||||
|
||||
public TraversalDescription filter(ScriptLanguage language, String code) {
|
||||
return add("return filter",toMap("language",language.name().toLowerCase(),"body",code ));
|
||||
public TraversalDescription filter( ScriptLanguage language, String code )
|
||||
{
|
||||
return add( "return filter", toMap( "language", language.name().toLowerCase(), "body", code ) );
|
||||
}
|
||||
|
||||
public TraversalDescription maxDepth(int depth) {
|
||||
return add("max depth",depth);
|
||||
public TraversalDescription maxDepth( int depth )
|
||||
{
|
||||
return add( "max depth", depth );
|
||||
}
|
||||
|
||||
public TraversalDescription order(BranchOrderingPolicy branchOrderingPolicy) {
|
||||
public TraversalDescription order( BranchOrderingPolicy branchOrderingPolicy )
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public TraversalDescription depthFirst() {
|
||||
return add("order","depth first");
|
||||
public TraversalDescription depthFirst()
|
||||
{
|
||||
return add( "order", "depth first" );
|
||||
}
|
||||
|
||||
public TraversalDescription breadthFirst() {
|
||||
return add("order", "breadth first");
|
||||
public TraversalDescription breadthFirst()
|
||||
{
|
||||
return add( "order", "breadth first" );
|
||||
}
|
||||
|
||||
private RestTraversalDescription add(String key, Object value) {
|
||||
description.put(key,value);
|
||||
private RestTraversalDescription add( String key, Object value )
|
||||
{
|
||||
description.put( key, value );
|
||||
return this;
|
||||
}
|
||||
|
||||
public TraversalDescription relationships(RelationshipType relationshipType) {
|
||||
return relationships(relationshipType, null);
|
||||
public TraversalDescription relationships( RelationshipType relationshipType )
|
||||
{
|
||||
return relationships( relationshipType, null );
|
||||
}
|
||||
|
||||
public TraversalDescription relationships(RelationshipType relationshipType, Direction direction) {
|
||||
if (!description.containsKey("relationships")) {
|
||||
description.put("relationships",new HashSet<Map<String,Object>>());
|
||||
public TraversalDescription relationships( RelationshipType relationshipType, Direction direction )
|
||||
{
|
||||
if ( !description.containsKey( "relationships" ) )
|
||||
{
|
||||
description.put( "relationships", new HashSet<Map<String, Object>>() );
|
||||
}
|
||||
Set<Map<String,Object>> relationships= (Set<Map<String, Object>>) description.get("relationships");
|
||||
relationships.add(toMap("type", relationshipType, "direction", directionString(direction)));
|
||||
Set<Map<String, Object>> relationships = (Set<Map<String, Object>>)description.get( "relationships" );
|
||||
relationships.add( toMap( "type", relationshipType, "direction", directionString( direction ) ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
private Map<String, Object> toMap(Object...params) {
|
||||
if (params.length % 2 != 0) throw new IllegalArgumentException("toMap needs an even number of arguments, but was "+Arrays.toString(params));
|
||||
private Map<String, Object> toMap( Object... params )
|
||||
{
|
||||
if ( params.length % 2 != 0 )
|
||||
{
|
||||
throw new IllegalArgumentException( "toMap needs an even number of arguments, but was " + Arrays.toString( params ) );
|
||||
}
|
||||
|
||||
Map<String, Object> result = new HashMap<String, Object>();
|
||||
for (int i = 0; i < params.length; i+=2) {
|
||||
if (params[i+1] == null) continue;
|
||||
result.put(params[i].toString(), params[i + 1].toString());
|
||||
for ( int i = 0; i < params.length; i += 2 )
|
||||
{
|
||||
if ( params[ i + 1 ] == null )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
result.put( params[ i ].toString(), params[ i + 1 ].toString() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String directionString(Direction direction) {
|
||||
if (direction==Direction.INCOMING) return "in";
|
||||
if (direction==Direction.OUTGOING) return "out";
|
||||
private String directionString( Direction direction )
|
||||
{
|
||||
switch ( direction )
|
||||
{
|
||||
case INCOMING:
|
||||
return "in";
|
||||
case OUTGOING:
|
||||
return "out";
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public TraversalDescription expand( RelationshipExpander relationshipExpander )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
public TraversalDescription expand(RelationshipExpander relationshipExpander) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Traverser traverse(Node node) {
|
||||
final RestNode restNode = (RestNode) node;
|
||||
public Traverser traverse( Node node )
|
||||
{
|
||||
final RestNode restNode = (RestNode)node;
|
||||
final RestRequest request = restNode.getRestRequest();
|
||||
final String traversalJson = JsonHelper.createJsonFrom(description);
|
||||
final ClientResponse result = request.post("traverse/" + FULLPATH, traversalJson);
|
||||
if (request.statusOtherThan(result, Response.Status.OK)) throw new RuntimeException(String.format("Error executing traversal: %d %s",result.getStatus(), traversalJson));
|
||||
final Object col = request.toEntity(result);
|
||||
if (!(col instanceof Collection)) throw new RuntimeException(String.format("Unexpected traversal result, %s instead of collection", col!=null ? col.getClass() : null));
|
||||
return new RestTraverser((Collection) col,restNode.getGraphDatabase());
|
||||
final String traversalJson = JsonHelper.createJsonFrom( description );
|
||||
final ClientResponse result = request.post( "traverse/" + FULLPATH, traversalJson );
|
||||
if ( request.statusOtherThan( result, Response.Status.OK ) )
|
||||
{
|
||||
throw new RuntimeException( String.format( "Error executing traversal: %d %s", result.getStatus(), traversalJson ) );
|
||||
}
|
||||
final Object col = request.toEntity( result );
|
||||
if ( !( col instanceof Collection ) )
|
||||
{
|
||||
throw new RuntimeException( String.format( "Unexpected traversal result, %s instead of collection", col != null ? col.getClass() : null ) );
|
||||
}
|
||||
return new RestTraverser( (Collection)col, restNode.getGraphDatabase() );
|
||||
}
|
||||
|
||||
public static RestTraversalDescription description() {
|
||||
public static RestTraversalDescription description()
|
||||
{
|
||||
return new RestTraversal();
|
||||
}
|
||||
|
||||
public Map<String,Object> getPostData() {
|
||||
public Map<String, Object> getPostData()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.rest.graphdb.RestTestBase;
|
||||
import org.springframework.data.graph.neo4j.support.ProjectionTest;
|
||||
import org.springframework.data.graph.neo4j.support.TraversalTest;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
@@ -15,29 +14,33 @@ import org.springframework.test.context.support.DependencyInjectionTestExecution
|
||||
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 28.03.11
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml",
|
||||
"classpath:RestTest-context.xml"})
|
||||
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
|
||||
public class RestTraversalTest extends TraversalTest {
|
||||
* @author mh
|
||||
* @since 28.03.11
|
||||
*/
|
||||
@RunWith( SpringJUnit4ClassRunner.class )
|
||||
@ContextConfiguration( locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml",
|
||||
"classpath:RestTest-context.xml"} )
|
||||
@TestExecutionListeners( {CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class} )
|
||||
public class RestTraversalTest extends TraversalTest
|
||||
{
|
||||
|
||||
@BeforeClass
|
||||
public static void startDb() throws Exception {
|
||||
RestTestBase.startDb();
|
||||
}
|
||||
@BeforeClass
|
||||
public static void startDb() throws Exception
|
||||
{
|
||||
RestTestBase.startDb();
|
||||
}
|
||||
|
||||
@Before
|
||||
public void cleanDb() {
|
||||
RestTestBase.cleanDb();
|
||||
}
|
||||
@Before
|
||||
public void cleanDb()
|
||||
{
|
||||
RestTestBase.cleanDb();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutdownDb() {
|
||||
RestTestBase.shutdownDb();
|
||||
|
||||
}
|
||||
@AfterClass
|
||||
public static void shutdownDb()
|
||||
{
|
||||
RestTestBase.shutdownDb();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user