diff --git a/spring-data-neo4j-rest/src/test/resources/log4j.properties b/spring-data-neo4j-rest/src/test/resources/log4j.properties
index 9b295b169..d8f54df4a 100644
--- a/spring-data-neo4j-rest/src/test/resources/log4j.properties
+++ b/spring-data-neo4j-rest/src/test/resources/log4j.properties
@@ -18,7 +18,7 @@ log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
log4j.category.org.springframework=WARN
-#log4j.category.org.springframework.data.graph.neo4j.support.SubReferenceTypeRepresentationStrategy=DEBUG
+#log4j.category.org.springframework.data.graph.neo4j.support.SubReferenceNodeTypeRepresentationStrategytegy=DEBUG
#log4j.category.org.springframework.data.graph.neo4j.fieldaccess=DEBUG
#log4j.category.org.springframework.data=TRACE
#log4j.category.org.springframework.data.support=TRACE
diff --git a/spring-data-neo4j-roo/src/test/resources/org/springframework/data/graph/neo4j/jpa/Neo4jEntityManagerTest-context.xml b/spring-data-neo4j-roo/src/test/resources/org/springframework/data/graph/neo4j/jpa/Neo4jEntityManagerTest-context.xml
index 01e088977..0fe46e4e6 100644
--- a/spring-data-neo4j-roo/src/test/resources/org/springframework/data/graph/neo4j/jpa/Neo4jEntityManagerTest-context.xml
+++ b/spring-data-neo4j-roo/src/test/resources/org/springframework/data/graph/neo4j/jpa/Neo4jEntityManagerTest-context.xml
@@ -90,22 +90,24 @@
-
-
-
+
+
-
+
+
+
+
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/NodeTypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/NodeTypeRepresentationStrategy.java
new file mode 100644
index 000000000..259f404f5
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/NodeTypeRepresentationStrategy.java
@@ -0,0 +1,7 @@
+package org.springframework.data.graph.core;
+
+import org.neo4j.graphdb.Node;
+
+public interface NodeTypeRepresentationStrategy extends TypeRepresentationStrategy {
+
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/RelationshipTypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/RelationshipTypeRepresentationStrategy.java
new file mode 100644
index 000000000..57495164f
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/RelationshipTypeRepresentationStrategy.java
@@ -0,0 +1,7 @@
+package org.springframework.data.graph.core;
+
+import org.neo4j.graphdb.Relationship;
+
+public interface RelationshipTypeRepresentationStrategy extends TypeRepresentationStrategy {
+
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/TypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/TypeRepresentationStrategy.java
index 689e41cb3..861ad5c9a 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/TypeRepresentationStrategy.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/core/TypeRepresentationStrategy.java
@@ -29,47 +29,70 @@ import org.neo4j.graphdb.PropertyContainer;
* @author Michael Hunger
* @since 13.09.2010
*/
-public interface TypeRepresentationStrategy {
+public interface TypeRepresentationStrategy> {
/**
* callback on entity creation for setting up type representation
- * @param entity
+ * @param state
+ * @param type
*/
- void postEntityCreation(GraphBacked> entity);
+ void postEntityCreation(S state, Class extends T> type);
/**
* @param clazz Type whose instances should be iterated over
- * @param Type parameter for generified return value
+ * @param Type parameter for generified return value
* @return lazy Iterable over all instances of the given type
*/
- > Iterable findAll(final Class clazz);
+ Iterable findAll(final Class clazz);
/**
* @param entityClass
* @return number of instances of this class contained in the graph
*/
- long count(final Class extends GraphBacked>> entityClass);
+ long count(final Class extends T> entityClass);
/**
- * @param primitive
- * @param
+ * @param state
* @return java type that of the node entity of this node
*/
- > Class getJavaType(PropertyContainer primitive);
+ Class getJavaType(S state);
/**
* callback for lifecycle management before node entity removal
* @param entity
*/
- void preEntityRemoval(GraphBacked> entity);
+ void preEntityRemoval(T entity);
/**
+ * Instantiate the entity given its state. The type of the entity is inferred by the strategy
+ * from the state.
*
- * @param node
- * @param type
- * @param
- * @throws IllegalArgumentException if the specified type did not match the stored one
- * @throws IllegalStateException if the primitive has no type stored
- * @return Concrete type for primitive, or throws exception
+ * @param state Backing state of entity to be instantiated
+ * @param Helper parameter for castless use
+ * @throws IllegalStateException If the strategy is unable to infer any type from the state
+ * @return Entity instance
*/
- > Class confirmType(PropertyContainer node, Class type);
+ U createEntity(S state) throws IllegalStateException;
+
+ /**
+ * Instantiate the entity given its state. The type of the desired entity is also specified.
+ * If the type is not compatible with what the strategy can infer from the state,
+ * {@link java.lang.IllegalArgumentException} is thrown.
+ *
+ * @param state Backing state of entity to be instantiated
+ * @param type Type of entity to be instantiated
+ * @throws IllegalStateException If the strategy is unable to infer any type from the state
+ * @throws IllegalArgumentException If the specified type does not match the inferred type
+ * @return Entity instance
+ */
+ U createEntity(S state, Class type) throws IllegalStateException, IllegalArgumentException;
+
+ /**
+ * Instantiate the entity of the given type, with the given state as backing state. No checking
+ * is done by the strategy.
+ *
+ * @param state Backing state of entity to be instantiated
+ * @param type Type of entity to be instantiated
+ * @return Entity instance.
+ */
+ U projectEntity(S state, Class type);
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/Neo4jConfiguration.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/Neo4jConfiguration.java
index da6540d66..f1ddfceb8 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/Neo4jConfiguration.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/config/Neo4jConfiguration.java
@@ -18,6 +18,7 @@ package org.springframework.data.graph.neo4j.config;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.Relationship;
import org.neo4j.kernel.impl.transaction.SpringTransactionManager;
import org.neo4j.kernel.impl.transaction.UserTransactionImpl;
import org.springframework.beans.factory.annotation.Autowired;
@@ -26,21 +27,22 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.graph.core.NodeBacked;
+import org.springframework.data.graph.core.RelationshipBacked;
import org.springframework.data.graph.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean;
import org.springframework.data.graph.neo4j.fieldaccess.NodeDelegatingFieldAccessorFactory;
import org.springframework.data.graph.neo4j.fieldaccess.NodeEntityStateFactory;
import org.springframework.data.graph.neo4j.fieldaccess.RelationshipEntityStateFactory;
import org.springframework.data.graph.neo4j.repository.DirectGraphRepositoryFactory;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
-import org.springframework.data.graph.neo4j.support.TypeRepresentationStrategyFactoryBean;
+import org.springframework.data.graph.neo4j.support.TypeRepresentationStrategyFactory;
import org.springframework.data.graph.neo4j.support.node.Neo4jConstructorGraphEntityInstantiator;
import org.springframework.data.graph.neo4j.support.node.Neo4jNodeBacking;
import org.springframework.data.graph.neo4j.support.node.PartialNeo4jEntityInstantiator;
import org.springframework.data.graph.neo4j.support.relationship.ConstructorBypassingGraphRelationshipInstantiator;
import org.springframework.data.graph.neo4j.support.relationship.Neo4jRelationshipBacking;
import org.springframework.data.graph.neo4j.transaction.ChainedTransactionManager;
-import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.data.persistence.EntityInstantiator;
+import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;
@@ -88,16 +90,17 @@ public class Neo4jConfiguration {
@Bean
public GraphDatabaseContext graphDatabaseContext() throws Exception {
- GraphDatabaseContext gdc = new GraphDatabaseContext();
- gdc.setGraphDatabaseService(getGraphDatabaseService());
- ConstructorBypassingGraphRelationshipInstantiator relationshipEntityInstantiator = graphRelationshipInstantiator();
- gdc.setRelationshipEntityInstantiator(relationshipEntityInstantiator);
- EntityInstantiator graphEntityInstantiator = graphEntityInstantiator();
- gdc.setGraphEntityInstantiator(graphEntityInstantiator);
- gdc.setConversionService(conversionService());
- TypeRepresentationStrategyFactoryBean typeRepresentationStrategyFactoryBean =
- new TypeRepresentationStrategyFactoryBean(graphDatabaseService, graphEntityInstantiator, relationshipEntityInstantiator);
- gdc.setTypeRepresentationStrategy(typeRepresentationStrategyFactoryBean.getObject());
+ EntityInstantiator relationshipEntityInstantiator = graphRelationshipInstantiator();
+ EntityInstantiator graphEntityInstantiator = graphEntityInstantiator();
+
+ TypeRepresentationStrategyFactory typeRepresentationStrategyFactory =
+ new TypeRepresentationStrategyFactory(graphDatabaseService, graphEntityInstantiator, relationshipEntityInstantiator);
+
+ GraphDatabaseContext gdc = new GraphDatabaseContext();
+ gdc.setGraphDatabaseService(getGraphDatabaseService());
+ gdc.setConversionService(conversionService());
+ gdc.setNodeTypeRepresentationStrategy(typeRepresentationStrategyFactory.getNodeTypeRepresentationStrategy());
+ gdc.setRelationshipTypeRepresentationStrategy(typeRepresentationStrategyFactory.getRelationshipTypeRepresentationStrategy());
if (validator!=null) {
gdc.setValidator(validator);
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeEntityState.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeEntityState.java
index 5a013d8dc..90130531a 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeEntityState.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/NodeEntityState.java
@@ -54,7 +54,7 @@ public class NodeEntityState extends DefaultEntitySta
final Node node = graphDatabaseContext.createNode();
setPersistentState(node);
if (log.isInfoEnabled()) log.info("User-defined constructor called on class " + entity.getClass() + "; created Node [" + getPersistentState() + "]; Updating metamodel");
- graphDatabaseContext.postEntityCreation(entity);
+ graphDatabaseContext.postEntityCreation(node, type);
} catch (NotInTransactionException e) {
throw new InvalidDataAccessResourceUsageException("Not in a Neo4j transaction.", e);
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/PartialNodeEntityState.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/PartialNodeEntityState.java
index 86c6491c1..d8dead1ee 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/PartialNodeEntityState.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/fieldaccess/PartialNodeEntityState.java
@@ -119,7 +119,7 @@ public class PartialNodeEntityState extends DefaultEn
persistForeignId(node, id);
setPersistentState(node);
log.info("User-defined constructor called on class " + entity.getClass() + "; created Node [" + entity.getPersistentState() + "]; Updating metamodel");
- graphDatabaseContext.postEntityCreation(entity);
+ graphDatabaseContext.postEntityCreation(node, type);
} else {
setPersistentState(node);
entity.setPersistentState(node);
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/GraphDatabaseContext.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/GraphDatabaseContext.java
index 751f80e09..95a6e1316 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/GraphDatabaseContext.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/GraphDatabaseContext.java
@@ -25,11 +25,7 @@ import org.neo4j.index.impl.lucene.LuceneIndexImplementation;
import org.neo4j.kernel.AbstractGraphDatabase;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.annotation.Indexed;
-import org.springframework.data.graph.core.GraphBacked;
-import org.springframework.data.graph.core.NodeBacked;
-import org.springframework.data.graph.core.TypeRepresentationStrategy;
-import org.springframework.data.graph.core.RelationshipBacked;
-import org.springframework.data.persistence.EntityInstantiator;
+import org.springframework.data.graph.core.*;
import javax.transaction.Status;
import javax.transaction.SystemException;
@@ -53,13 +49,10 @@ public class GraphDatabaseContext {
private GraphDatabaseService graphDatabaseService;
- public EntityInstantiator graphEntityInstantiator;
-
- public EntityInstantiator relationshipEntityInstantiator;
-
private ConversionService conversionService;
- private TypeRepresentationStrategy typeRepresentationStrategy;
+ private NodeTypeRepresentationStrategy nodeTypeRepresentationStrategy;
+ private RelationshipTypeRepresentationStrategy relationshipTypeRepresentationStrategy;
private Validator validator;
@@ -73,25 +66,23 @@ public class GraphDatabaseContext {
this.graphDatabaseService = graphDatabaseService;
}
- public EntityInstantiator getGraphEntityInstantiator() {
- return graphEntityInstantiator;
- }
+ public NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy() {
+ return nodeTypeRepresentationStrategy;
+ }
- public void setGraphEntityInstantiator(
- EntityInstantiator graphEntityInstantiator) {
- this.graphEntityInstantiator = graphEntityInstantiator;
- }
+ public void setNodeTypeRepresentationStrategy(NodeTypeRepresentationStrategy nodeTypeRepresentationStrategy) {
+ this.nodeTypeRepresentationStrategy = nodeTypeRepresentationStrategy;
+ }
- public EntityInstantiator getRelationshipEntityInstantiator() {
- return relationshipEntityInstantiator;
- }
+ public RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy() {
+ return relationshipTypeRepresentationStrategy;
+ }
- public void setRelationshipEntityInstantiator(
- EntityInstantiator relationshipEntityInstantiator) {
- this.relationshipEntityInstantiator = relationshipEntityInstantiator;
- }
+ public void setRelationshipTypeRepresentationStrategy(RelationshipTypeRepresentationStrategy relationshipTypeRepresentationStrategy) {
+ this.relationshipTypeRepresentationStrategy = relationshipTypeRepresentationStrategy;
+ }
- public ConversionService getConversionService() {
+ public ConversionService getConversionService() {
return conversionService;
}
@@ -99,14 +90,6 @@ public class GraphDatabaseContext {
this.conversionService = conversionService;
}
- public TypeRepresentationStrategy getTypeRepresentationStrategy() {
- return typeRepresentationStrategy;
- }
-
- public void setTypeRepresentationStrategy(TypeRepresentationStrategy typeRepresentationStrategy) {
- this.typeRepresentationStrategy = typeRepresentationStrategy;
- }
-
public Node createNode() {
return graphDatabaseService.createNode();
}
@@ -136,16 +119,18 @@ public class GraphDatabaseContext {
* but all modifications will throw an exception
* @param entity to remove
*/
+ // TODO: What about connected relationship entities?
public void removeNodeEntity(NodeBacked entity) {
Node node = entity.getPersistentState();
if (node==null) return;
- this.typeRepresentationStrategy.preEntityRemoval(entity);
+ nodeTypeRepresentationStrategy.preEntityRemoval(entity);
for (Relationship relationship : node.getRelationships()) {
removeRelationship(relationship);
}
removeFromIndexes(node);
node.delete();
}
+
public void removeRelationshipEntity(RelationshipBacked entity) {
Relationship relationship = entity.getPersistentState();
if (relationship==null) return;
@@ -170,10 +155,12 @@ public class GraphDatabaseContext {
*/
public T createEntityFromState(final S state, final Class type) {
if (state==null) throw new IllegalArgumentException("state has to be either a Node or Relationship, not null");
- if (state instanceof Node)
- return (T) graphEntityInstantiator.createEntityFromState((Node) state, typeRepresentationStrategy.confirmType((Node)state, (Class extends NodeBacked>)type));
+ if (state instanceof Node && NodeBacked.class.isAssignableFrom(type))
+ return (T) nodeTypeRepresentationStrategy.createEntity((Node) state, (Class) type);
+// return (T) graphEntityInstantiator.createEntityFromState((Node) state, typeRepresentationStrategy.confirmType((Node)state, (Class extends NodeBacked>)type));
else
- return (T) relationshipEntityInstantiator.createEntityFromState((Relationship) state, (Class extends RelationshipBacked>) type);
+ return (T) relationshipTypeRepresentationStrategy.createEntity((Relationship) state, (Class) type);
+// return (T) relationshipEntityInstantiator.createEntityFromState((Relationship) state, (Class extends RelationshipBacked>) type);
}
private IndexManager getIndexManager() {
@@ -215,10 +202,19 @@ public class GraphDatabaseContext {
/**
* delegates to the configured @{link TypeRepresentationStrategy} for after entity creation operations
- * @param entity
+ * @param node
+ * @param entityClass
*/
- public void postEntityCreation(final NodeBacked entity) {
- typeRepresentationStrategy.postEntityCreation(entity);
+ public void postEntityCreation(Node node, final Class extends NodeBacked> entityClass) {
+ nodeTypeRepresentationStrategy.postEntityCreation(node, entityClass);
+ }
+ /**
+ * delegates to the configured @{link TypeRepresentationStrategy} for after entity creation operations
+ * @param relationship
+ * @param entityClass
+ */
+ public void postEntityCreation(Relationship relationship, final Class extends RelationshipBacked> entityClass) {
+ relationshipTypeRepresentationStrategy.postEntityCreation(relationship, entityClass);
}
/**
@@ -230,7 +226,7 @@ public class GraphDatabaseContext {
*/
public Iterable findAll(final Class clazz) {
if (!checkIsNodeBacked(clazz)) throw new UnsupportedOperationException("No support for relationships");
- return (Iterable) typeRepresentationStrategy.findAll((Class)clazz);
+ return (Iterable) nodeTypeRepresentationStrategy.findAll((Class)clazz);
}
/**
@@ -247,7 +243,7 @@ public class GraphDatabaseContext {
*/
public long count(final Class extends GraphBacked> entityClass) {
if (!checkIsNodeBacked(entityClass)) throw new UnsupportedOperationException("No support for relationships");
- return typeRepresentationStrategy.count((Class)entityClass);
+ return nodeTypeRepresentationStrategy.count((Class)entityClass);
}
/**
@@ -258,7 +254,7 @@ public class GraphDatabaseContext {
* @throws IllegalStateException for nodes that are not instance backing nodes of a known type
*/
public Class getJavaType(final Node node) {
- return typeRepresentationStrategy.getJavaType(node);
+ return nodeTypeRepresentationStrategy.getJavaType(node);
}
/**
@@ -313,9 +309,9 @@ public class GraphDatabaseContext {
public T projectTo(GraphBacked entity, Class targetType) {
final Object state = entity.getPersistentState();
if (state instanceof Node)
- return (T) graphEntityInstantiator.createEntityFromState((Node) state, (Class extends NodeBacked>) targetType);
+ return (T) nodeTypeRepresentationStrategy.projectEntity((Node) state, (Class) targetType);
else
- return (T) relationshipEntityInstantiator.createEntityFromState((Relationship) state, (Class extends RelationshipBacked>) targetType);
+ return (T) relationshipTypeRepresentationStrategy.projectEntity((Relationship) state, (Class) targetType);
}
public Validator getValidator() {
@@ -327,7 +323,7 @@ public class GraphDatabaseContext {
}
public T createEntityFromStoredType(Node node) {
- return (T)graphEntityInstantiator.createEntityFromState(node, typeRepresentationStrategy.getJavaType(node));
+ return nodeTypeRepresentationStrategy.createEntity(node);
}
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeRepresentationStrategy.java
new file mode 100644
index 000000000..f1af715f5
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeRepresentationStrategy.java
@@ -0,0 +1,146 @@
+package org.springframework.data.graph.neo4j.support;
+
+import org.neo4j.graphdb.*;
+import org.neo4j.graphdb.index.Index;
+import org.neo4j.graphdb.index.IndexHits;
+import org.neo4j.helpers.Predicate;
+import org.neo4j.helpers.collection.FilteringIterable;
+import org.neo4j.helpers.collection.IterableWrapper;
+import org.springframework.data.graph.annotation.NodeEntity;
+import org.springframework.data.graph.core.GraphBacked;
+import org.springframework.data.graph.core.NodeBacked;
+import org.springframework.data.graph.core.NodeTypeRepresentationStrategy;
+import org.springframework.data.persistence.EntityInstantiator;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class IndexingNodeTypeRepresentationStrategy implements NodeTypeRepresentationStrategy {
+
+ public static final String INDEX_NAME = "__types__";
+ public static final String TYPE_PROPERTY_NAME = "__type__";
+ public static final String INDEX_KEY = "className";
+ private EntityInstantiator graphEntityInstantiator;
+ private GraphDatabaseService graphDb;
+ private final Map> cache=new HashMap>();
+
+ public IndexingNodeTypeRepresentationStrategy(GraphDatabaseService graphDb,
+ EntityInstantiator graphEntityInstantiator) {
+ this.graphDb = graphDb;
+ this.graphEntityInstantiator = graphEntityInstantiator;
+ }
+
+ private Index getNodeTypesIndex() {
+ return graphDb.index().forNodes(INDEX_NAME);
+ }
+
+ private Index getRelTypesIndex() {
+ return graphDb.index().forRelationships(INDEX_NAME);
+ }
+
+ @Override
+ public void postEntityCreation(Node state, Class extends NodeBacked> type) {
+ addToNodeTypesIndex(state, type);
+ state.setProperty(TYPE_PROPERTY_NAME, type.getName());
+ }
+
+ private void addToNodeTypesIndex(Node node, Class extends NodeBacked> entityClass) {
+ Class> klass = entityClass;
+ while (klass.getAnnotation(NodeEntity.class) != null) {
+ getNodeTypesIndex().add(node, INDEX_KEY, klass.getName());
+ klass = klass.getSuperclass();
+ }
+ }
+
+ @Override
+ public Iterable findAll(Class clazz) {
+ return findAllNodeBacked(clazz);
+ }
+
+ private Iterable findAllNodeBacked(Class clazz) {
+ final IndexHits allEntitiesOfType = getNodeTypesIndex().get(INDEX_KEY, clazz.getName());
+ return new FilteringIterable(new IterableWrapper(allEntitiesOfType) {
+ @Override
+ @SuppressWarnings("unchecked")
+ protected ENTITY underlyingObjectToObject(Node node) {
+ Class javaType = (Class) getJavaType(node);
+ if (javaType == null) return null;
+ return graphEntityInstantiator.createEntityFromState(node, javaType);
+ }
+ }, new Predicate() {
+ @Override
+ public boolean accept(ENTITY item) {
+ return item != null;
+ }
+ });
+ }
+
+ @Override
+ public long count(Class extends NodeBacked> entityClass) {
+ long count = 0;
+ for (Object o : getNodeTypesIndex().get(INDEX_KEY, entityClass.getName())) {
+ count += 1;
+ }
+ return count;
+ }
+
+
+ @Override
+ public Class extends NodeBacked> getJavaType(Node node) {
+ if (node == null) throw new IllegalArgumentException("Node is null");
+ String className = (String) node.getProperty(TYPE_PROPERTY_NAME);
+ return getClassForName(className);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private > Class getClassForName(String className) {
+ try {
+ Class result= (Class) cache.get(className);
+ if (result!=null) return result;
+ synchronized (cache) {
+ result= (Class) cache.get(className);
+ if (result!=null) return result;
+ result = (Class) Class.forName(className);
+ cache.put(className,result);
+ return result;
+ }
+ } catch (NotFoundException e) {
+ return null;
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public void preEntityRemoval(NodeBacked entity) {
+ getNodeTypesIndex().remove(entity.getPersistentState());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public U createEntity(Node state) {
+ Class extends NodeBacked> javaType = getJavaType(state);
+ if (javaType == null) {
+ throw new IllegalStateException("No type stored on node.");
+ }
+ return (U) graphEntityInstantiator.createEntityFromState(state, javaType);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public U createEntity(Node state, Class type) {
+ Class extends NodeBacked> javaType = getJavaType(state);
+ if (javaType == null) {
+ throw new IllegalStateException("No type stored on node.");
+ }
+ if (type.isAssignableFrom(javaType)) {
+ return (U) graphEntityInstantiator.createEntityFromState(state, javaType);
+ }
+ throw new IllegalArgumentException(String.format("Entity is not of type: %s (was %s)", type, javaType));
+ }
+
+ @Override
+ public U projectEntity(Node state, Class type) {
+ return graphEntityInstantiator.createEntityFromState(state, type);
+ }
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingRelationshipTypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingRelationshipTypeRepresentationStrategy.java
new file mode 100644
index 000000000..2cd60b633
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingRelationshipTypeRepresentationStrategy.java
@@ -0,0 +1,151 @@
+package org.springframework.data.graph.neo4j.support;
+
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.NotFoundException;
+import org.neo4j.graphdb.Relationship;
+import org.neo4j.graphdb.index.Index;
+import org.neo4j.graphdb.index.IndexHits;
+import org.neo4j.helpers.Predicate;
+import org.neo4j.helpers.collection.FilteringIterable;
+import org.neo4j.helpers.collection.IterableWrapper;
+import org.springframework.data.graph.annotation.RelationshipEntity;
+import org.springframework.data.graph.core.GraphBacked;
+import org.springframework.data.graph.core.RelationshipBacked;
+import org.springframework.data.graph.core.RelationshipTypeRepresentationStrategy;
+import org.springframework.data.persistence.EntityInstantiator;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class IndexingRelationshipTypeRepresentationStrategy implements RelationshipTypeRepresentationStrategy {
+
+ public static final String INDEX_NAME = "__types__";
+ public static final String TYPE_PROPERTY_NAME = "__type__";
+ public static final String INDEX_KEY = "className";
+ private EntityInstantiator relationshipEntityInstantiator;
+ private GraphDatabaseService graphDb;
+ private final Map> cache=new HashMap>();
+
+ public IndexingRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDb,
+ EntityInstantiator relationshipEntityInstantiator) {
+ this.graphDb = graphDb;
+ this.relationshipEntityInstantiator = relationshipEntityInstantiator;
+ }
+
+ private Index getNodeTypesIndex() {
+ return graphDb.index().forNodes(INDEX_NAME);
+ }
+
+ private Index getRelTypesIndex() {
+ return graphDb.index().forRelationships(INDEX_NAME);
+ }
+
+ @Override
+ public void postEntityCreation(Relationship state, Class extends RelationshipBacked> type) {
+ addToTypesIndex(state, type);
+ state.setProperty(TYPE_PROPERTY_NAME, type.getName());
+ }
+
+ private void addToTypesIndex(Relationship node, Class extends RelationshipBacked> entityClass) {
+ Class> klass = entityClass;
+ while (klass.getAnnotation(RelationshipEntity.class) != null) {
+ getRelTypesIndex().add(node, INDEX_KEY, klass.getName());
+ klass = klass.getSuperclass();
+ }
+ }
+
+ @Override
+ public Iterable findAll(Class clazz) {
+ return findAllRelBacked(clazz);
+ }
+
+ private Iterable findAllRelBacked(Class clazz) {
+ final IndexHits allEntitiesOfType = getRelTypesIndex().get(INDEX_KEY, clazz.getName());
+ return new FilteringIterable(new IterableWrapper(allEntitiesOfType) {
+ @Override
+ @SuppressWarnings("unchecked")
+ protected ENTITY underlyingObjectToObject(Relationship rel) {
+ Class javaType = (Class) getJavaType(rel);
+ if (javaType == null) return null;
+ return relationshipEntityInstantiator.createEntityFromState(rel, javaType);
+ }
+ }, new Predicate() {
+ @Override
+ public boolean accept(ENTITY item) {
+ return item != null;
+ }
+ });
+
+ }
+
+
+ @Override
+ public long count(Class extends RelationshipBacked> entityClass) {
+ long count = 0;
+ for (Object o : getRelTypesIndex().get(INDEX_KEY, entityClass.getName())) {
+ count += 1;
+ }
+ return count;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Class extends RelationshipBacked> getJavaType(Relationship relationship) {
+ if (relationship == null) throw new IllegalArgumentException("Node is null");
+ String className = (String) relationship.getProperty(TYPE_PROPERTY_NAME);
+ return getClassForName(className);
+ }
+
+ @SuppressWarnings({"unchecked"})
+ private > Class getClassForName(String className) {
+ try {
+ Class result= (Class) cache.get(className);
+ if (result!=null) return result;
+ synchronized (cache) {
+ result= (Class) cache.get(className);
+ if (result!=null) return result;
+ result = (Class) Class.forName(className);
+ cache.put(className,result);
+ return result;
+ }
+ } catch (NotFoundException e) {
+ return null;
+ } catch (ClassNotFoundException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public void preEntityRemoval(RelationshipBacked entity) {
+ getRelTypesIndex().remove(entity.getPersistentState());
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public U createEntity(Relationship state) {
+ Class extends RelationshipBacked> javaType = getJavaType(state);
+ if (javaType == null) {
+ throw new IllegalStateException("No type stored on relationship.");
+ }
+ return (U) relationshipEntityInstantiator.createEntityFromState(state, javaType);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public U createEntity(Relationship state, Class type) {
+ Class extends RelationshipBacked> javaType = getJavaType(state);
+ if (javaType == null) {
+ throw new IllegalStateException("No type stored on relationship.");
+ }
+ if (type.isAssignableFrom(javaType)) {
+ return (U) relationshipEntityInstantiator.createEntityFromState(state, javaType);
+ }
+ throw new IllegalArgumentException(String.format("Entity is not of type: %s (was %s)", type, javaType));
+ }
+
+ @Override
+ public U projectEntity(Relationship state, Class type) {
+ return relationshipEntityInstantiator.createEntityFromState(state, type);
+ }
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingTypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingTypeRepresentationStrategy.java
deleted file mode 100644
index 05584ea4f..000000000
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingTypeRepresentationStrategy.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package org.springframework.data.graph.neo4j.support;
-
-import org.neo4j.graphdb.*;
-import org.neo4j.graphdb.index.Index;
-import org.neo4j.graphdb.index.IndexHits;
-import org.neo4j.helpers.Predicate;
-import org.neo4j.helpers.collection.FilteringIterable;
-import org.neo4j.helpers.collection.IterableWrapper;
-import org.springframework.data.graph.annotation.NodeEntity;
-import org.springframework.data.graph.core.GraphBacked;
-import org.springframework.data.graph.core.NodeBacked;
-import org.springframework.data.graph.core.RelationshipBacked;
-import org.springframework.data.graph.core.TypeRepresentationStrategy;
-import org.springframework.data.persistence.EntityInstantiator;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class IndexingTypeRepresentationStrategy implements TypeRepresentationStrategy {
-
- public static final String INDEX_NAME = "__types__";
- public static final String TYPE_PROPERTY_NAME = "__type__";
- public static final String INDEX_KEY = "className";
- private EntityInstantiator graphEntityInstantiator;
- private EntityInstantiator relationshipEntityInstantiator;
- private GraphDatabaseService graphDb;
- private final Map> cache=new HashMap>();
-
- public IndexingTypeRepresentationStrategy(GraphDatabaseService graphDb,
- EntityInstantiator graphEntityInstantiator,
- EntityInstantiator relationshipEntityInstantiator) {
- this.graphDb = graphDb;
- this.graphEntityInstantiator = graphEntityInstantiator;
- this.relationshipEntityInstantiator = relationshipEntityInstantiator;
- }
-
- private Index getNodeTypesIndex() {
- return graphDb.index().forNodes(INDEX_NAME);
- }
-
- private Index getRelTypesIndex() {
- return graphDb.index().forRelationships(INDEX_NAME);
- }
-
- @Override
- public void postEntityCreation(GraphBacked> entity) {
- if (entity instanceof NodeBacked) {
- NodeBacked nodeBacked = (NodeBacked) entity;
- Node node = nodeBacked.getPersistentState();
- Class extends NodeBacked> entityClass = nodeBacked.getClass();
- addToNodeTypesIndex(node, entityClass);
- node.setProperty(TYPE_PROPERTY_NAME, entityClass.getName());
- } else if (entity instanceof RelationshipBacked) {
- RelationshipBacked relationshipBacked = (RelationshipBacked) entity;
- Relationship rel = relationshipBacked.getPersistentState();
- Class extends RelationshipBacked> entityClass = relationshipBacked.getClass();
- addToRelTypesIndex(rel, entityClass);
- rel.setProperty(TYPE_PROPERTY_NAME, entityClass.getName());
- }
- }
-
- private void addToRelTypesIndex(Relationship rel, Class extends RelationshipBacked> entityClass) {
- getRelTypesIndex().add(rel, INDEX_KEY, entityClass.getName());
- }
-
- private void addToNodeTypesIndex(Node node, Class extends NodeBacked> entityClass) {
- Class> klass = entityClass;
- while (klass.getAnnotation(NodeEntity.class) != null) {
- getNodeTypesIndex().add(node, INDEX_KEY, klass.getName());
- klass = klass.getSuperclass();
- }
- }
-
- @Override
- public > Iterable findAll(Class clazz) {
- if (NodeBacked.class.isAssignableFrom(clazz)) {
- return (Iterable) findAllNodeBacked((Class extends NodeBacked>) clazz);
- } else if (RelationshipBacked.class.isAssignableFrom(clazz)) {
- return (Iterable) findAllRelBacked((Class extends RelationshipBacked>) clazz);
- }
- throw new UnsupportedOperationException();
- }
-
- private Iterable findAllRelBacked(Class clazz) {
- final IndexHits allEntitiesOfType = getRelTypesIndex().get(INDEX_KEY, clazz.getName());
- return new FilteringIterable(new IterableWrapper(allEntitiesOfType) {
- @Override
- @SuppressWarnings("unchecked")
- protected ENTITY underlyingObjectToObject(Relationship rel) {
- Class javaType = (Class) getJavaType(rel);
- if (javaType == null) return null;
- return relationshipEntityInstantiator.createEntityFromState(rel, javaType);
- }
- }, new Predicate() {
- @Override
- public boolean accept(ENTITY item) {
- return item != null;
- }
- });
-
- }
-
- private Iterable findAllNodeBacked(Class clazz) {
- final IndexHits allEntitiesOfType = getNodeTypesIndex().get(INDEX_KEY, clazz.getName());
- return new FilteringIterable(new IterableWrapper(allEntitiesOfType) {
- @Override
- @SuppressWarnings("unchecked")
- protected ENTITY underlyingObjectToObject(Node node) {
- Class javaType = (Class) getJavaType(node);
- if (javaType == null) return null;
- return graphEntityInstantiator.createEntityFromState(node, javaType);
- }
- }, new Predicate() {
- @Override
- public boolean accept(ENTITY item) {
- return item != null;
- }
- });
- }
-
- @Override
- public long count(Class extends GraphBacked>> entityClass) {
- long count = 0;
- for (Object o : getIndexForType(entityClass).get(INDEX_KEY, entityClass.getName())) {
- count += 1;
- }
- return count;
- }
-
- private Index> getIndexForType(Class extends GraphBacked>> entityClass) {
- if (NodeBacked.class.isAssignableFrom(entityClass)) {
- return getNodeTypesIndex();
- } else if (RelationshipBacked.class.isAssignableFrom(entityClass)) {
- return getRelTypesIndex();
- }
- throw new UnsupportedOperationException();
- }
-
- @Override
- @SuppressWarnings("unchecked")
- public > Class getJavaType(PropertyContainer primitive) {
- if (primitive == null) throw new IllegalArgumentException("Node is null");
- String className = (String) primitive.getProperty(TYPE_PROPERTY_NAME);
- return getClassForName(className);
- }
-
- @SuppressWarnings({"unchecked"})
- private > Class getClassForName(String className) {
- try {
- Class result= (Class) cache.get(className);
- if (result!=null) return result;
- synchronized (cache) {
- result= (Class) cache.get(className);
- if (result!=null) return result;
- result = (Class) Class.forName(className);
- cache.put(className,result);
- return result;
- }
- } catch (NotFoundException e) {
- return null;
- } catch (ClassNotFoundException e) {
- return null;
- }
- }
-
- @Override
- public void preEntityRemoval(GraphBacked> entity) {
- if (entity instanceof NodeBacked) {
- getNodeTypesIndex().remove(((NodeBacked)entity).getPersistentState());
- } else if (entity instanceof RelationshipBacked) {
- getRelTypesIndex().remove(((RelationshipBacked)entity).getPersistentState());
- }
- }
-
- @Override
- public > Class confirmType(PropertyContainer primitive, Class type) {
- Class javaType = getJavaType(primitive);
- if (javaType == null) throw new IllegalStateException("No type stored on node.");
- if (type.isAssignableFrom(javaType)) return javaType;
- throw new IllegalArgumentException(String.format("%s does not correspond to the stored type %s of %s %s",
- type, javaType, primitive instanceof Node ? "node" : "relationship", primitive));
- }
-}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NoopTypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NoopTypeRepresentationStrategy.java
index 8ce879106..55d1025b0 100644
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NoopTypeRepresentationStrategy.java
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NoopTypeRepresentationStrategy.java
@@ -1,36 +1,92 @@
package org.springframework.data.graph.neo4j.support;
-import org.neo4j.graphdb.PropertyContainer;
-import org.springframework.data.graph.core.GraphBacked;
-import org.springframework.data.graph.core.TypeRepresentationStrategy;
+import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.Relationship;
+import org.springframework.data.graph.core.NodeBacked;
+import org.springframework.data.graph.core.NodeTypeRepresentationStrategy;
+import org.springframework.data.graph.core.RelationshipBacked;
+import org.springframework.data.graph.core.RelationshipTypeRepresentationStrategy;
-public class NoopTypeRepresentationStrategy implements TypeRepresentationStrategy {
+public class NoopTypeRepresentationStrategy {
+ public static class NoopNodeStrategy implements NodeTypeRepresentationStrategy {
- @Override
- public void postEntityCreation(GraphBacked> entity) {
+ @Override
+ public void postEntityCreation(Node state, Class extends NodeBacked> type) {
+ }
+
+ @Override
+ public Iterable findAll(Class clazz) {
+ throw new UnsupportedOperationException("findAll not supported by NoopTypeRepresentationStrategy.");
+ }
+
+ @Override
+ public long count(Class extends NodeBacked> entityClass) {
+ throw new UnsupportedOperationException("count not supported by NoopTypeRepresentationStrategy.");
+ }
+
+ @Override
+ public Class extends NodeBacked> getJavaType(Node state) {
+ throw new UnsupportedOperationException("getJavaType not supported by NoopTypeRepresentationStrategy.");
+ }
+
+ @Override
+ public void preEntityRemoval(NodeBacked entity) {
+ }
+
+ @Override
+ public U createEntity(Node state) {
+ throw new UnsupportedOperationException("Creation with stored type not supported by NoopTypeRepresentationStrategy.");
+ }
+
+ @Override
+ public U createEntity(Node state, Class type) {
+ return projectEntity(state, type);
+ }
+
+ @Override
+ public U projectEntity(Node state, Class type) {
+ return null;
+ }
}
- @Override
- public > Iterable findAll(Class clazz) {
- throw new UnsupportedOperationException("findAll not supported by NoopTypeRepresentationStrategy.");
- }
+ public static class NoopRelationshipStrategy implements RelationshipTypeRepresentationStrategy {
- @Override
- public long count(Class extends GraphBacked>> entityClass) {
- throw new UnsupportedOperationException("count not supported by NoopTypeRepresentationStrategy.");
- }
+ @Override
+ public void postEntityCreation(Relationship state, Class extends RelationshipBacked> type) {
+ }
- @Override
- public > Class getJavaType(PropertyContainer primitive) {
- throw new UnsupportedOperationException("getJavaType not supported NoopTypeRepresentationStrategy.");
- }
+ @Override
+ public Iterable findAll(Class clazz) {
+ throw new UnsupportedOperationException("findAll not supported by NoopTypeRepresentationStrategy.");
+ }
- @Override
- public void preEntityRemoval(GraphBacked> entity) {
- }
+ @Override
+ public long count(Class extends RelationshipBacked> entityClass) {
+ throw new UnsupportedOperationException("count not supported by NoopTypeRepresentationStrategy.");
+ }
- @Override
- public > Class confirmType(PropertyContainer node, Class type) {
- return type;
+ @Override
+ public Class extends RelationshipBacked> getJavaType(Relationship state) {
+ throw new UnsupportedOperationException("getJavaType not supported by NoopTypeRepresentationStrategy.");
+ }
+
+ @Override
+ public void preEntityRemoval(RelationshipBacked entity) {
+ }
+
+ @Override
+ public U createEntity(Relationship state) {
+ throw new UnsupportedOperationException("Creation with stored type not supported by NoopTypeRepresentationStrategy.");
+ }
+
+ @Override
+ public U createEntity(Relationship state, Class type) {
+ return projectEntity(state, type);
+ }
+
+ @Override
+ public U projectEntity(Relationship state, Class type) {
+ return null;
+ }
}
}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeRepresentationStrategy.java
new file mode 100644
index 000000000..1125a4817
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeRepresentationStrategy.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.data.graph.neo4j.support;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.neo4j.graphdb.*;
+import org.neo4j.graphdb.traversal.TraversalDescription;
+import org.neo4j.helpers.collection.CombiningIterable;
+import org.neo4j.helpers.collection.IterableWrapper;
+import org.neo4j.kernel.Traversal;
+import org.springframework.data.graph.core.NodeBacked;
+import org.springframework.data.graph.core.NodeTypeRepresentationStrategy;
+import org.springframework.data.persistence.EntityInstantiator;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A {@link org.springframework.data.graph.core.TypeRepresentationStrategy} that uses a hierarchy of reference nodes to represent the java type of the entity in the
+ * graph database. Entity nodes are related to their concrete type via an INSTANCE_OF relationship, the type hierarchy is
+ * related to supertypes via SUBCLASS_OF relationships. Each concrete subreference node keeps a count property with the number of
+ * instances of this class in the graph.
+ *
+ * @author Michael Hunger
+ * @since 13.09.2010
+ */
+public class SubReferenceNodeTypeRepresentationStrategy implements NodeTypeRepresentationStrategy {
+ private final static Log log = LogFactory.getLog(SubReferenceNodeTypeRepresentationStrategy.class);
+
+ public final static RelationshipType INSTANCE_OF_RELATIONSHIP_TYPE = DynamicRelationshipType.withName("INSTANCE_OF");
+ public final static RelationshipType SUBCLASS_OF_RELATIONSHIP_TYPE = DynamicRelationshipType.withName("SUBCLASS_OF");
+
+ public static final String SUBREFERENCE_NODE_COUNTER_KEY = "count";
+ public static final String SUBREF_PREFIX = "SUBREF_";
+ public static final String SUBREF_CLASS_KEY = "class";
+
+ private GraphDatabaseService graphDatabaseService;
+ private EntityInstantiator entityInstantiator;
+
+ public SubReferenceNodeTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator entityInstantiator) {
+ this.graphDatabaseService = graphDatabaseService;
+ this.entityInstantiator = entityInstantiator;
+ }
+
+ public static Node getSingleOtherNode(Node node, RelationshipType type,
+ Direction direction) {
+ Relationship rel = node.getSingleRelationship(type, direction);
+ return rel == null ? null : rel.getOtherNode(node);
+ }
+
+ public static Integer incrementAndGetCounter(Node node, String propertyKey) {
+ acquireWriteLock(node);
+ int value = (Integer) node.getProperty(propertyKey, 0);
+ value++;
+ node.setProperty(propertyKey, value);
+ return value;
+ }
+
+ public static Integer decrementAndGetCounter(Node node, String propertyKey,
+ int notLowerThan) {
+ int value = (Integer) node.getProperty(propertyKey, 0);
+ value--;
+ value = value < notLowerThan ? notLowerThan : value;
+ node.setProperty(propertyKey, value);
+ return value;
+ }
+
+ public static void acquireWriteLock(PropertyContainer entity) {
+ // TODO At the moment this is the best way of doing it, if you don't want to use
+ // the LockManager (and release the lock yourself)
+ entity.removeProperty("___dummy_property_for_locking___");
+ }
+
+ @Override
+ public void postEntityCreation(Node state, Class extends NodeBacked> type) {
+ final Node subReference = obtainSubreferenceNode(type);
+ state.createRelationshipTo(subReference, INSTANCE_OF_RELATIONSHIP_TYPE);
+ subReference.setProperty(SUBREF_CLASS_KEY, type.getName());
+ if (log.isDebugEnabled()) log.debug("Created link to subref node: " + subReference + " with type: " + type.getName());
+
+ incrementAndGetCounter(subReference, SUBREFERENCE_NODE_COUNTER_KEY);
+
+ updateSuperClassSubrefs(type, subReference);
+ }
+
+ /**
+ * removes instanceof relationship and decrements instance counters for type nodes
+ * @param entity
+ */
+ @Override
+ public void preEntityRemoval(NodeBacked entity) {
+ Class extends NodeBacked> clazz = entity.getClass();
+
+ final Node subReference = obtainSubreferenceNode(clazz);
+ Node subRefNode = entity.getPersistentState();
+ Relationship instanceOf = subRefNode.getSingleRelationship(INSTANCE_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
+ instanceOf.delete();
+ if (log.isDebugEnabled()) log.debug("Removed link to subref node: " + subReference + " with type: " + clazz.getName());
+ TraversalDescription traversal = Traversal.description().depthFirst().relationships(SUBCLASS_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
+ for (Node node : traversal.traverse(subReference).nodes()) {
+ Integer count = (Integer) node.getProperty(SUBREFERENCE_NODE_COUNTER_KEY);
+ Integer newCount = decrementAndGetCounter(node, SUBREFERENCE_NODE_COUNTER_KEY, 0);
+ if (log.isDebugEnabled()) log.debug("count on ref " + node + " was " + count + " new " + newCount);
+ }
+ }
+
+// @Override
+// public Class confirmType(Node node, Class type) {
+// Class nodeType = this.getJavaType(node);
+// if (type.isAssignableFrom(nodeType)) return nodeType;
+// throw new IllegalArgumentException(String.format("%s does not correspond to the node type %s of node %s",type,nodeType,node));
+// }
+
+ private void updateSuperClassSubrefs(Class> clazz, Node subReference) {
+ Class> superClass = clazz.getSuperclass();
+ if (superClass != null) {
+ Node superClassSubref = obtainSubreferenceNode(superClass);
+ if (getSingleOtherNode(subReference, SUBCLASS_OF_RELATIONSHIP_TYPE, Direction.OUTGOING) == null) {
+ subReference.createRelationshipTo(superClassSubref, SUBCLASS_OF_RELATIONSHIP_TYPE);
+ }
+ superClassSubref.setProperty(SUBREF_CLASS_KEY, superClass.getName());
+ Integer count = incrementAndGetCounter(superClassSubref, SUBREFERENCE_NODE_COUNTER_KEY);
+ if (log.isDebugEnabled()) log.debug("count on ref " + superClassSubref + " for class " + superClass.getSimpleName() + " = " + count);
+ updateSuperClassSubrefs(superClass, superClassSubref);
+ }
+ }
+
+ @Override
+ public long count(final Class extends NodeBacked> entityClass) {
+ final Node subrefNode = findSubreferenceNode(entityClass);
+ if (subrefNode == null) return 0;
+ return (Integer) subrefNode.getProperty(SUBREFERENCE_NODE_COUNTER_KEY, 0);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Class getJavaType(Node node) {
+ if (node==null) throw new IllegalArgumentException("Node is null");
+ Relationship instanceOfRelationship = node.getSingleRelationship(INSTANCE_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
+ if (instanceOfRelationship==null) throw new IllegalArgumentException("The node "+node+" is not attached to a type hierarchy.");
+ Node subrefNode = instanceOfRelationship.getEndNode();
+ try {
+ Class clazz = (Class) Class.forName((String) subrefNode.getProperty(SUBREF_CLASS_KEY)).asSubclass(NodeBacked.class);
+ if (log.isDebugEnabled()) log.debug("Found class " + clazz.getSimpleName() + " for node: " + node);
+ return clazz;
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Unable to get type for node: " + node, e);
+ }
+ }
+
+ @Override
+ public Iterable findAll(final Class clazz) {
+ final Node subrefNode = findSubreferenceNode(clazz);
+ if (log.isDebugEnabled()) log.debug("Subref: " + subrefNode);
+ Iterable> relIterables = findEntityIterables(subrefNode);
+ return new CombiningIterable(relIterables);
+ }
+
+ private List> findEntityIterables(Node subrefNode) {
+ if (subrefNode == null) return Collections.emptyList();
+ List> result = new LinkedList>();
+ for (Relationship relationship : subrefNode.getRelationships(SUBCLASS_OF_RELATIONSHIP_TYPE, Direction.INCOMING)) {
+ result.addAll((Collection extends Iterable>) findEntityIterables(relationship.getStartNode()));
+ }
+ Iterable t = new IterableWrapper(subrefNode.getRelationships(INSTANCE_OF_RELATIONSHIP_TYPE, Direction.INCOMING)) {
+ @Override
+ protected T underlyingObjectToObject(final Relationship rel) {
+ final Node node = rel.getStartNode();
+ T entity = (T) entityInstantiator.createEntityFromState(node, getJavaType(node));
+ if (log.isDebugEnabled()) log.debug("Converting node: " + node + " to entity: " + entity);
+ return entity;
+ }
+ };
+ result.add(t);
+ return result;
+ }
+
+
+ public Node obtainSubreferenceNode(final Class> entityClass) {
+ return getOrCreateSubReferenceNode(subRefRelationshipType(entityClass));
+ }
+
+ public Node findSubreferenceNode(final Class extends NodeBacked> entityClass) {
+ final Relationship subrefRelationship = graphDatabaseService.getReferenceNode().getSingleRelationship(subRefRelationshipType(entityClass), Direction.OUTGOING);
+ return subrefRelationship != null ? subrefRelationship.getEndNode() : null;
+ }
+
+ private DynamicRelationshipType subRefRelationshipType(Class> clazz) {
+ return DynamicRelationshipType.withName(SUBREF_PREFIX + clazz.getName());
+ }
+
+ public Node getOrCreateSubReferenceNode(final RelationshipType relType) {
+ return getOrCreateSingleOtherNode(graphDatabaseService.getReferenceNode(), relType, Direction.OUTGOING);
+ }
+
+ private Node getOrCreateSingleOtherNode(Node fromNode, RelationshipType type,
+ Direction direction) {
+ Relationship singleRelationship = fromNode.getSingleRelationship(type, direction);
+ if (singleRelationship != null) {
+ return singleRelationship.getOtherNode(fromNode);
+ }
+
+ Node otherNode = graphDatabaseService.createNode();
+ fromNode.createRelationshipTo(otherNode, type);
+ return otherNode;
+
+ }
+
+
+ @Override
+ public U createEntity(Node state) {
+ Class extends NodeBacked> javaType = getJavaType(state);
+ if (javaType == null) {
+ throw new IllegalStateException("No type stored on node.");
+ }
+ return (U) entityInstantiator.createEntityFromState(state, javaType);
+ }
+
+ @Override
+ public U createEntity(Node state, Class type) {
+ Class extends NodeBacked> javaType = getJavaType(state);
+ if (javaType == null) {
+ throw new IllegalStateException("No type stored on node.");
+ }
+ if (type.isAssignableFrom(javaType)) {
+ return (U) entityInstantiator.createEntityFromState(state, javaType);
+ }
+ throw new IllegalArgumentException(String.format("Entity is not of type: %s (was %s)", type, javaType));
+ }
+
+ @Override
+ public U projectEntity(Node state, Class type) {
+ return entityInstantiator.createEntityFromState(state, type);
+ }
+}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceTypeRepresentationStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceTypeRepresentationStrategy.java
deleted file mode 100644
index bd83b3c2b..000000000
--- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/SubReferenceTypeRepresentationStrategy.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright 2010 the original author or authors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.data.graph.neo4j.support;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.neo4j.graphdb.*;
-import org.springframework.data.graph.core.GraphBacked;
-import org.springframework.data.graph.core.NodeBacked;
-import org.springframework.data.graph.core.TypeRepresentationStrategy;
-import org.springframework.data.persistence.EntityInstantiator;
-
-/**
- * A {@link org.springframework.data.graph.core.TypeRepresentationStrategy} that uses a hierarchy of reference nodes to represent the java type of the entity in the
- * graph database. Entity nodes are related to their concrete type via an INSTANCE_OF relationship, the type hierarchy is
- * related to supertypes via SUBCLASS_OF relationships. Each concrete subreference node keeps a count property with the number of
- * instances of this class in the graph.
- *
- * @author Michael Hunger
- * @since 13.09.2010
- */
-public class SubReferenceTypeRepresentationStrategy implements TypeRepresentationStrategy {
- private final static Log log = LogFactory.getLog(SubReferenceTypeRepresentationStrategy.class);
-
- public final static RelationshipType INSTANCE_OF_RELATIONSHIP_TYPE = DynamicRelationshipType.withName("INSTANCE_OF");
- public final static RelationshipType SUBCLASS_OF_RELATIONSHIP_TYPE = DynamicRelationshipType.withName("SUBCLASS_OF");
-
- public static final String SUBREFERENCE_NODE_COUNTER_KEY = "count";
- public static final String SUBREF_PREFIX = "SUBREF_";
- public static final String SUBREF_CLASS_KEY = "class";
-
- private GraphDatabaseService graphDatabaseService;
- private EntityInstantiator entityInstantiator;
-
- public SubReferenceTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator entityInstantiator) {
- this.graphDatabaseService = graphDatabaseService;
- this.entityInstantiator = entityInstantiator;
- }
-//
-// public static Node getSingleOtherNode(Node node, RelationshipType type,
-// Direction direction) {
-// Relationship rel = node.getSingleRelationship(type, direction);
-// return rel == null ? null : rel.getOtherNode(node);
-// }
-//
-// public static Integer incrementAndGetCounter(Node node, String propertyKey) {
-// acquireWriteLock(node);
-// int value = (Integer) node.getProperty(propertyKey, 0);
-// value++;
-// node.setProperty(propertyKey, value);
-// return value;
-// }
-//
-// public static Integer decrementAndGetCounter(Node node, String propertyKey,
-// int notLowerThan) {
-// int value = (Integer) node.getProperty(propertyKey, 0);
-// value--;
-// value = value < notLowerThan ? notLowerThan : value;
-// node.setProperty(propertyKey, value);
-// return value;
-// }
-//
-// public static void acquireWriteLock(PropertyContainer entity) {
-// // TODO At the moment this is the best way of doing it, if you don't want to use
-// // the LockManager (and release the lock yourself)
-// entity.removeProperty("___dummy_property_for_locking___");
-// }
-//
-// /**
-// * lifecycle method, creates instanceof relationship to type node, creates the type nodes of the inheritance
-// * hierarchy if necessary and increments instance counters
-// * @param entity
-// */
-// @Override
-// public void postEntityCreation(final NodeBacked entity) {
-// Class extends NodeBacked> clazz = entity.getClass();
-//
-// final Node subReference = obtainSubreferenceNode(clazz);
-// entity.getPersistentState().createRelationshipTo(subReference, INSTANCE_OF_RELATIONSHIP_TYPE);
-// subReference.setProperty(SUBREF_CLASS_KEY, clazz.getName());
-// if (log.isDebugEnabled()) log.debug("Created link to subref node: " + subReference + " with type: " + clazz.getName());
-//
-// incrementAndGetCounter(subReference, SUBREFERENCE_NODE_COUNTER_KEY);
-//
-// updateSuperClassSubrefs(clazz, subReference);
-// }
-//
-// /**
-// * removes instanceof relationship and decrements instance counters for type nodes
-// * @param entity
-// */
-// @Override
-// public void preEntityRemoval(NodeBacked entity) {
-// Class extends NodeBacked> clazz = entity.getClass();
-//
-// final Node subReference = obtainSubreferenceNode(clazz);
-// Node subRefNode = entity.getPersistentState();
-// Relationship instanceOf = subRefNode.getSingleRelationship(INSTANCE_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
-// instanceOf.delete();
-// if (log.isDebugEnabled()) log.debug("Removed link to subref node: " + subReference + " with type: " + clazz.getName());
-// TraversalDescription traversal = new TraversalDescriptionImpl().depthFirst().relationships(SUBCLASS_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
-// for (Node node : traversal.traverse(subReference).nodes()) {
-// Integer count = (Integer) node.getProperty(SUBREFERENCE_NODE_COUNTER_KEY);
-// Integer newCount = decrementAndGetCounter(node, SUBREFERENCE_NODE_COUNTER_KEY, 0);
-// if (log.isDebugEnabled()) log.debug("count on ref " + node + " was " + count + " new " + newCount);
-// }
-// }
-//
-// @Override
-// public Class confirmType(Node node, Class type) {
-// Class nodeType = this.getJavaType(node);
-// if (type.isAssignableFrom(nodeType)) return nodeType;
-// throw new IllegalArgumentException(String.format("%s does not correspond to the node type %s of node %s",type,nodeType,node));
-// }
-//
-// private void updateSuperClassSubrefs(Class> clazz, Node subReference) {
-// Class> superClass = clazz.getSuperclass();
-// if (superClass != null) {
-// Node superClassSubref = obtainSubreferenceNode(superClass);
-// if (getSingleOtherNode(subReference, SUBCLASS_OF_RELATIONSHIP_TYPE, Direction.OUTGOING) == null) {
-// subReference.createRelationshipTo(superClassSubref, SUBCLASS_OF_RELATIONSHIP_TYPE);
-// }
-// superClassSubref.setProperty(SUBREF_CLASS_KEY, superClass.getName());
-// Integer count = incrementAndGetCounter(superClassSubref, SUBREFERENCE_NODE_COUNTER_KEY);
-// if (log.isDebugEnabled()) log.debug("count on ref " + superClassSubref + " for class " + superClass.getSimpleName() + " = " + count);
-// updateSuperClassSubrefs(superClass, superClassSubref);
-// }
-// }
-//
-// @Override
-// public long count(final Class extends NodeBacked> entityClass) {
-// final Node subrefNode = findSubreferenceNode(entityClass);
-// if (subrefNode == null) return 0;
-// return (Integer) subrefNode.getProperty(SUBREFERENCE_NODE_COUNTER_KEY, 0);
-// }
-//
-// @Override
-// @SuppressWarnings("unchecked")
-// public Class getJavaType(Node node) {
-// if (node==null) throw new IllegalArgumentException("Node is null");
-// Relationship instanceOfRelationship = node.getSingleRelationship(INSTANCE_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
-// if (instanceOfRelationship==null) throw new IllegalArgumentException("The node "+node+" is not attached to a type hierarchy.");
-// Node subrefNode = instanceOfRelationship.getEndNode();
-// try {
-// Class clazz = (Class) Class.forName((String) subrefNode.getProperty(SUBREF_CLASS_KEY)).asSubclass(NodeBacked.class);
-// if (log.isDebugEnabled()) log.debug("Found class " + clazz.getSimpleName() + " for node: " + node);
-// return clazz;
-// } catch (ClassNotFoundException e) {
-// throw new IllegalStateException("Unable to get type for node: " + node, e);
-// }
-// }
-//
-// @Override
-// public Iterable findAll(final Class clazz) {
-// final Node subrefNode = findSubreferenceNode(clazz);
-// if (log.isDebugEnabled()) log.debug("Subref: " + subrefNode);
-// Iterable> relIterables = findEntityIterables(subrefNode);
-// return new CombiningIterable(relIterables);
-// }
-//
-// private List> findEntityIterables(Node subrefNode) {
-// if (subrefNode == null) return Collections.emptyList();
-// List> result = new LinkedList>();
-// for (Relationship relationship : subrefNode.getRelationships(SUBCLASS_OF_RELATIONSHIP_TYPE, Direction.INCOMING)) {
-// result.addAll((Collection extends Iterable>) findEntityIterables(relationship.getStartNode()));
-// }
-// Iterable t = new IterableWrapper(subrefNode.getRelationships(INSTANCE_OF_RELATIONSHIP_TYPE, Direction.INCOMING)) {
-// @Override
-// protected T underlyingObjectToObject(final Relationship rel) {
-// final Node node = rel.getStartNode();
-// T entity = (T) entityInstantiator.createEntityFromState(node, getJavaType(node));
-// if (log.isDebugEnabled()) log.debug("Converting node: " + node + " to entity: " + entity);
-// return entity;
-// }
-// };
-// result.add(t);
-// return result;
-// }
-//
-//
-// public Node obtainSubreferenceNode(final Class> entityClass) {
-// return getOrCreateSubReferenceNode(subRefRelationshipType(entityClass));
-// }
-//
-// public Node findSubreferenceNode(final Class extends NodeBacked> entityClass) {
-// final Relationship subrefRelationship = graphDatabaseService.getReferenceNode().getSingleRelationship(subRefRelationshipType(entityClass), Direction.OUTGOING);
-// return subrefRelationship != null ? subrefRelationship.getEndNode() : null;
-// }
-//
-// private DynamicRelationshipType subRefRelationshipType(Class> clazz) {
-// return DynamicRelationshipType.withName(SUBREF_PREFIX + clazz.getName());
-// }
-//
-// public Node getOrCreateSubReferenceNode(final RelationshipType relType) {
-// return getOrCreateSingleOtherNode(graphDatabaseService.getReferenceNode(), relType, Direction.OUTGOING);
-// }
-//
-// private Node getOrCreateSingleOtherNode(Node fromNode, RelationshipType type,
-// Direction direction) {
-// Relationship singleRelationship = fromNode.getSingleRelationship(type, direction);
-// if (singleRelationship != null) {
-// return singleRelationship.getOtherNode(fromNode);
-// }
-//
-// Node otherNode = graphDatabaseService.createNode();
-// fromNode.createRelationshipTo(otherNode, type);
-// return otherNode;
-//
-// }
-
- @Override
- public void postEntityCreation(GraphBacked> entity) {
- }
-
- @Override
- public > Iterable findAll(Class clazz) {
- return null;
- }
-
- @Override
- public long count(Class extends GraphBacked>> entityClass) {
- return 0;
- }
-
- @Override
- public > Class getJavaType(PropertyContainer primitive) {
- return null;
- }
-
- @Override
- public void preEntityRemoval(GraphBacked> entity) {
- }
-
- @Override
- public > Class confirmType(PropertyContainer node, Class type) {
- return null;
- }
-}
diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/TypeRepresentationStrategyFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/TypeRepresentationStrategyFactory.java
new file mode 100644
index 000000000..83e285282
--- /dev/null
+++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/TypeRepresentationStrategyFactory.java
@@ -0,0 +1,90 @@
+package org.springframework.data.graph.neo4j.support;
+
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.Relationship;
+import org.springframework.data.graph.core.*;
+import org.springframework.data.persistence.EntityInstantiator;
+
+public class TypeRepresentationStrategyFactory {
+ private GraphDatabaseService graphDatabaseService;
+ private EntityInstantiator graphEntityInstantiator;
+ private EntityInstantiator relationshipEntityInstantiator;
+ private Strategy strategy;
+
+ public TypeRepresentationStrategyFactory(GraphDatabaseService graphDatabaseService,
+ EntityInstantiator graphEntityInstantiator,
+ EntityInstantiator relationshipEntityInstantiator) {
+ this.graphDatabaseService = graphDatabaseService;
+ this.graphEntityInstantiator = graphEntityInstantiator;
+ this.relationshipEntityInstantiator = relationshipEntityInstantiator;
+ strategy = chooseStrategy();
+ }
+
+ private Strategy chooseStrategy() {
+ if (isAlreadyIndexed()) return Strategy.Indexed;
+ if (isAlreadySubRef()) return Strategy.SubRef;
+ return Strategy.Indexed;
+ }
+
+ private boolean isAlreadyIndexed() {
+ return graphDatabaseService.index().existsForNodes(IndexingNodeTypeRepresentationStrategy.INDEX_NAME);
+ }
+
+ private boolean isAlreadySubRef() {
+ for (Relationship rel : graphDatabaseService.getReferenceNode().getRelationships()) {
+ if (rel.getType().name().startsWith(SubReferenceNodeTypeRepresentationStrategy.SUBREF_PREFIX)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy() {
+ return strategy.getNodeTypeRepresentationStrategy(graphDatabaseService, graphEntityInstantiator);
+ }
+
+ public RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy() {
+ return strategy.getRelationshipTypeRepresentationStrategy(graphDatabaseService, relationshipEntityInstantiator);
+ }
+
+ private enum Strategy {
+ SubRef {
+ @Override
+ public NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) {
+ return new SubReferenceNodeTypeRepresentationStrategy(graphDatabaseService, graphEntityInstantiator);
+ }
+
+ @Override
+ public RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator relationshipEntityInstantiator) {
+ return new NoopTypeRepresentationStrategy.NoopRelationshipStrategy();
+ }
+ },
+ Indexed {
+ @Override
+ public NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) {
+ return new IndexingNodeTypeRepresentationStrategy(graphDatabaseService, graphEntityInstantiator);
+ }
+
+ @Override
+ public RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator relationshipEntityInstantiator) {
+ return new IndexingRelationshipTypeRepresentationStrategy(graphDatabaseService, relationshipEntityInstantiator);
+ }
+ },
+ Noop {
+ @Override
+ public NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) {
+ return new NoopTypeRepresentationStrategy.NoopNodeStrategy();
+ }
+
+ @Override
+ public RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator relationshipEntityInstantiator) {
+ return new NoopTypeRepresentationStrategy.NoopRelationshipStrategy();
+ }
+ };
+
+ public abstract NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator);
+
+ public abstract RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator