diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategy.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategy.java index ae6c78270..eac2afc1e 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategy.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategy.java @@ -15,7 +15,10 @@ import org.springframework.persistence.support.EntityInstantiator; public class IndexingNodeTypeStrategy implements NodeTypeStrategy { - private EntityInstantiator graphEntityInstantiator; + public static final String NODE_INDEX_NAME = "__types__"; + public static final String TYPE_PROPERTY_NAME = "__type__"; + public static final String INDEX_KEY = "className"; + private EntityInstantiator graphEntityInstantiator; private GraphDatabaseService graphDb; public IndexingNodeTypeStrategy(GraphDatabaseService graphDb, EntityInstantiator graphEntityInstantiator) { @@ -24,7 +27,7 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy { } private Index getTypesIndex() { - return graphDb.index().forNodes("__types__"); + return graphDb.index().forNodes(NODE_INDEX_NAME); } @Override @@ -32,20 +35,20 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy { Node node = entity.getPersistentState(); Class entityClass = entity.getClass(); addToTypesIndex(node, entityClass); - node.setProperty("__type__", entityClass.getName()); + node.setProperty(TYPE_PROPERTY_NAME, entityClass.getName()); } private void addToTypesIndex(Node node, Class entityClass) { Class klass = entityClass; while (klass.getAnnotation(NodeEntity.class) != null) { - getTypesIndex().add(node, "className", klass.getName()); + getTypesIndex().add(node, INDEX_KEY, klass.getName()); klass = klass.getSuperclass(); } } @Override public Iterable findAll(Class clazz) { - final IndexHits allEntitiesOfType = getTypesIndex().get("className", clazz.getName()); + final IndexHits allEntitiesOfType = getTypesIndex().get(INDEX_KEY, clazz.getName()); return new FilteringIterable(new IterableWrapper(allEntitiesOfType) { @Override @SuppressWarnings("unchecked") @@ -64,7 +67,11 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy { @Override public long count(Class entityClass) { - return getTypesIndex().get("className", entityClass.getName()).size(); + long count = 0; + for (Node node : getTypesIndex().get(INDEX_KEY, entityClass.getName())) { + count += 1; + } + return count; } @Override @@ -72,7 +79,7 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy { public Class getJavaType(Node node) { if (node == null) throw new IllegalArgumentException("Node is null"); try { - return (Class) Class.forName((String) node.getProperty("__type__")); + return (Class) Class.forName((String) node.getProperty(TYPE_PROPERTY_NAME)); } catch (NotFoundException e) { return null; } catch (ClassNotFoundException e) { diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NodeTypeStrategyFactoryBean.java b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NodeTypeStrategyFactoryBean.java index ec4c95a93..0810258c4 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NodeTypeStrategyFactoryBean.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/graph/neo4j/support/NodeTypeStrategyFactoryBean.java @@ -2,6 +2,7 @@ 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.beans.factory.FactoryBean; import org.springframework.data.graph.core.NodeBacked; import org.springframework.data.graph.core.NodeTypeStrategy; @@ -10,24 +11,83 @@ import org.springframework.persistence.support.EntityInstantiator; public class NodeTypeStrategyFactoryBean implements FactoryBean { private GraphDatabaseService graphDatabaseService; private EntityInstantiator graphEntityInstantiator; + private Strategy strategy; public NodeTypeStrategyFactoryBean(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) { this.graphDatabaseService = graphDatabaseService; this.graphEntityInstantiator = graphEntityInstantiator; + 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(IndexingNodeTypeStrategy.NODE_INDEX_NAME); + } + + private boolean isAlreadySubRef() { + for (Relationship rel : graphDatabaseService.getReferenceNode().getRelationships()) { + if (rel.getType().name().startsWith(SubReferenceNodeTypeStrategy.SUBREF_PREFIX)) { + return true; + } + } + return false; } @Override public NodeTypeStrategy getObject() throws Exception { - return new SubReferenceNodeTypeStrategy(graphDatabaseService, graphEntityInstantiator); + return strategy.getObject(graphDatabaseService, graphEntityInstantiator); } @Override public Class getObjectType() { - return SubReferenceNodeTypeStrategy.class; + return strategy.getObjectType(); } @Override public boolean isSingleton() { return false; } + + private enum Strategy { + SubRef { + @Override + NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) { + return new SubReferenceNodeTypeStrategy(graphDatabaseService, graphEntityInstantiator); + } + + @Override + Class getObjectType() { + return SubReferenceNodeTypeStrategy.class; + } + }, + Indexed { + @Override + NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) { + return new IndexingNodeTypeStrategy(graphDatabaseService, graphEntityInstantiator); + } + + @Override + Class getObjectType() { + return IndexingNodeTypeStrategy.class; + } + }, + Noop { + @Override + NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) { + return new NoopNodeTypeStrategy(); + } + + @Override + Class getObjectType() { + return NoopNodeTypeStrategy.class; + } + }; + abstract NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator); + abstract Class getObjectType(); + } }