Split the type representation strategy into one for rels and one for nodes (via a generic base interface). Moved all entity creation into the type strategies. Next step is to add full support for relationship finders.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -90,22 +90,24 @@
|
||||
|
||||
<bean id="graphDatabaseContext" class="org.springframework.data.graph.neo4j.support.GraphDatabaseContext">
|
||||
<property name="graphDatabaseService" ref="graphDatabaseService"/>
|
||||
<property name="relationshipEntityInstantiator" ref="relationshipEntityInstantiator"/>
|
||||
<property name="graphEntityInstantiator" ref="graphEntityInstantiator"/>
|
||||
<property name="conversionService">
|
||||
<bean class="org.springframework.data.graph.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean"/>
|
||||
</property>
|
||||
<property name="typeRepresentationStrategy" ref="typeRepresentationStrategy"/>
|
||||
<property name="nodeTypeRepresentationStrategy" ref="nodeTypeRepresentationStrategy" />
|
||||
<property name="relationshipTypeRepresentationStrategy" ref="relationshipTypeRepresentationStrategy" />
|
||||
</bean>
|
||||
<bean id="relationshipEntityInstantiator"
|
||||
class="org.springframework.data.graph.neo4j.support.relationship.ConstructorBypassingGraphRelationshipInstantiator"/>
|
||||
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.TypeRepresentationStrategyFactoryBean">
|
||||
<bean id="typeRepresentationStrategyFactory" class="org.springframework.data.graph.neo4j.support.TypeRepresentationStrategyFactory">
|
||||
<constructor-arg ref="graphDatabaseService"/>
|
||||
<constructor-arg ref="graphEntityInstantiator"/>
|
||||
<constructor-arg ref="relationshipEntityInstantiator"/>
|
||||
</bean>
|
||||
|
||||
<bean id="nodeTypeRepresentationStrategy" factory-bean="typeRepresentationStrategyFactory" factory-method="getNodeTypeRepresentationStrategy" />
|
||||
<bean id="relationshipTypeRepresentationStrategy" factory-bean="typeRepresentationStrategyFactory" factory-method="getRelationshipTypeRepresentationStrategy"/>
|
||||
|
||||
<bean id="graphEntityInstantiator"
|
||||
class="org.springframework.data.graph.neo4j.support.node.Neo4jConstructorGraphEntityInstantiator"/>
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.springframework.data.graph.core;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
|
||||
public interface NodeTypeRepresentationStrategy extends TypeRepresentationStrategy<Node, NodeBacked> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.springframework.data.graph.core;
|
||||
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
|
||||
public interface RelationshipTypeRepresentationStrategy extends TypeRepresentationStrategy<Relationship, RelationshipBacked> {
|
||||
|
||||
}
|
||||
@@ -29,47 +29,70 @@ import org.neo4j.graphdb.PropertyContainer;
|
||||
* @author Michael Hunger
|
||||
* @since 13.09.2010
|
||||
*/
|
||||
public interface TypeRepresentationStrategy {
|
||||
public interface TypeRepresentationStrategy<S extends PropertyContainer, T extends GraphBacked<S>> {
|
||||
/**
|
||||
* 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 <T> Type parameter for generified return value
|
||||
* @param <U> Type parameter for generified return value
|
||||
* @return lazy Iterable over all instances of the given type
|
||||
*/
|
||||
<T extends GraphBacked<?>> Iterable<T> findAll(final Class<T> clazz);
|
||||
<U extends T> Iterable<U> findAll(final Class<U> 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 <T>
|
||||
* @param state
|
||||
* @return java type that of the node entity of this node
|
||||
*/
|
||||
<T extends GraphBacked<?>> Class<T> getJavaType(PropertyContainer primitive);
|
||||
<U extends T> Class<U> 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 <T>
|
||||
* @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 <U> Helper parameter for castless use
|
||||
* @throws IllegalStateException If the strategy is unable to infer any type from the state
|
||||
* @return Entity instance
|
||||
*/
|
||||
<T extends GraphBacked<?>> Class<T> confirmType(PropertyContainer node, Class<T> type);
|
||||
<U extends T> 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 extends T> U createEntity(S state, Class<U> 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 extends T> U projectEntity(S state, Class<U> type);
|
||||
}
|
||||
|
||||
@@ -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<NodeBacked, Node> graphEntityInstantiator = graphEntityInstantiator();
|
||||
gdc.setGraphEntityInstantiator(graphEntityInstantiator);
|
||||
gdc.setConversionService(conversionService());
|
||||
TypeRepresentationStrategyFactoryBean typeRepresentationStrategyFactoryBean =
|
||||
new TypeRepresentationStrategyFactoryBean(graphDatabaseService, graphEntityInstantiator, relationshipEntityInstantiator);
|
||||
gdc.setTypeRepresentationStrategy(typeRepresentationStrategyFactoryBean.getObject());
|
||||
EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator = graphRelationshipInstantiator();
|
||||
EntityInstantiator<NodeBacked, Node> 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);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class NodeEntityState<ENTITY extends NodeBacked> 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);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public class PartialNodeEntityState<ENTITY extends NodeBacked> 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);
|
||||
|
||||
@@ -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<NodeBacked, Node> graphEntityInstantiator;
|
||||
|
||||
public EntityInstantiator<RelationshipBacked, Relationship> 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<NodeBacked, Node> getGraphEntityInstantiator() {
|
||||
return graphEntityInstantiator;
|
||||
}
|
||||
public NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy() {
|
||||
return nodeTypeRepresentationStrategy;
|
||||
}
|
||||
|
||||
public void setGraphEntityInstantiator(
|
||||
EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
this.graphEntityInstantiator = graphEntityInstantiator;
|
||||
}
|
||||
public void setNodeTypeRepresentationStrategy(NodeTypeRepresentationStrategy nodeTypeRepresentationStrategy) {
|
||||
this.nodeTypeRepresentationStrategy = nodeTypeRepresentationStrategy;
|
||||
}
|
||||
|
||||
public EntityInstantiator<RelationshipBacked, Relationship> getRelationshipEntityInstantiator() {
|
||||
return relationshipEntityInstantiator;
|
||||
}
|
||||
public RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy() {
|
||||
return relationshipTypeRepresentationStrategy;
|
||||
}
|
||||
|
||||
public void setRelationshipEntityInstantiator(
|
||||
EntityInstantiator<RelationshipBacked, Relationship> 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 <S, T extends GraphBacked> T createEntityFromState(final S state, final Class<T> 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<NodeBacked>) 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<RelationshipBacked>) 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 <T extends GraphBacked> Iterable<T> findAll(final Class<T> clazz) {
|
||||
if (!checkIsNodeBacked(clazz)) throw new UnsupportedOperationException("No support for relationships");
|
||||
return (Iterable<T>) typeRepresentationStrategy.findAll((Class<NodeBacked>)clazz);
|
||||
return (Iterable<T>) nodeTypeRepresentationStrategy.findAll((Class<NodeBacked>)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<NodeBacked>)entityClass);
|
||||
return nodeTypeRepresentationStrategy.count((Class<NodeBacked>)entityClass);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -258,7 +254,7 @@ public class GraphDatabaseContext {
|
||||
* @throws IllegalStateException for nodes that are not instance backing nodes of a known type
|
||||
*/
|
||||
public <T extends NodeBacked> Class<T> getJavaType(final Node node) {
|
||||
return typeRepresentationStrategy.getJavaType(node);
|
||||
return nodeTypeRepresentationStrategy.getJavaType(node);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,9 +309,9 @@ public class GraphDatabaseContext {
|
||||
public <T extends GraphBacked> T projectTo(GraphBacked entity, Class<T> 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<NodeBacked>) targetType);
|
||||
else
|
||||
return (T) relationshipEntityInstantiator.createEntityFromState((Relationship) state, (Class<? extends RelationshipBacked>) targetType);
|
||||
return (T) relationshipTypeRepresentationStrategy.projectEntity((Relationship) state, (Class<RelationshipBacked>) targetType);
|
||||
}
|
||||
|
||||
public Validator getValidator() {
|
||||
@@ -327,7 +323,7 @@ public class GraphDatabaseContext {
|
||||
}
|
||||
|
||||
public <T extends NodeBacked> T createEntityFromStoredType(Node node) {
|
||||
return (T)graphEntityInstantiator.createEntityFromState(node, typeRepresentationStrategy.<NodeBacked>getJavaType(node));
|
||||
return nodeTypeRepresentationStrategy.createEntity(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<NodeBacked, Node> graphEntityInstantiator;
|
||||
private GraphDatabaseService graphDb;
|
||||
private final Map<String,Class<?>> cache=new HashMap<String, Class<?>>();
|
||||
|
||||
public IndexingNodeTypeRepresentationStrategy(GraphDatabaseService graphDb,
|
||||
EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
this.graphDb = graphDb;
|
||||
this.graphEntityInstantiator = graphEntityInstantiator;
|
||||
}
|
||||
|
||||
private Index<Node> getNodeTypesIndex() {
|
||||
return graphDb.index().forNodes(INDEX_NAME);
|
||||
}
|
||||
|
||||
private Index<Relationship> 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 <U extends NodeBacked> Iterable<U> findAll(Class<U> clazz) {
|
||||
return findAllNodeBacked(clazz);
|
||||
}
|
||||
|
||||
private <ENTITY extends NodeBacked> Iterable<ENTITY> findAllNodeBacked(Class<ENTITY> clazz) {
|
||||
final IndexHits<Node> allEntitiesOfType = getNodeTypesIndex().get(INDEX_KEY, clazz.getName());
|
||||
return new FilteringIterable<ENTITY>(new IterableWrapper<ENTITY, Node>(allEntitiesOfType) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ENTITY underlyingObjectToObject(Node node) {
|
||||
Class<ENTITY> javaType = (Class<ENTITY>) getJavaType(node);
|
||||
if (javaType == null) return null;
|
||||
return graphEntityInstantiator.createEntityFromState(node, javaType);
|
||||
}
|
||||
}, new Predicate<ENTITY>() {
|
||||
@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 <ENTITY extends GraphBacked<?>> Class<ENTITY> getClassForName(String className) {
|
||||
try {
|
||||
Class<ENTITY> result= (Class<ENTITY>) cache.get(className);
|
||||
if (result!=null) return result;
|
||||
synchronized (cache) {
|
||||
result= (Class<ENTITY>) cache.get(className);
|
||||
if (result!=null) return result;
|
||||
result = (Class<ENTITY>) 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 extends NodeBacked> 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 extends NodeBacked> U createEntity(Node state, Class<U> 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 extends NodeBacked> U projectEntity(Node state, Class<U> type) {
|
||||
return graphEntityInstantiator.createEntityFromState(state, type);
|
||||
}
|
||||
}
|
||||
@@ -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<RelationshipBacked, Relationship> relationshipEntityInstantiator;
|
||||
private GraphDatabaseService graphDb;
|
||||
private final Map<String,Class<?>> cache=new HashMap<String, Class<?>>();
|
||||
|
||||
public IndexingRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDb,
|
||||
EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator) {
|
||||
this.graphDb = graphDb;
|
||||
this.relationshipEntityInstantiator = relationshipEntityInstantiator;
|
||||
}
|
||||
|
||||
private Index<Node> getNodeTypesIndex() {
|
||||
return graphDb.index().forNodes(INDEX_NAME);
|
||||
}
|
||||
|
||||
private Index<Relationship> 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 <U extends RelationshipBacked> Iterable<U> findAll(Class<U> clazz) {
|
||||
return findAllRelBacked(clazz);
|
||||
}
|
||||
|
||||
private <ENTITY extends RelationshipBacked> Iterable<ENTITY> findAllRelBacked(Class<ENTITY> clazz) {
|
||||
final IndexHits<Relationship> allEntitiesOfType = getRelTypesIndex().get(INDEX_KEY, clazz.getName());
|
||||
return new FilteringIterable<ENTITY>(new IterableWrapper<ENTITY, Relationship>(allEntitiesOfType) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ENTITY underlyingObjectToObject(Relationship rel) {
|
||||
Class<ENTITY> javaType = (Class<ENTITY>) getJavaType(rel);
|
||||
if (javaType == null) return null;
|
||||
return relationshipEntityInstantiator.createEntityFromState(rel, javaType);
|
||||
}
|
||||
}, new Predicate<ENTITY>() {
|
||||
@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 <ENTITY extends GraphBacked<?>> Class<ENTITY> getClassForName(String className) {
|
||||
try {
|
||||
Class<ENTITY> result= (Class<ENTITY>) cache.get(className);
|
||||
if (result!=null) return result;
|
||||
synchronized (cache) {
|
||||
result= (Class<ENTITY>) cache.get(className);
|
||||
if (result!=null) return result;
|
||||
result = (Class<ENTITY>) 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 extends RelationshipBacked> 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 extends RelationshipBacked> U createEntity(Relationship state, Class<U> 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 extends RelationshipBacked> U projectEntity(Relationship state, Class<U> type) {
|
||||
return relationshipEntityInstantiator.createEntityFromState(state, type);
|
||||
}
|
||||
}
|
||||
@@ -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<NodeBacked, Node> graphEntityInstantiator;
|
||||
private EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator;
|
||||
private GraphDatabaseService graphDb;
|
||||
private final Map<String,Class<?>> cache=new HashMap<String, Class<?>>();
|
||||
|
||||
public IndexingTypeRepresentationStrategy(GraphDatabaseService graphDb,
|
||||
EntityInstantiator<NodeBacked, Node> graphEntityInstantiator,
|
||||
EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator) {
|
||||
this.graphDb = graphDb;
|
||||
this.graphEntityInstantiator = graphEntityInstantiator;
|
||||
this.relationshipEntityInstantiator = relationshipEntityInstantiator;
|
||||
}
|
||||
|
||||
private Index<Node> getNodeTypesIndex() {
|
||||
return graphDb.index().forNodes(INDEX_NAME);
|
||||
}
|
||||
|
||||
private Index<Relationship> 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 <ENTITY extends GraphBacked<?>> Iterable<ENTITY> findAll(Class<ENTITY> clazz) {
|
||||
if (NodeBacked.class.isAssignableFrom(clazz)) {
|
||||
return (Iterable<ENTITY>) findAllNodeBacked((Class<? extends NodeBacked>) clazz);
|
||||
} else if (RelationshipBacked.class.isAssignableFrom(clazz)) {
|
||||
return (Iterable<ENTITY>) findAllRelBacked((Class<? extends RelationshipBacked>) clazz);
|
||||
}
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private <ENTITY extends RelationshipBacked> Iterable<ENTITY> findAllRelBacked(Class<ENTITY> clazz) {
|
||||
final IndexHits<Relationship> allEntitiesOfType = getRelTypesIndex().get(INDEX_KEY, clazz.getName());
|
||||
return new FilteringIterable<ENTITY>(new IterableWrapper<ENTITY, Relationship>(allEntitiesOfType) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ENTITY underlyingObjectToObject(Relationship rel) {
|
||||
Class<ENTITY> javaType = (Class<ENTITY>) getJavaType(rel);
|
||||
if (javaType == null) return null;
|
||||
return relationshipEntityInstantiator.createEntityFromState(rel, javaType);
|
||||
}
|
||||
}, new Predicate<ENTITY>() {
|
||||
@Override
|
||||
public boolean accept(ENTITY item) {
|
||||
return item != null;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private <ENTITY extends NodeBacked> Iterable<ENTITY> findAllNodeBacked(Class<ENTITY> clazz) {
|
||||
final IndexHits<Node> allEntitiesOfType = getNodeTypesIndex().get(INDEX_KEY, clazz.getName());
|
||||
return new FilteringIterable<ENTITY>(new IterableWrapper<ENTITY, Node>(allEntitiesOfType) {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ENTITY underlyingObjectToObject(Node node) {
|
||||
Class<ENTITY> javaType = (Class<ENTITY>) getJavaType(node);
|
||||
if (javaType == null) return null;
|
||||
return graphEntityInstantiator.createEntityFromState(node, javaType);
|
||||
}
|
||||
}, new Predicate<ENTITY>() {
|
||||
@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 <ENTITY extends GraphBacked<?>> Class<ENTITY> 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 <ENTITY extends GraphBacked<?>> Class<ENTITY> getClassForName(String className) {
|
||||
try {
|
||||
Class<ENTITY> result= (Class<ENTITY>) cache.get(className);
|
||||
if (result!=null) return result;
|
||||
synchronized (cache) {
|
||||
result= (Class<ENTITY>) cache.get(className);
|
||||
if (result!=null) return result;
|
||||
result = (Class<ENTITY>) 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 <T extends GraphBacked<?>> Class<T> confirmType(PropertyContainer primitive, Class<T> type) {
|
||||
Class<T> 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));
|
||||
}
|
||||
}
|
||||
@@ -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 <U extends NodeBacked> Iterable<U> findAll(Class<U> 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 extends NodeBacked> U createEntity(Node state) {
|
||||
throw new UnsupportedOperationException("Creation with stored type not supported by NoopTypeRepresentationStrategy.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U extends NodeBacked> U createEntity(Node state, Class<U> type) {
|
||||
return projectEntity(state, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U extends NodeBacked> U projectEntity(Node state, Class<U> type) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends GraphBacked<?>> Iterable<T> findAll(Class<T> 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 <T extends GraphBacked<?>> Class<T> getJavaType(PropertyContainer primitive) {
|
||||
throw new UnsupportedOperationException("getJavaType not supported NoopTypeRepresentationStrategy.");
|
||||
}
|
||||
@Override
|
||||
public <U extends RelationshipBacked> Iterable<U> findAll(Class<U> 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 <T extends GraphBacked<?>> Class<T> confirmType(PropertyContainer node, Class<T> 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 extends RelationshipBacked> U createEntity(Relationship state) {
|
||||
throw new UnsupportedOperationException("Creation with stored type not supported by NoopTypeRepresentationStrategy.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U extends RelationshipBacked> U createEntity(Relationship state, Class<U> type) {
|
||||
return projectEntity(state, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <U extends RelationshipBacked> U projectEntity(Relationship state, Class<U> type) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<NodeBacked, Node> entityInstantiator;
|
||||
|
||||
public SubReferenceNodeTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> 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 <T extends NodeBacked> Class<T> confirmType(Node node, Class<T> type) {
|
||||
// Class<T> nodeType = this.<T>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 <T extends NodeBacked> Class<T> 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<T> clazz = (Class<T>) 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 <T extends NodeBacked> Iterable<T> findAll(final Class<T> clazz) {
|
||||
final Node subrefNode = findSubreferenceNode(clazz);
|
||||
if (log.isDebugEnabled()) log.debug("Subref: " + subrefNode);
|
||||
Iterable<Iterable<T>> relIterables = findEntityIterables(subrefNode);
|
||||
return new CombiningIterable<T>(relIterables);
|
||||
}
|
||||
|
||||
private <T extends NodeBacked> List<Iterable<T>> findEntityIterables(Node subrefNode) {
|
||||
if (subrefNode == null) return Collections.emptyList();
|
||||
List<Iterable<T>> result = new LinkedList<Iterable<T>>();
|
||||
for (Relationship relationship : subrefNode.getRelationships(SUBCLASS_OF_RELATIONSHIP_TYPE, Direction.INCOMING)) {
|
||||
result.addAll((Collection<? extends Iterable<T>>) findEntityIterables(relationship.getStartNode()));
|
||||
}
|
||||
Iterable<T> t = new IterableWrapper<T, Relationship>(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 extends NodeBacked> 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 extends NodeBacked> U createEntity(Node state, Class<U> 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 extends NodeBacked> U projectEntity(Node state, Class<U> type) {
|
||||
return entityInstantiator.createEntityFromState(state, type);
|
||||
}
|
||||
}
|
||||
@@ -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<NodeBacked, Node> entityInstantiator;
|
||||
|
||||
public SubReferenceTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> 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 <T extends NodeBacked> Class<T> confirmType(Node node, Class<T> type) {
|
||||
// Class<T> nodeType = this.<T>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 <T extends NodeBacked> Class<T> 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<T> clazz = (Class<T>) 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 <T extends NodeBacked> Iterable<T> findAll(final Class<T> clazz) {
|
||||
// final Node subrefNode = findSubreferenceNode(clazz);
|
||||
// if (log.isDebugEnabled()) log.debug("Subref: " + subrefNode);
|
||||
// Iterable<Iterable<T>> relIterables = findEntityIterables(subrefNode);
|
||||
// return new CombiningIterable<T>(relIterables);
|
||||
// }
|
||||
//
|
||||
// private <T extends NodeBacked> List<Iterable<T>> findEntityIterables(Node subrefNode) {
|
||||
// if (subrefNode == null) return Collections.emptyList();
|
||||
// List<Iterable<T>> result = new LinkedList<Iterable<T>>();
|
||||
// for (Relationship relationship : subrefNode.getRelationships(SUBCLASS_OF_RELATIONSHIP_TYPE, Direction.INCOMING)) {
|
||||
// result.addAll((Collection<? extends Iterable<T>>) findEntityIterables(relationship.getStartNode()));
|
||||
// }
|
||||
// Iterable<T> t = new IterableWrapper<T, Relationship>(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 <T extends GraphBacked<?>> Iterable<T> findAll(Class<T> clazz) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count(Class<? extends GraphBacked<?>> entityClass) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends GraphBacked<?>> Class<T> getJavaType(PropertyContainer primitive) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void preEntityRemoval(GraphBacked<?> entity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends GraphBacked<?>> Class<T> confirmType(PropertyContainer node, Class<T> type) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -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<NodeBacked, Node> graphEntityInstantiator;
|
||||
private EntityInstantiator<RelationshipBacked,Relationship> relationshipEntityInstantiator;
|
||||
private Strategy strategy;
|
||||
|
||||
public TypeRepresentationStrategyFactory(GraphDatabaseService graphDatabaseService,
|
||||
EntityInstantiator<NodeBacked, Node> graphEntityInstantiator,
|
||||
EntityInstantiator<RelationshipBacked, Relationship> 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<NodeBacked, Node> graphEntityInstantiator) {
|
||||
return new SubReferenceNodeTypeRepresentationStrategy(graphDatabaseService, graphEntityInstantiator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator) {
|
||||
return new NoopTypeRepresentationStrategy.NoopRelationshipStrategy();
|
||||
}
|
||||
},
|
||||
Indexed {
|
||||
@Override
|
||||
public NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
return new IndexingNodeTypeRepresentationStrategy(graphDatabaseService, graphEntityInstantiator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator) {
|
||||
return new IndexingRelationshipTypeRepresentationStrategy(graphDatabaseService, relationshipEntityInstantiator);
|
||||
}
|
||||
},
|
||||
Noop {
|
||||
@Override
|
||||
public NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
return new NoopTypeRepresentationStrategy.NoopNodeStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator) {
|
||||
return new NoopTypeRepresentationStrategy.NoopRelationshipStrategy();
|
||||
}
|
||||
};
|
||||
|
||||
public abstract NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator);
|
||||
|
||||
public abstract RelationshipTypeRepresentationStrategy getRelationshipTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator);
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
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.RelationshipBacked;
|
||||
import org.springframework.data.graph.core.TypeRepresentationStrategy;
|
||||
import org.springframework.data.persistence.EntityInstantiator;
|
||||
|
||||
public class TypeRepresentationStrategyFactoryBean implements FactoryBean<TypeRepresentationStrategy> {
|
||||
private GraphDatabaseService graphDatabaseService;
|
||||
private EntityInstantiator<NodeBacked, Node> graphEntityInstantiator;
|
||||
private EntityInstantiator<RelationshipBacked,Relationship> relationshipEntityInstantiator;
|
||||
private Strategy strategy;
|
||||
|
||||
public TypeRepresentationStrategyFactoryBean(GraphDatabaseService graphDatabaseService,
|
||||
EntityInstantiator<NodeBacked, Node> graphEntityInstantiator,
|
||||
EntityInstantiator<RelationshipBacked, Relationship> 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(IndexingTypeRepresentationStrategy.INDEX_NAME);
|
||||
}
|
||||
|
||||
private boolean isAlreadySubRef() {
|
||||
for (Relationship rel : graphDatabaseService.getReferenceNode().getRelationships()) {
|
||||
if (rel.getType().name().startsWith(SubReferenceTypeRepresentationStrategy.SUBREF_PREFIX)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeRepresentationStrategy getObject() throws Exception {
|
||||
return strategy.getObject(graphDatabaseService, graphEntityInstantiator, relationshipEntityInstantiator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return strategy.getObjectType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private enum Strategy {
|
||||
SubRef {
|
||||
@Override
|
||||
TypeRepresentationStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator, EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator) {
|
||||
return new SubReferenceTypeRepresentationStrategy(graphDatabaseService, graphEntityInstantiator);
|
||||
}
|
||||
|
||||
@Override
|
||||
Class<? extends TypeRepresentationStrategy> getObjectType() {
|
||||
return SubReferenceTypeRepresentationStrategy.class;
|
||||
}
|
||||
},
|
||||
Indexed {
|
||||
@Override
|
||||
TypeRepresentationStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator, EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator) {
|
||||
return new IndexingTypeRepresentationStrategy(graphDatabaseService, graphEntityInstantiator, relationshipEntityInstantiator);
|
||||
}
|
||||
|
||||
@Override
|
||||
Class<? extends TypeRepresentationStrategy> getObjectType() {
|
||||
return IndexingTypeRepresentationStrategy.class;
|
||||
}
|
||||
},
|
||||
Noop {
|
||||
@Override
|
||||
TypeRepresentationStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator, EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator) {
|
||||
return new NoopTypeRepresentationStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
Class<? extends TypeRepresentationStrategy> getObjectType() {
|
||||
return NoopTypeRepresentationStrategy.class;
|
||||
}
|
||||
};
|
||||
|
||||
abstract TypeRepresentationStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator, EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator);
|
||||
abstract Class<? extends TypeRepresentationStrategy> getObjectType();
|
||||
}
|
||||
}
|
||||
@@ -179,7 +179,10 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
|
||||
if (relationshipType==null) throw new IllegalArgumentException("Relationshiptype is null");
|
||||
|
||||
Relationship rel = this.relateTo(target,relationshipType);
|
||||
return (R)Neo4jNodeBacking.aspectOf().graphDatabaseContext.createEntityFromState(rel, relationshipClass);
|
||||
|
||||
GraphDatabaseContext gdc = Neo4jNodeBacking.aspectOf().graphDatabaseContext;
|
||||
gdc.postEntityCreation(rel, relationshipClass);
|
||||
return (R) gdc.createEntityFromState(rel, relationshipClass);
|
||||
}
|
||||
|
||||
public void NodeBacked.remove() {
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
package org.springframework.data.graph.neo4j.support;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.index.IndexHits;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.graph.annotation.NodeEntity;
|
||||
import org.springframework.data.graph.core.NodeBacked;
|
||||
import org.springframework.data.graph.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml",
|
||||
"classpath:org/springframework/data/graph/neo4j/support/IndexingTypeRepresentationStrategyOverride-context.xml"})
|
||||
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
|
||||
public class IndexingNodeTypeRepresentationStrategyTest {
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseService graphDatabaseService;
|
||||
@Autowired
|
||||
private IndexingNodeTypeRepresentationStrategy nodeTypeRepresentationStrategy;
|
||||
|
||||
private Thing thing;
|
||||
private SubThing subThing;
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseService);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
if (thing == null) {
|
||||
createThingsAndLinks();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testPostEntityCreation() throws Exception {
|
||||
Index<Node> typesIndex = graphDatabaseService.index().forNodes(IndexingNodeTypeRepresentationStrategy.INDEX_NAME);
|
||||
IndexHits<Node> thingHits = typesIndex.get(IndexingNodeTypeRepresentationStrategy.INDEX_KEY, thing.getClass().getName());
|
||||
assertEquals(set(node(thing), node(subThing)), IteratorUtil.addToCollection((Iterable<Node>)thingHits, new HashSet<Node>()));
|
||||
IndexHits<Node> subThingHits = typesIndex.get(IndexingNodeTypeRepresentationStrategy.INDEX_KEY, subThing.getClass().getName());
|
||||
assertEquals(node(subThing), subThingHits.getSingle());
|
||||
assertEquals(thing.getClass().getName(), node(thing).getProperty(IndexingNodeTypeRepresentationStrategy.TYPE_PROPERTY_NAME));
|
||||
assertEquals(subThing.getClass().getName(), node(subThing).getProperty(IndexingNodeTypeRepresentationStrategy.TYPE_PROPERTY_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreEntityRemoval() throws Exception {
|
||||
manualCleanDb();
|
||||
createThingsAndLinks();
|
||||
Index<Node> typesIndex = graphDatabaseService.index().forNodes(IndexingNodeTypeRepresentationStrategy.INDEX_NAME);
|
||||
IndexHits<Node> thingHits;
|
||||
IndexHits<Node> subThingHits;
|
||||
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try
|
||||
{
|
||||
nodeTypeRepresentationStrategy.preEntityRemoval(thing);
|
||||
tx.success();
|
||||
}
|
||||
finally
|
||||
{
|
||||
tx.finish();
|
||||
}
|
||||
|
||||
thingHits = typesIndex.get(IndexingNodeTypeRepresentationStrategy.INDEX_KEY, thing.getClass().getName());
|
||||
assertEquals(node(subThing), thingHits.getSingle());
|
||||
subThingHits = typesIndex.get(IndexingNodeTypeRepresentationStrategy.INDEX_KEY, subThing.getClass().getName());
|
||||
assertEquals(node(subThing), subThingHits.getSingle());
|
||||
|
||||
tx = graphDatabaseService.beginTx();
|
||||
try
|
||||
{
|
||||
nodeTypeRepresentationStrategy.preEntityRemoval(subThing);
|
||||
tx.success();
|
||||
}
|
||||
finally
|
||||
{
|
||||
tx.finish();
|
||||
}
|
||||
|
||||
thingHits = typesIndex.get(IndexingNodeTypeRepresentationStrategy.INDEX_KEY, thing.getClass().getName());
|
||||
assertNull(thingHits.getSingle());
|
||||
subThingHits = typesIndex.get(IndexingNodeTypeRepresentationStrategy.INDEX_KEY, subThing.getClass().getName());
|
||||
assertNull(subThingHits.getSingle());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFindAll() throws Exception {
|
||||
assertEquals("Did not find all things.",
|
||||
new HashSet<Thing>(Arrays.asList(subThing, thing)),
|
||||
IteratorUtil.addToCollection(nodeTypeRepresentationStrategy.findAll(Thing.class), new HashSet<Thing>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCount() throws Exception {
|
||||
assertEquals(2, nodeTypeRepresentationStrategy.count(Thing.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testGetJavaType() throws Exception {
|
||||
assertEquals(Thing.class, nodeTypeRepresentationStrategy.getJavaType(node(thing)));
|
||||
assertEquals(SubThing.class, nodeTypeRepresentationStrategy.getJavaType(node(subThing)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateEntityAndInferType() throws Exception {
|
||||
Thing newThing = nodeTypeRepresentationStrategy.createEntity(node(thing));
|
||||
assertEquals(thing, newThing);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateEntityAndSpecifyType() throws Exception {
|
||||
Thing newThing = nodeTypeRepresentationStrategy.createEntity(node(subThing), Thing.class);
|
||||
assertEquals(subThing, newThing);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testProjectEntity() throws Exception {
|
||||
Unrelated other = nodeTypeRepresentationStrategy.projectEntity(node(thing), Unrelated.class);
|
||||
assertEquals("thing", other.getName());
|
||||
}
|
||||
|
||||
private static Node node(Thing thing) {
|
||||
return thing.getPersistentState();
|
||||
}
|
||||
|
||||
private Thing createThingsAndLinks() {
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try {
|
||||
Node n1 = graphDatabaseService.createNode();
|
||||
thing = new Thing(n1);
|
||||
nodeTypeRepresentationStrategy.postEntityCreation(n1, Thing.class);
|
||||
thing.setName("thing");
|
||||
Node n2 = graphDatabaseService.createNode();
|
||||
subThing = new SubThing(n2);
|
||||
nodeTypeRepresentationStrategy.postEntityCreation(n2, SubThing.class);
|
||||
subThing.setName("subThing");
|
||||
tx.success();
|
||||
return thing;
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
public static class Unrelated {
|
||||
String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
public static class Thing {
|
||||
String name;
|
||||
|
||||
public Thing(Node node) {
|
||||
setPersistentState(node);
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SubThing extends Thing {
|
||||
public SubThing(Node node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static Set<Node> set(Node... nodes) {
|
||||
return new HashSet<Node>(Arrays.asList(nodes));
|
||||
}
|
||||
|
||||
private void manualCleanDb() {
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try {
|
||||
cleanDb();
|
||||
tx.success();
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
package org.springframework.data.graph.neo4j.support;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.index.IndexHits;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.graph.annotation.EndNode;
|
||||
import org.springframework.data.graph.annotation.NodeEntity;
|
||||
import org.springframework.data.graph.annotation.RelationshipEntity;
|
||||
import org.springframework.data.graph.annotation.StartNode;
|
||||
import org.springframework.data.graph.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml",
|
||||
"classpath:org/springframework/data/graph/neo4j/support/IndexingTypeRepresentationStrategyOverride-context.xml"})
|
||||
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
|
||||
public class IndexingRelationshipTypeRepresentationStrategyTest {
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseService graphDatabaseService;
|
||||
@Autowired
|
||||
private IndexingRelationshipTypeRepresentationStrategy relationshipTypeRepresentationStrategy;
|
||||
|
||||
private Link link;
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseService);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
if (link == null) {
|
||||
createThingsAndLinks();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testPostEntityCreationOfRelationshipBacked() throws Exception {
|
||||
Index<Relationship> typesIndex = graphDatabaseService.index().forRelationships(IndexingNodeTypeRepresentationStrategy.INDEX_NAME);
|
||||
IndexHits<Relationship> linkHits = typesIndex.get(IndexingNodeTypeRepresentationStrategy.INDEX_KEY, link.getClass().getName());
|
||||
Relationship rel = linkHits.getSingle();
|
||||
assertEquals(rel(link), rel);
|
||||
assertEquals(link.getClass().getName(), rel.getProperty("__type__"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreEntityRemovalOfRelationshipBacked() throws Exception {
|
||||
manualCleanDb();
|
||||
createThingsAndLinks();
|
||||
Index<Relationship> typesIndex = graphDatabaseService.index().forRelationships(IndexingNodeTypeRepresentationStrategy.INDEX_NAME);
|
||||
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try
|
||||
{
|
||||
relationshipTypeRepresentationStrategy.preEntityRemoval(link);
|
||||
tx.success();
|
||||
}
|
||||
finally
|
||||
{
|
||||
tx.finish();
|
||||
}
|
||||
|
||||
IndexHits<Relationship> linkHits = typesIndex.get(IndexingNodeTypeRepresentationStrategy.INDEX_KEY, link.getClass().getName());
|
||||
assertNull(linkHits.getSingle());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFindAllOfRelationshipBacked() throws Exception {
|
||||
assertEquals("Did not find all links.",
|
||||
Arrays.asList(link),
|
||||
IteratorUtil.addToCollection(relationshipTypeRepresentationStrategy.findAll(Link.class), new ArrayList<Link>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCountOfRelationshipBacked() throws Exception {
|
||||
assertEquals(1, relationshipTypeRepresentationStrategy.count(Link.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testGetJavaTypeOfRelationshipBacked() throws Exception {
|
||||
assertEquals(Link.class, relationshipTypeRepresentationStrategy.getJavaType(rel(link)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateEntityAndInferType() throws Exception {
|
||||
Link newLink = relationshipTypeRepresentationStrategy.createEntity(rel(link));
|
||||
assertEquals(link, newLink);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateEntityAndSpecifyType() throws Exception {
|
||||
Link newLink = relationshipTypeRepresentationStrategy.createEntity(rel(link), Link.class);
|
||||
assertEquals(link, newLink);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testProjectEntity() throws Exception {
|
||||
UnrelatedLink other = relationshipTypeRepresentationStrategy.projectEntity(rel(link), UnrelatedLink.class);
|
||||
assertEquals("link", other.getLabel());
|
||||
}
|
||||
|
||||
private static Relationship rel(Link link) {
|
||||
return link.getPersistentState();
|
||||
}
|
||||
|
||||
private void createThingsAndLinks() {
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try {
|
||||
Node n1 = graphDatabaseService.createNode();
|
||||
Node n2 = graphDatabaseService.createNode();
|
||||
Relationship rel = n1.createRelationshipTo(n2, DynamicRelationshipType.withName("link"));
|
||||
link = new Link(rel);
|
||||
relationshipTypeRepresentationStrategy.postEntityCreation(rel, Link.class);
|
||||
link.setLabel("link");
|
||||
tx.success();
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@RelationshipEntity
|
||||
public static class UnrelatedLink {
|
||||
String label;
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
}
|
||||
|
||||
@RelationshipEntity
|
||||
public static class Link {
|
||||
String label;
|
||||
|
||||
public Link() {
|
||||
}
|
||||
|
||||
public Link(Relationship rel) {
|
||||
setPersistentState(rel);
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SubLink extends Link {
|
||||
public SubLink() {
|
||||
}
|
||||
|
||||
public SubLink(Relationship rel) {
|
||||
super(rel);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<Node> set(Node... nodes) {
|
||||
return new HashSet<Node>(Arrays.asList(nodes));
|
||||
}
|
||||
|
||||
private void manualCleanDb() {
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try {
|
||||
cleanDb();
|
||||
tx.success();
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,274 +0,0 @@
|
||||
package org.springframework.data.graph.neo4j.support;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.index.IndexHits;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.graph.annotation.EndNode;
|
||||
import org.springframework.data.graph.annotation.NodeEntity;
|
||||
import org.springframework.data.graph.annotation.RelationshipEntity;
|
||||
import org.springframework.data.graph.annotation.StartNode;
|
||||
import org.springframework.data.graph.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml",
|
||||
"classpath:org/springframework/data/graph/neo4j/support/IndexingNodeTypeStrategyOverride-context.xml"})
|
||||
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
|
||||
public class IndexingTypeRepresentationStrategyTest {
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseService graphDatabaseService;
|
||||
@Autowired
|
||||
private IndexingTypeRepresentationStrategy typeRepresentationStrategy;
|
||||
|
||||
private Thing thing;
|
||||
private SubThing subThing;
|
||||
private Link link;
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseService);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
if (thing == null) {
|
||||
createThingsAndLinks();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testPostEntityCreationOfNodeBacked() throws Exception {
|
||||
Index<Node> typesIndex = graphDatabaseService.index().forNodes(IndexingTypeRepresentationStrategy.INDEX_NAME);
|
||||
IndexHits<Node> thingHits = typesIndex.get(IndexingTypeRepresentationStrategy.INDEX_KEY, thing.getClass().getName());
|
||||
assertEquals(set(node(thing), node(subThing)), IteratorUtil.addToCollection((Iterable<Node>)thingHits, new HashSet<Node>()));
|
||||
IndexHits<Node> subThingHits = typesIndex.get(IndexingTypeRepresentationStrategy.INDEX_KEY, subThing.getClass().getName());
|
||||
assertEquals(node(subThing), subThingHits.getSingle());
|
||||
assertEquals(thing.getClass().getName(), node(thing).getProperty(IndexingTypeRepresentationStrategy.TYPE_PROPERTY_NAME));
|
||||
assertEquals(subThing.getClass().getName(), node(subThing).getProperty(IndexingTypeRepresentationStrategy.TYPE_PROPERTY_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreEntityRemovalOfNodeBacked() throws Exception {
|
||||
manualCleanDb();
|
||||
createThingsAndLinks();
|
||||
Index<Node> typesIndex = graphDatabaseService.index().forNodes(IndexingTypeRepresentationStrategy.INDEX_NAME);
|
||||
IndexHits<Node> thingHits;
|
||||
IndexHits<Node> subThingHits;
|
||||
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try
|
||||
{
|
||||
typeRepresentationStrategy.preEntityRemoval(thing);
|
||||
tx.success();
|
||||
}
|
||||
finally
|
||||
{
|
||||
tx.finish();
|
||||
}
|
||||
|
||||
thingHits = typesIndex.get(IndexingTypeRepresentationStrategy.INDEX_KEY, thing.getClass().getName());
|
||||
assertEquals(node(subThing), thingHits.getSingle());
|
||||
subThingHits = typesIndex.get(IndexingTypeRepresentationStrategy.INDEX_KEY, subThing.getClass().getName());
|
||||
assertEquals(node(subThing), subThingHits.getSingle());
|
||||
|
||||
tx = graphDatabaseService.beginTx();
|
||||
try
|
||||
{
|
||||
typeRepresentationStrategy.preEntityRemoval(subThing);
|
||||
tx.success();
|
||||
}
|
||||
finally
|
||||
{
|
||||
tx.finish();
|
||||
}
|
||||
|
||||
thingHits = typesIndex.get(IndexingTypeRepresentationStrategy.INDEX_KEY, thing.getClass().getName());
|
||||
assertNull(thingHits.getSingle());
|
||||
subThingHits = typesIndex.get(IndexingTypeRepresentationStrategy.INDEX_KEY, subThing.getClass().getName());
|
||||
assertNull(subThingHits.getSingle());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFindAllOfNodeBacked() throws Exception {
|
||||
assertEquals("Did not find all things.",
|
||||
new HashSet<Thing>(Arrays.asList(subThing, thing)),
|
||||
IteratorUtil.addToCollection(typeRepresentationStrategy.findAll(Thing.class), new HashSet<Thing>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCountOfNodeBacked() throws Exception {
|
||||
assertEquals(2, typeRepresentationStrategy.count(Thing.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testGetJavaTypeOfNodeBacked() throws Exception {
|
||||
assertEquals(Thing.class, typeRepresentationStrategy.getJavaType(node(thing)));
|
||||
assertEquals(SubThing.class, typeRepresentationStrategy.getJavaType(node(subThing)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testConfirmTypeOfNodeBacked() throws Exception {
|
||||
assertEquals(Thing.class, typeRepresentationStrategy.confirmType(node(thing), Thing.class));
|
||||
assertEquals(SubThing.class, typeRepresentationStrategy.confirmType(node(subThing), Thing.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testPostEntityCreationOfRelationshipBacked() throws Exception {
|
||||
Index<Relationship> typesIndex = graphDatabaseService.index().forRelationships(IndexingTypeRepresentationStrategy.INDEX_NAME);
|
||||
IndexHits<Relationship> linkHits = typesIndex.get(IndexingTypeRepresentationStrategy.INDEX_KEY, link.getClass().getName());
|
||||
Relationship rel = linkHits.getSingle();
|
||||
assertEquals(rel(link), rel);
|
||||
assertEquals(link.getClass().getName(), rel.getProperty("__type__"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreEntityRemovalOfRelationshipBacked() throws Exception {
|
||||
manualCleanDb();
|
||||
createThingsAndLinks();
|
||||
Index<Relationship> typesIndex = graphDatabaseService.index().forRelationships(IndexingTypeRepresentationStrategy.INDEX_NAME);
|
||||
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try
|
||||
{
|
||||
typeRepresentationStrategy.preEntityRemoval(link);
|
||||
tx.success();
|
||||
}
|
||||
finally
|
||||
{
|
||||
tx.finish();
|
||||
}
|
||||
|
||||
IndexHits<Relationship> linkHits = typesIndex.get(IndexingTypeRepresentationStrategy.INDEX_KEY, link.getClass().getName());
|
||||
assertNull(linkHits.getSingle());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFindAllOfRelationshipBacked() throws Exception {
|
||||
assertEquals("Did not find all links.",
|
||||
Arrays.asList(link),
|
||||
IteratorUtil.addToCollection(typeRepresentationStrategy.findAll(Link.class), new ArrayList<Link>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCountOfRelationshipBacked() throws Exception {
|
||||
assertEquals(1, typeRepresentationStrategy.count(Link.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testGetJavaTypeOfRelationshipBacked() throws Exception {
|
||||
assertEquals(Link.class, typeRepresentationStrategy.getJavaType(rel(link)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testConfirmTypeOfRelationshipBacked() throws Exception {
|
||||
assertEquals(Link.class, typeRepresentationStrategy.confirmType(rel(link), Link.class));
|
||||
}
|
||||
|
||||
private static Node node(Thing thing) {
|
||||
return thing.getPersistentState();
|
||||
}
|
||||
|
||||
private static Relationship rel(Link link) {
|
||||
return link.getPersistentState();
|
||||
}
|
||||
|
||||
private Thing createThingsAndLinks() {
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try {
|
||||
thing = new Thing(graphDatabaseService.createNode());
|
||||
typeRepresentationStrategy.postEntityCreation(thing);
|
||||
subThing = new SubThing(graphDatabaseService.createNode());
|
||||
typeRepresentationStrategy.postEntityCreation(subThing);
|
||||
link = thing.linkTo(subThing);
|
||||
typeRepresentationStrategy.postEntityCreation(link);
|
||||
tx.success();
|
||||
return thing;
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
public static class Thing {
|
||||
String name;
|
||||
Link link;
|
||||
|
||||
public Thing(Node node) {
|
||||
setPersistentState(node);
|
||||
}
|
||||
|
||||
public Link linkTo(Thing thing) {
|
||||
return relateTo(thing, Link.class, "link");
|
||||
}
|
||||
}
|
||||
|
||||
public static class SubThing extends Thing {
|
||||
public SubThing(Node node) {
|
||||
super(node);
|
||||
}
|
||||
}
|
||||
|
||||
@RelationshipEntity
|
||||
public static class Link {
|
||||
String label;
|
||||
@StartNode
|
||||
Thing start;
|
||||
@EndNode
|
||||
Thing end;
|
||||
|
||||
public Link() {
|
||||
}
|
||||
|
||||
public Link(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<Node> set(Node... nodes) {
|
||||
return new HashSet<Node>(Arrays.asList(nodes));
|
||||
}
|
||||
|
||||
private void manualCleanDb() {
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try {
|
||||
cleanDb();
|
||||
tx.success();
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,7 @@
|
||||
package org.springframework.data.graph.neo4j.support;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.graph.annotation.NodeEntity;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
@@ -14,81 +9,79 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
|
||||
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml",
|
||||
"classpath:org/springframework/data/graph/neo4j/support/NoopNodeTypeStrategyOverride-context.xml"})
|
||||
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
|
||||
public class NoopTypeRepresentationStrategyTest {
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
@Autowired
|
||||
private NoopTypeRepresentationStrategy nodeTypeStrategy;
|
||||
|
||||
private Thing thing;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
thing = createThing();
|
||||
}
|
||||
//
|
||||
// @Autowired
|
||||
// private GraphDatabaseContext graphDatabaseContext;
|
||||
// @Autowired
|
||||
// private NoopTypeRepresentationStrategy nodeTypeStrategy;
|
||||
//
|
||||
// private Thing thing;
|
||||
//
|
||||
// @Before
|
||||
// public void setUp() throws Exception {
|
||||
// thing = createThing();
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testPostEntityCreation() throws Exception {
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testFindAll() throws Exception {
|
||||
nodeTypeStrategy.findAll(Thing.class);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testCount() throws Exception {
|
||||
nodeTypeStrategy.count(Thing.class);
|
||||
}
|
||||
|
||||
@Test(expected = UnsupportedOperationException.class)
|
||||
public void testGetJavaType() throws Exception {
|
||||
nodeTypeStrategy.getJavaType(node(thing));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPreEntityRemoval() throws Exception {
|
||||
nodeTypeStrategy.preEntityRemoval(thing);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConfirmType() throws Exception {
|
||||
assertEquals(Thing.class, nodeTypeStrategy.confirmType(node(thing), Thing.class));
|
||||
}
|
||||
|
||||
private static Node node(Thing thing) {
|
||||
return thing.getPersistentState();
|
||||
}
|
||||
|
||||
private Thing createThing() {
|
||||
Transaction tx = graphDatabaseContext.beginTx();
|
||||
try {
|
||||
Node node = graphDatabaseContext.createNode();
|
||||
Thing thing = new Thing(node);
|
||||
nodeTypeStrategy.postEntityCreation(thing);
|
||||
tx.success();
|
||||
return thing;
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
public static class Thing {
|
||||
String name;
|
||||
|
||||
public Thing() {
|
||||
}
|
||||
|
||||
public Thing(Node n) {
|
||||
setPersistentState(n);
|
||||
}
|
||||
}
|
||||
//
|
||||
// @Test(expected = UnsupportedOperationException.class)
|
||||
// public void testFindAll() throws Exception {
|
||||
// nodeTypeStrategy.findAll(Thing.class);
|
||||
// }
|
||||
//
|
||||
// @Test(expected = UnsupportedOperationException.class)
|
||||
// public void testCount() throws Exception {
|
||||
// nodeTypeStrategy.count(Thing.class);
|
||||
// }
|
||||
//
|
||||
// @Test(expected = UnsupportedOperationException.class)
|
||||
// public void testGetJavaType() throws Exception {
|
||||
// nodeTypeStrategy.getJavaType(node(thing));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testPreEntityRemoval() throws Exception {
|
||||
// nodeTypeStrategy.preEntityRemoval(thing);
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testConfirmType() throws Exception {
|
||||
// assertEquals(Thing.class, nodeTypeStrategy.confirmType(node(thing), Thing.class));
|
||||
// }
|
||||
//
|
||||
// private static Node node(Thing thing) {
|
||||
// return thing.getPersistentState();
|
||||
// }
|
||||
//
|
||||
// private Thing createThing() {
|
||||
// Transaction tx = graphDatabaseContext.beginTx();
|
||||
// try {
|
||||
// Node node = graphDatabaseContext.createNode();
|
||||
// Thing thing = new Thing(node);
|
||||
// nodeTypeStrategy.postEntityCreation(thing);
|
||||
// tx.success();
|
||||
// return thing;
|
||||
// } finally {
|
||||
// tx.finish();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @NodeEntity
|
||||
// public static class Thing {
|
||||
// String name;
|
||||
//
|
||||
// public Thing() {
|
||||
// }
|
||||
//
|
||||
// public Thing(Node n) {
|
||||
// setPersistentState(n);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -2,9 +2,7 @@ package org.springframework.data.graph.neo4j.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.Direction;
|
||||
@@ -14,7 +12,6 @@ import org.neo4j.graphdb.Transaction;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.graph.annotation.NodeEntity;
|
||||
import org.springframework.data.graph.core.NodeBacked;
|
||||
import org.springframework.data.graph.neo4j.Car;
|
||||
import org.springframework.data.graph.neo4j.Person;
|
||||
import org.springframework.data.graph.neo4j.Toyota;
|
||||
@@ -32,8 +29,10 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.data.graph.neo4j.Person.persistedPerson;
|
||||
|
||||
/**
|
||||
@@ -42,10 +41,9 @@ import static org.springframework.data.graph.neo4j.Person.persistedPerson;
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/support/Neo4jGraphPersistenceTest-context.xml",
|
||||
"classpath:org/springframework/data/graph/neo4j/support/SubReferenceNodeTypeStrategyOverride-context.xml"})
|
||||
"classpath:org/springframework/data/graph/neo4j/support/SubReferenceTypeRepresentationStrategyOverride-context.xml"})
|
||||
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
|
||||
@Ignore
|
||||
public class SubReferenceTypeRepresentationStrategyTest {
|
||||
public class SubReferenceNodeTypeRepresentationStrategyTest {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@@ -54,9 +52,11 @@ public class SubReferenceTypeRepresentationStrategyTest {
|
||||
@Autowired
|
||||
private DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
@Autowired
|
||||
private SubReferenceTypeRepresentationStrategy nodeTypeStrategy;
|
||||
private SubReferenceNodeTypeRepresentationStrategy nodeTypeRepresentationStrategy;
|
||||
private Node thingNode;
|
||||
private Thing thing;
|
||||
private SubThing subThing;
|
||||
private Node subThingNode;
|
||||
|
||||
|
||||
@BeforeTransaction
|
||||
@@ -66,92 +66,96 @@ public class SubReferenceTypeRepresentationStrategyTest {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
thingNode = createThing();
|
||||
createThing();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testPostEntityCreation() throws Exception {
|
||||
Node typeNode = getInstanceofRelationship().getOtherNode(thingNode);
|
||||
Assert.assertNotNull("type node for thing exists", typeNode);
|
||||
Assert.assertEquals("type node has property of type Thing.class", Thing.class.getName(), typeNode.getProperty(SubReferenceTypeRepresentationStrategy.SUBREF_CLASS_KEY));
|
||||
Assert.assertEquals("one thing has been created", 1, typeNode.getProperty(SubReferenceTypeRepresentationStrategy.SUBREFERENCE_NODE_COUNTER_KEY));
|
||||
Node typeNode = getInstanceofRelationship(thingNode).getOtherNode(thingNode);
|
||||
assertNotNull("type node for thing exists", typeNode);
|
||||
assertEquals("type node has property of type Thing.class", Thing.class.getName(), typeNode.getProperty(SubReferenceNodeTypeRepresentationStrategy.SUBREF_CLASS_KEY));
|
||||
assertEquals("one thing has been created", 2, typeNode.getProperty(SubReferenceNodeTypeRepresentationStrategy.SUBREFERENCE_NODE_COUNTER_KEY));
|
||||
}
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void gettingTypeFromNonTypeNodeShouldThrowAnDescriptiveException() throws Exception {
|
||||
Node referenceNode = graphDatabaseContext.getReferenceNode();
|
||||
nodeTypeStrategy.getJavaType(referenceNode);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void confirmingTypeOfNonTypeNodeShouldThrowAnDescriptiveException() throws Exception {
|
||||
Node referenceNode = graphDatabaseContext.getReferenceNode();
|
||||
nodeTypeStrategy.confirmType(referenceNode, Thing.class);
|
||||
nodeTypeRepresentationStrategy.getJavaType(referenceNode);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void gettingTypeFromNullShouldFail() throws Exception {
|
||||
nodeTypeStrategy.getJavaType(null);
|
||||
nodeTypeRepresentationStrategy.getJavaType(null);
|
||||
}
|
||||
|
||||
private Node createThing() {
|
||||
private void createThing() {
|
||||
Transaction tx = graphDatabaseContext.beginTx();
|
||||
try {
|
||||
Node node = graphDatabaseContext.createNode();
|
||||
thing = new Thing(node);
|
||||
nodeTypeStrategy.postEntityCreation(thing);
|
||||
thingNode = graphDatabaseContext.createNode();
|
||||
thing = new Thing(thingNode);
|
||||
nodeTypeRepresentationStrategy.postEntityCreation(thingNode, Thing.class);
|
||||
thing.setName("thing");
|
||||
subThingNode = graphDatabaseContext.createNode();
|
||||
subThing = new SubThing(subThingNode);
|
||||
nodeTypeRepresentationStrategy.postEntityCreation(subThingNode, SubThing.class);
|
||||
subThing.setName("subThing");
|
||||
tx.success();
|
||||
return node;
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
}
|
||||
|
||||
private static Node node(Thing thing) {
|
||||
return thing.getPersistentState();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testPreEntityRemoval() throws Exception {
|
||||
Node typeNode = getInstanceofRelationship().getOtherNode(thingNode);
|
||||
nodeTypeStrategy.preEntityRemoval(thing);
|
||||
Assert.assertNull("instanceof relationship was removed", getInstanceofRelationship());
|
||||
Assert.assertEquals("no things left after removal", 0, typeNode.getProperty(SubReferenceTypeRepresentationStrategy.SUBREFERENCE_NODE_COUNTER_KEY));
|
||||
Node typeNode = getInstanceofRelationship(thingNode).getOtherNode(thingNode);
|
||||
nodeTypeRepresentationStrategy.preEntityRemoval(thing);
|
||||
assertNull("instanceof relationship was removed", getInstanceofRelationship(thingNode));
|
||||
assertNotNull("instanceof relationship was removed", getInstanceofRelationship(subThingNode));
|
||||
assertEquals("no things left after removal", 1, typeNode.getProperty(SubReferenceNodeTypeRepresentationStrategy.SUBREFERENCE_NODE_COUNTER_KEY));
|
||||
nodeTypeRepresentationStrategy.preEntityRemoval(subThing);
|
||||
assertNull("instanceof relationship was removed", getInstanceofRelationship(subThingNode));
|
||||
assertEquals("no things left after removal", 0, typeNode.getProperty(SubReferenceNodeTypeRepresentationStrategy.SUBREFERENCE_NODE_COUNTER_KEY));
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
private Relationship getInstanceofRelationship() {
|
||||
return thingNode.getSingleRelationship(SubReferenceTypeRepresentationStrategy.INSTANCE_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
|
||||
private Relationship getInstanceofRelationship(Node node) {
|
||||
return node.getSingleRelationship(SubReferenceNodeTypeRepresentationStrategy.INSTANCE_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCount() throws Exception {
|
||||
Assert.assertEquals("one thing created", 1, nodeTypeStrategy.count(Thing.class));
|
||||
assertEquals("one thing created", 2, nodeTypeRepresentationStrategy.count(Thing.class));
|
||||
assertEquals("one thing created", 1, nodeTypeRepresentationStrategy.count(SubThing.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testGetJavaType() throws Exception {
|
||||
Assert.assertEquals("class in graph is thing", Thing.class, nodeTypeStrategy.<NodeBacked>getJavaType(thingNode));
|
||||
assertEquals("class in graph is thing", Thing.class, nodeTypeRepresentationStrategy.getJavaType(thingNode));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testConfirmType() throws Exception {
|
||||
Assert.assertEquals("class in graph is thing", Thing.class, nodeTypeStrategy.confirmType(thingNode,Thing.class));
|
||||
|
||||
public void testFindAllThings() throws Exception {
|
||||
Collection<Thing> things = IteratorUtil.asCollection(nodeTypeRepresentationStrategy.findAll(Thing.class));
|
||||
assertEquals("one thing created and found", 2, things.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFindAll() throws Exception {
|
||||
Collection<Thing> things = IteratorUtil.asCollection(nodeTypeStrategy.findAll(Thing.class));
|
||||
Assert.assertEquals("one thing created and found", 1, things.size());
|
||||
Assert.assertTrue("result only contains Thing", things.iterator().next() instanceof Thing);
|
||||
public void testFindAllSubThings() {
|
||||
Collection<SubThing> things = IteratorUtil.asCollection(nodeTypeRepresentationStrategy.findAll(SubThing.class));
|
||||
assertEquals("one thing created and found", Collections.<SubThing>singleton(subThing), new HashSet<SubThing>(things));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testInstantiateConcreteClass() {
|
||||
@@ -191,6 +195,37 @@ public class SubReferenceTypeRepresentationStrategyTest {
|
||||
assertEquals("Wrong Person instance count.", (Long)2L, graphRepositoryFactory.createNodeEntityRepository(Person.class).count());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateEntityAndInferType() throws Exception {
|
||||
Thing newThing = nodeTypeRepresentationStrategy.createEntity(node(thing));
|
||||
assertEquals(thing, newThing);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateEntityAndSpecifyType() throws Exception {
|
||||
Thing newThing = nodeTypeRepresentationStrategy.createEntity(node(subThing), Thing.class);
|
||||
assertEquals(subThing, newThing);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testProjectEntity() throws Exception {
|
||||
Unrelated other = nodeTypeRepresentationStrategy.projectEntity(node(thing), Unrelated.class);
|
||||
assertEquals("thing", other.getName());
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
public static class Unrelated {
|
||||
String name;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
public static class Thing {
|
||||
String name;
|
||||
@@ -201,5 +236,22 @@ public class SubReferenceTypeRepresentationStrategyTest {
|
||||
public Thing(Node n) {
|
||||
setPersistentState(n);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SubThing extends Thing {
|
||||
public SubThing(Node n) {
|
||||
super(n);
|
||||
}
|
||||
|
||||
public SubThing() {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -88,29 +88,29 @@
|
||||
|
||||
<bean id="graphDatabaseContext" class="org.springframework.data.graph.neo4j.support.GraphDatabaseContext">
|
||||
<property name="graphDatabaseService" ref="graphDatabaseService"/>
|
||||
<property name="relationshipEntityInstantiator" ref="relationshipEntityInstantiator"/>
|
||||
<property name="graphEntityInstantiator">
|
||||
<bean class="org.springframework.data.graph.neo4j.support.node.PartialNeo4jEntityInstantiator">
|
||||
<constructor-arg ref="graphEntityInstantiator"/>
|
||||
<constructor-arg ref="entityManagerFactory"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="conversionService">
|
||||
<bean class="org.springframework.data.graph.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean"/>
|
||||
</property>
|
||||
<property name="typeRepresentationStrategy" ref="typeRepresentationStrategy"/>
|
||||
<property name="nodeTypeRepresentationStrategy" ref="nodeTypeRepresentationStrategy"/>
|
||||
<property name="relationshipTypeRepresentationStrategy" ref="relationshipTypeRepresentationStrategy"/>
|
||||
</bean>
|
||||
<bean id="graphEntityInstantiator" class="org.springframework.data.graph.neo4j.support.node.PartialNeo4jEntityInstantiator">
|
||||
<constructor-arg>
|
||||
<bean class="org.springframework.data.graph.neo4j.support.node.Neo4jConstructorGraphEntityInstantiator" />
|
||||
</constructor-arg>
|
||||
<constructor-arg ref="entityManagerFactory"/>
|
||||
</bean>
|
||||
<bean id="relationshipEntityInstantiator"
|
||||
class="org.springframework.data.graph.neo4j.support.relationship.ConstructorBypassingGraphRelationshipInstantiator"/>
|
||||
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.TypeRepresentationStrategyFactoryBean">
|
||||
<bean id="typeRepresentationStrategyFactory" class="org.springframework.data.graph.neo4j.support.TypeRepresentationStrategyFactory">
|
||||
<constructor-arg ref="graphDatabaseService"/>
|
||||
<constructor-arg ref="graphEntityInstantiator"/>
|
||||
<constructor-arg ref="relationshipEntityInstantiator"/>
|
||||
</bean>
|
||||
|
||||
<bean id="graphEntityInstantiator"
|
||||
class="org.springframework.data.graph.neo4j.support.node.Neo4jConstructorGraphEntityInstantiator"/>
|
||||
<bean id="nodeTypeRepresentationStrategy" factory-bean="typeRepresentationStrategyFactory" factory-method="getNodeTypeRepresentationStrategy" />
|
||||
<bean id="relationshipTypeRepresentationStrategy" factory-bean="typeRepresentationStrategyFactory" factory-method="getRelationshipTypeRepresentationStrategy"/>
|
||||
|
||||
<bean id="nodeEntityStateFactory" class="org.springframework.data.graph.neo4j.fieldaccess.NodeEntityStateFactory">
|
||||
<property name="nodeDelegatingFieldAccessorFactory">
|
||||
|
||||
@@ -14,9 +14,12 @@
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.IndexingTypeRepresentationStrategy">
|
||||
<bean id="nodeTypeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.IndexingNodeTypeRepresentationStrategy">
|
||||
<constructor-arg ref="graphDatabaseService" />
|
||||
<constructor-arg ref="graphEntityInstantiator" />
|
||||
</bean>
|
||||
<bean id="relationshipTypeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.IndexingRelationshipTypeRepresentationStrategy">
|
||||
<constructor-arg ref="graphDatabaseService" />
|
||||
<constructor-arg ref="relationshipEntityInstantiator" />
|
||||
</bean>
|
||||
</beans>
|
||||
@@ -84,12 +84,11 @@
|
||||
|
||||
<bean id="graphDatabaseContext" class="org.springframework.data.graph.neo4j.support.GraphDatabaseContext">
|
||||
<property name="graphDatabaseService" ref="graphDatabaseService"/>
|
||||
<property name="relationshipEntityInstantiator" ref="relationshipEntityInstantiator"/>
|
||||
<property name="graphEntityInstantiator" ref="graphEntityInstantiator"/>
|
||||
<property name="conversionService">
|
||||
<bean class="org.springframework.data.graph.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean"/>
|
||||
</property>
|
||||
<property name="typeRepresentationStrategy" ref="typeRepresentationStrategy"/>
|
||||
<property name="nodeTypeRepresentationStrategy" ref="nodeTypeRepresentationStrategy"/>
|
||||
<property name="relationshipTypeRepresentationStrategy" ref="relationshipTypeRepresentationStrategy"/>
|
||||
<property name="validator">
|
||||
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
|
||||
</property>
|
||||
@@ -101,12 +100,15 @@
|
||||
<bean id="graphEntityInstantiator"
|
||||
class="org.springframework.data.graph.neo4j.support.node.Neo4jConstructorGraphEntityInstantiator"/>
|
||||
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.TypeRepresentationStrategyFactoryBean">
|
||||
<constructor-arg ref="graphDatabaseService" />
|
||||
<constructor-arg ref="graphEntityInstantiator" />
|
||||
<constructor-arg ref="relationshipEntityInstantiator" />
|
||||
<bean id="typeRepresentationStrategyFactory" class="org.springframework.data.graph.neo4j.support.TypeRepresentationStrategyFactory">
|
||||
<constructor-arg ref="graphDatabaseService"/>
|
||||
<constructor-arg ref="graphEntityInstantiator"/>
|
||||
<constructor-arg ref="relationshipEntityInstantiator"/>
|
||||
</bean>
|
||||
|
||||
<bean id="nodeTypeRepresentationStrategy" factory-bean="typeRepresentationStrategyFactory" factory-method="getNodeTypeRepresentationStrategy" />
|
||||
<bean id="relationshipTypeRepresentationStrategy" factory-bean="typeRepresentationStrategyFactory" factory-method="getRelationshipTypeRepresentationStrategy"/>
|
||||
|
||||
<bean id="nodeEntityStateFactory" class="org.springframework.data.graph.neo4j.fieldaccess.NodeEntityStateFactory">
|
||||
<property name="nodeDelegatingFieldAccessorFactory">
|
||||
<bean class="org.springframework.data.graph.neo4j.fieldaccess.NodeDelegatingFieldAccessorFactory">
|
||||
|
||||
@@ -14,5 +14,5 @@
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.NoopTypeRepresentationStrategy" />
|
||||
<!--<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.NoopTypeRepresentationStrategy" />-->
|
||||
</beans>
|
||||
@@ -14,7 +14,7 @@
|
||||
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
|
||||
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.SubReferenceTypeRepresentationStrategy">
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.SubReferenceNodeTypeRepresentationStrategy">
|
||||
<constructor-arg ref="graphDatabaseService"/>
|
||||
<constructor-arg ref="graphEntityInstantiator" />
|
||||
</bean>
|
||||
Reference in New Issue
Block a user