Merge branch 'master' into rest
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.SubReferenceNodeTypeStrategy=DEBUG
|
||||
#log4j.category.org.springframework.data.graph.neo4j.support.SubReferenceTypeRepresentationStrategy=DEBUG
|
||||
#log4j.category.org.springframework.data.graph.neo4j.fieldaccess=DEBUG
|
||||
#log4j.category.org.springframework.data=TRACE
|
||||
#log4j.category.org.springframework.data.support=TRACE
|
||||
|
||||
@@ -97,10 +97,10 @@
|
||||
<property name="conversionService">
|
||||
<bean class="org.springframework.data.graph.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean"/>
|
||||
</property>
|
||||
<property name="nodeTypeStrategy" ref="nodeTypeStrategy"/>
|
||||
<property name="typeRepresentationStrategy" ref="typeRepresentationStrategy"/>
|
||||
</bean>
|
||||
|
||||
<bean id="nodeTypeStrategy" class="org.springframework.data.graph.neo4j.support.NodeTypeStrategyFactoryBean">
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.NodeTypeStrategyFactoryBean">
|
||||
<constructor-arg ref="graphDatabaseService"/>
|
||||
<constructor-arg ref="graphEntityInstantiator"/>
|
||||
</bean>
|
||||
|
||||
@@ -27,6 +27,7 @@ package org.springframework.data.graph.core;
|
||||
public interface GraphBacked<STATE> {
|
||||
/**
|
||||
* internal setter used for initializing the graph-db state on existing or newly created entities
|
||||
*
|
||||
* @param state (Node or Relationship)
|
||||
*/
|
||||
void setPersistentState(STATE state);
|
||||
@@ -35,4 +36,13 @@ public interface GraphBacked<STATE> {
|
||||
* @return the underlying graph-db state or null if the current entity is not related to the graph-store (possible with unsaved or partial entities)
|
||||
*/
|
||||
STATE getPersistentState();
|
||||
|
||||
boolean hasPersistentState();
|
||||
|
||||
/**
|
||||
* removes the entity using @{link GraphDatabaseContext.removeNodeEntity}
|
||||
* the entity and relationship are still accessible after removal but before transaction commit
|
||||
* but all modifications will throw an exception
|
||||
*/
|
||||
void remove();
|
||||
}
|
||||
|
||||
@@ -17,14 +17,126 @@
|
||||
package org.springframework.data.graph.core;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.springframework.data.graph.neo4j.fieldaccess.EntityState;
|
||||
|
||||
/**
|
||||
* Interface introduced to objects annotated with @NodeEntity by the {@link org.springframework.data.graph.neo4j.support.node.Neo4jNodeBacking} aspect.
|
||||
* annotation, to hold underlying Neo4j Node state.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
*/
|
||||
public interface NodeBacked extends GraphBacked<Node> {
|
||||
|
||||
// Relationship relateTo(NodeBacked nb, RelationshipType type);
|
||||
/**
|
||||
* Attach the entity inside a running transaction. Creating or changing an entity outside of a transaction
|
||||
* detaches it. It must be subsequently attached in order to be persisted.
|
||||
*
|
||||
* @return the attached entity
|
||||
*/
|
||||
<T extends NodeBacked> T persist();
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Creates a relationship to the target node, returning a relationship entity representing the created
|
||||
* relationship.
|
||||
* </p>
|
||||
* <p/>
|
||||
* <p>
|
||||
* Example:
|
||||
* <pre>
|
||||
* public class Person {
|
||||
* ...
|
||||
* public Friendship knows(Person p) {
|
||||
* return (Friendship) relateTo(p, Friendship.class, "knows");
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* </pre>
|
||||
* </p>
|
||||
*
|
||||
* @param target other entity
|
||||
* @param relationshipClass relationship entity class
|
||||
* @param relationshipType type of relationship to be created
|
||||
* @return relationship entity of specified relationshipClass
|
||||
*/
|
||||
<R extends RelationshipBacked, N extends NodeBacked> R relateTo(N target, Class<R> relationshipClass, String relationshipType);
|
||||
|
||||
|
||||
/**
|
||||
* Reify this entity as another node backed type. The same underlying node will be used for the new entity.
|
||||
*
|
||||
* @param targetType type to project to
|
||||
* @return new instance of specified type, sharing the same underlying node with this entity
|
||||
*/
|
||||
<T extends NodeBacked> T projectTo(Class<T> targetType);
|
||||
|
||||
|
||||
/**
|
||||
* Get the ID of the entity.
|
||||
*
|
||||
* @return underlying node ID, or null if there is no underlying node
|
||||
*/
|
||||
Long getNodeId();
|
||||
|
||||
|
||||
/**
|
||||
* Perform a traversal from this entity's underlying node with the given traversal description. The found nodes
|
||||
* are used as underlying nodes for new entities of the specified type.
|
||||
* provided target type
|
||||
*
|
||||
* @param targetType node entity type for new entities
|
||||
* @param traversalDescription traversal description used
|
||||
* @return Lazy {@link java.lang.Iterable} over the traversal results, converted to the expected node
|
||||
* entity instances
|
||||
*/
|
||||
<T extends NodeBacked> Iterable<T> findAllByTraversal(final Class<T> targetType, TraversalDescription traversalDescription);
|
||||
|
||||
|
||||
/**
|
||||
* Removes the all relationships of the given type between this entity's underlying node and the target
|
||||
* entity's underlying node. Note that this is handled automatically by
|
||||
* {@link org.springframework.data.graph.annotation.RelatedTo} fields,
|
||||
* single-relationship non-annotated fields, and
|
||||
* {@link org.springframework.data.graph.annotation.RelatedToVia} fields.
|
||||
*
|
||||
* @param target other node entity
|
||||
* @param relationshipType type to be removed
|
||||
*/
|
||||
void removeRelationshipTo(NodeBacked target, String relationshipType);
|
||||
|
||||
/**
|
||||
* Finds the relationship of the specified type, from this entity's underlying node to the target entity's
|
||||
* underlying node. If a relationship is found, it is used as state for a relationship entity that is returned.
|
||||
*
|
||||
* @param target end node of relationship
|
||||
* @param relationshipClass class of the relationship entity
|
||||
* @param type type of the sought relationship
|
||||
* @return Instance of the requested relationshipClass if the relationship was found, null otherwise
|
||||
*/
|
||||
<R extends RelationshipBacked> R getRelationshipTo(NodeBacked target, Class<R> relationshipClass, String type);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Relationship getRelationshipTo(NodeBacked target, String type);
|
||||
|
||||
/**
|
||||
* Creates a relationship to the target node entity with the given relationship type.
|
||||
*
|
||||
* @param target entity
|
||||
* @param type neo4j relationship type for the underlying relationship
|
||||
* @return the newly created relationship to the target node
|
||||
*/
|
||||
Relationship relateTo(NodeBacked target, String type);
|
||||
|
||||
// get internal state object
|
||||
EntityState<NodeBacked, Node> getEntityState();
|
||||
|
||||
|
||||
// will possibly be used for object graphs
|
||||
boolean refersTo(GraphBacked target);
|
||||
}
|
||||
|
||||
@@ -23,5 +23,19 @@ import org.neo4j.graphdb.Relationship;
|
||||
* aspect, encapsulates a neo4j relationship as backing state
|
||||
*/
|
||||
public interface RelationshipBacked extends GraphBacked<Relationship>{
|
||||
|
||||
|
||||
/**
|
||||
* @return relationship id if there is an underlying relationship
|
||||
*/
|
||||
Long getRelationshipId();
|
||||
|
||||
|
||||
/**
|
||||
* Reify this relationship entity as another relationship backed type. The same underlying relationship will be
|
||||
* used for the new entity.
|
||||
*
|
||||
* @param targetType type to project to
|
||||
* @return new instance of specified type, sharing the same underlying relationship with this entity
|
||||
*/
|
||||
<R extends RelationshipBacked> R projectTo(Class<R> targetType);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.data.graph.core;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.data.graph.core.NodeBacked;
|
||||
|
||||
/**
|
||||
* Strategy to handle representation of java types in the graph. Possible implementation are type/class nodes
|
||||
@@ -30,7 +29,7 @@ import org.springframework.data.graph.core.NodeBacked;
|
||||
* @author Michael Hunger
|
||||
* @since 13.09.2010
|
||||
*/
|
||||
public interface NodeTypeStrategy {
|
||||
public interface TypeRepresentationStrategy {
|
||||
/**
|
||||
* callback on entity creation for setting up type representation
|
||||
* @param entity
|
||||
@@ -95,7 +95,7 @@ public class Neo4jConfiguration {
|
||||
gdc.setGraphEntityInstantiator(graphEntityInstantiator);
|
||||
gdc.setConversionService(conversionService());
|
||||
NodeTypeStrategyFactoryBean nodeTypeStrategyFactoryBean = new NodeTypeStrategyFactoryBean(graphDatabaseService, graphEntityInstantiator);
|
||||
gdc.setNodeTypeStrategy(nodeTypeStrategyFactoryBean.getObject());
|
||||
gdc.setTypeRepresentationStrategy(nodeTypeStrategyFactoryBean.getObject());
|
||||
if (validator!=null) {
|
||||
gdc.setValidator(validator);
|
||||
}
|
||||
@@ -144,6 +144,7 @@ public class Neo4jConfiguration {
|
||||
NodeEntityStateFactory entityStateFactory = new NodeEntityStateFactory();
|
||||
entityStateFactory.setGraphDatabaseContext(graphDatabaseContext);
|
||||
entityStateFactory.setFinderFactory(finderFactory);
|
||||
entityStateFactory.setEntityManagerFactory(entityManagerFactory);
|
||||
entityStateFactory.setNodeDelegatingFieldAccessorFactory(
|
||||
new NodeDelegatingFieldAccessorFactory(graphDatabaseContext, finderFactory));
|
||||
aspect.setNodeEntityStateFactory(entityStateFactory);
|
||||
|
||||
@@ -22,9 +22,8 @@ import org.springframework.data.graph.core.NodeBacked;
|
||||
import org.springframework.data.graph.neo4j.finder.FinderFactory;
|
||||
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.springframework.data.graph.neo4j.fieldaccess.PartialNodeEntityState.getId;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceUnitUtil;
|
||||
|
||||
public class NodeEntityStateFactory {
|
||||
|
||||
@@ -32,16 +31,18 @@ public class NodeEntityStateFactory {
|
||||
|
||||
private FinderFactory finderFactory;
|
||||
|
||||
private EntityManagerFactory entityManagerFactory;
|
||||
|
||||
private NodeDelegatingFieldAccessorFactory nodeDelegatingFieldAccessorFactory;
|
||||
|
||||
public EntityState<NodeBacked,Node> getEntityState(final NodeBacked entity) {
|
||||
final NodeEntity graphEntityAnnotation = entity.getClass().getAnnotation(NodeEntity.class); // todo cache ??
|
||||
if (graphEntityAnnotation.partial()) {
|
||||
PartialNodeEntityState<NodeBacked> partialNodeEntityState = new PartialNodeEntityState<NodeBacked>(null, entity, entity.getClass(), graphDatabaseContext, finderFactory);
|
||||
final PartialNodeEntityState<NodeBacked> partialNodeEntityState = new PartialNodeEntityState<NodeBacked>(null, entity, entity.getClass(), graphDatabaseContext, finderFactory, getPersistenceUnitUtils());
|
||||
return new DetachedEntityState<NodeBacked, Node>(partialNodeEntityState, graphDatabaseContext) {
|
||||
@Override
|
||||
protected boolean isDetached() {
|
||||
return super.isDetached() || getId(entity, entity.getClass()) == null;
|
||||
return super.isDetached() || partialNodeEntityState.getId(entity) == null;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
@@ -51,7 +52,12 @@ public class NodeEntityStateFactory {
|
||||
}
|
||||
}
|
||||
|
||||
public void setNodeDelegatingFieldAccessorFactory(
|
||||
private PersistenceUnitUtil getPersistenceUnitUtils() {
|
||||
if (entityManagerFactory == null) return null;
|
||||
return entityManagerFactory.getPersistenceUnitUtil();
|
||||
}
|
||||
|
||||
public void setNodeDelegatingFieldAccessorFactory(
|
||||
NodeDelegatingFieldAccessorFactory nodeDelegatingFieldAccessorFactory) {
|
||||
this.nodeDelegatingFieldAccessorFactory = nodeDelegatingFieldAccessorFactory;
|
||||
}
|
||||
@@ -64,4 +70,7 @@ public class NodeEntityStateFactory {
|
||||
this.finderFactory = finderFactory;
|
||||
}
|
||||
|
||||
public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
|
||||
this.entityManagerFactory = entityManagerFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.data.graph.neo4j.finder.FinderFactory;
|
||||
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.persistence.StateProvider;
|
||||
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.PersistenceUnitUtil;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -43,8 +43,9 @@ public class PartialNodeEntityState<ENTITY extends NodeBacked> extends DefaultEn
|
||||
public static final String FOREIGN_ID_INDEX = "foreign_id";
|
||||
|
||||
private final GraphDatabaseContext graphDatabaseContext;
|
||||
private PersistenceUnitUtil persistenceUnitUtil;
|
||||
|
||||
public PartialNodeEntityState(final Node underlyingState, final ENTITY entity, final Class<? extends ENTITY> type, final GraphDatabaseContext graphDatabaseContext, final FinderFactory finderFactory) {
|
||||
public PartialNodeEntityState(final Node underlyingState, final ENTITY entity, final Class<? extends ENTITY> type, final GraphDatabaseContext graphDatabaseContext, final FinderFactory finderFactory, PersistenceUnitUtil persistenceUnitUtil) {
|
||||
super(underlyingState, entity, type, new DelegatingFieldAccessorFactory(graphDatabaseContext, finderFactory) {
|
||||
|
||||
@Override
|
||||
@@ -101,6 +102,7 @@ public class PartialNodeEntityState<ENTITY extends NodeBacked> extends DefaultEn
|
||||
}
|
||||
});
|
||||
this.graphDatabaseContext = graphDatabaseContext;
|
||||
this.persistenceUnitUtil = persistenceUnitUtil;
|
||||
}
|
||||
|
||||
// TODO handle non persisted Entity like running outside of an transaction
|
||||
@@ -108,7 +110,7 @@ public class PartialNodeEntityState<ENTITY extends NodeBacked> extends DefaultEn
|
||||
public void createAndAssignState() {
|
||||
if (entity.getPersistentState() != null) return;
|
||||
try {
|
||||
final Object id = getId(entity,type);
|
||||
final Object id = getId(entity);
|
||||
if (id == null) return;
|
||||
final String foreignId = createForeignId(id);
|
||||
IndexHits<Node> indexHits = getForeignIdIndex().get(FOREIGN_ID, foreignId);
|
||||
@@ -162,21 +164,7 @@ public class PartialNodeEntityState<ENTITY extends NodeBacked> extends DefaultEn
|
||||
return type.getName() + ":" + id;
|
||||
}
|
||||
|
||||
public static Object getId(final Object entity, Class type) {
|
||||
Class clazz = type;
|
||||
while (clazz != null) {
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.isAnnotationPresent(Id.class)) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
return field.get(entity);
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
return null;
|
||||
public Object getId(final Object entity) {
|
||||
return persistenceUnitUtil!=null ? persistenceUnitUtil.getIdentifier(entity) : null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
|
||||
import java.util.Collections;
|
||||
|
||||
/**
|
||||
* Repository like finder for Node and Relationship-Entities. Provides finder methods for direct access, access via {@link org.springframework.data.graph.core.NodeTypeStrategy}
|
||||
* Repository like finder for Node and Relationship-Entities. Provides finder methods for direct access, access via {@link org.springframework.data.graph.core.TypeRepresentationStrategy}
|
||||
* and indexing.
|
||||
*
|
||||
* @param <T> GraphBacked target of this finder, enables the finder methods to return this concrete type
|
||||
|
||||
@@ -27,7 +27,7 @@ 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.NodeTypeStrategy;
|
||||
import org.springframework.data.graph.core.TypeRepresentationStrategy;
|
||||
import org.springframework.data.graph.core.RelationshipBacked;
|
||||
import org.springframework.data.persistence.EntityInstantiator;
|
||||
|
||||
@@ -39,7 +39,7 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* Mediator class for the graph related services like the {@link GraphDatabaseService}, the used
|
||||
* {@link NodeTypeStrategy}, entity instantiators for nodes and relationships as well as a spring conversion service.
|
||||
* {@link org.springframework.data.graph.core.TypeRepresentationStrategy}, entity instantiators for nodes and relationships as well as a spring conversion service.
|
||||
*
|
||||
* It delegates the appropriate methods to those services. The services are not intended to be accessible from outside.
|
||||
*
|
||||
@@ -59,7 +59,7 @@ public class GraphDatabaseContext {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private NodeTypeStrategy nodeTypeStrategy;
|
||||
private TypeRepresentationStrategy typeRepresentationStrategy;
|
||||
|
||||
private Validator validator;
|
||||
|
||||
@@ -99,12 +99,12 @@ public class GraphDatabaseContext {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public NodeTypeStrategy getNodeTypeStrategy() {
|
||||
return nodeTypeStrategy;
|
||||
public TypeRepresentationStrategy getTypeRepresentationStrategy() {
|
||||
return typeRepresentationStrategy;
|
||||
}
|
||||
|
||||
public void setNodeTypeStrategy(NodeTypeStrategy nodeTypeStrategy) {
|
||||
this.nodeTypeStrategy = nodeTypeStrategy;
|
||||
public void setTypeRepresentationStrategy(TypeRepresentationStrategy typeRepresentationStrategy) {
|
||||
this.typeRepresentationStrategy = typeRepresentationStrategy;
|
||||
}
|
||||
|
||||
public Node createNode() {
|
||||
@@ -139,7 +139,7 @@ public class GraphDatabaseContext {
|
||||
public void removeNodeEntity(NodeBacked entity) {
|
||||
Node node = entity.getPersistentState();
|
||||
if (node==null) return;
|
||||
this.nodeTypeStrategy.preEntityRemoval(entity);
|
||||
this.typeRepresentationStrategy.preEntityRemoval(entity);
|
||||
for (Relationship relationship : node.getRelationships()) {
|
||||
removeRelationship(relationship);
|
||||
}
|
||||
@@ -171,7 +171,7 @@ 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, nodeTypeStrategy.confirmType((Node)state, (Class<? extends 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);
|
||||
}
|
||||
@@ -214,15 +214,15 @@ public class GraphDatabaseContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates to the configured @{link NodeTypeStrategy} for after entity creation operations
|
||||
* delegates to the configured @{link TypeRepresentationStrategy} for after entity creation operations
|
||||
* @param entity
|
||||
*/
|
||||
public void postEntityCreation(final NodeBacked entity) {
|
||||
nodeTypeStrategy.postEntityCreation(entity);
|
||||
typeRepresentationStrategy.postEntityCreation(entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates to the configured @{link NodeTypeStrategy} to iterate over all instances of this type
|
||||
* delegates to the configured @{link TypeRepresentationStrategy} to iterate over all instances of this type
|
||||
* @param clazz type of entity
|
||||
* @param <T>
|
||||
* @return
|
||||
@@ -230,7 +230,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>) nodeTypeStrategy.findAll((Class<NodeBacked>)clazz);
|
||||
return (Iterable<T>) typeRepresentationStrategy.findAll((Class<NodeBacked>)clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,24 +241,24 @@ public class GraphDatabaseContext {
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates to the configured @{link NodeTypeStrategy} for a count of all instances of this type
|
||||
* delegates to the configured @{link TypeRepresentationStrategy} for a count of all instances of this type
|
||||
* @param entityClass
|
||||
* @return count of all instances
|
||||
*/
|
||||
public long count(final Class<? extends GraphBacked> entityClass) {
|
||||
if (!checkIsNodeBacked(entityClass)) throw new UnsupportedOperationException("No support for relationships");
|
||||
return nodeTypeStrategy.count((Class<NodeBacked>)entityClass);
|
||||
return typeRepresentationStrategy.count((Class<NodeBacked>)entityClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* delegates to the configured @{link NodeTypeStrategy} to lookup the type information for the given node
|
||||
* delegates to the configured @{link TypeRepresentationStrategy} to lookup the type information for the given node
|
||||
* @param node
|
||||
* @param <T>
|
||||
* @return entity type of the node
|
||||
* @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 nodeTypeStrategy.getJavaType(node);
|
||||
return typeRepresentationStrategy.getJavaType(node);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,7 +327,7 @@ public class GraphDatabaseContext {
|
||||
}
|
||||
|
||||
public <T extends NodeBacked> T createEntityFromStoredType(Node node) {
|
||||
return (T)graphEntityInstantiator.createEntityFromState(node,nodeTypeStrategy.<NodeBacked>getJavaType(node));
|
||||
return (T)graphEntityInstantiator.createEntityFromState(node, typeRepresentationStrategy.<NodeBacked>getJavaType(node));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ 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.NodeBacked;
|
||||
import org.springframework.data.graph.core.NodeTypeStrategy;
|
||||
import org.springframework.data.graph.core.TypeRepresentationStrategy;
|
||||
import org.springframework.data.persistence.EntityInstantiator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class IndexingNodeTypeStrategy implements NodeTypeStrategy {
|
||||
public class IndexingTypeRepresentationStrategy implements TypeRepresentationStrategy {
|
||||
|
||||
public static final String NODE_INDEX_NAME = "__types__";
|
||||
public static final String TYPE_PROPERTY_NAME = "__type__";
|
||||
@@ -25,7 +25,7 @@ public class IndexingNodeTypeStrategy implements NodeTypeStrategy {
|
||||
private GraphDatabaseService graphDb;
|
||||
private final Map<String,Class<?>> cache=new HashMap<String, Class<?>>();
|
||||
|
||||
public IndexingNodeTypeStrategy(GraphDatabaseService graphDb, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
public IndexingTypeRepresentationStrategy(GraphDatabaseService graphDb, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
this.graphDb = graphDb;
|
||||
this.graphEntityInstantiator = graphEntityInstantiator;
|
||||
}
|
||||
@@ -5,10 +5,10 @@ import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.data.graph.core.NodeBacked;
|
||||
import org.springframework.data.graph.core.NodeTypeStrategy;
|
||||
import org.springframework.data.graph.core.TypeRepresentationStrategy;
|
||||
import org.springframework.data.persistence.EntityInstantiator;
|
||||
|
||||
public class NodeTypeStrategyFactoryBean implements FactoryBean<NodeTypeStrategy> {
|
||||
public class NodeTypeStrategyFactoryBean implements FactoryBean<TypeRepresentationStrategy> {
|
||||
private GraphDatabaseService graphDatabaseService;
|
||||
private EntityInstantiator<NodeBacked, Node> graphEntityInstantiator;
|
||||
private Strategy strategy;
|
||||
@@ -26,12 +26,12 @@ public class NodeTypeStrategyFactoryBean implements FactoryBean<NodeTypeStrategy
|
||||
}
|
||||
|
||||
private boolean isAlreadyIndexed() {
|
||||
return graphDatabaseService.index().existsForNodes(IndexingNodeTypeStrategy.NODE_INDEX_NAME);
|
||||
return graphDatabaseService.index().existsForNodes(IndexingTypeRepresentationStrategy.NODE_INDEX_NAME);
|
||||
}
|
||||
|
||||
private boolean isAlreadySubRef() {
|
||||
for (Relationship rel : graphDatabaseService.getReferenceNode().getRelationships()) {
|
||||
if (rel.getType().name().startsWith(SubReferenceNodeTypeStrategy.SUBREF_PREFIX)) {
|
||||
if (rel.getType().name().startsWith(SubReferenceTypeRepresentationStrategy.SUBREF_PREFIX)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ public class NodeTypeStrategyFactoryBean implements FactoryBean<NodeTypeStrategy
|
||||
}
|
||||
|
||||
@Override
|
||||
public NodeTypeStrategy getObject() throws Exception {
|
||||
public TypeRepresentationStrategy getObject() throws Exception {
|
||||
return strategy.getObject(graphDatabaseService, graphEntityInstantiator);
|
||||
}
|
||||
|
||||
@@ -56,38 +56,38 @@ public class NodeTypeStrategyFactoryBean implements FactoryBean<NodeTypeStrategy
|
||||
private enum Strategy {
|
||||
SubRef {
|
||||
@Override
|
||||
NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
return new SubReferenceNodeTypeStrategy(graphDatabaseService, graphEntityInstantiator);
|
||||
TypeRepresentationStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
return new SubReferenceTypeRepresentationStrategy(graphDatabaseService, graphEntityInstantiator);
|
||||
}
|
||||
|
||||
@Override
|
||||
Class<? extends NodeTypeStrategy> getObjectType() {
|
||||
return SubReferenceNodeTypeStrategy.class;
|
||||
Class<? extends TypeRepresentationStrategy> getObjectType() {
|
||||
return SubReferenceTypeRepresentationStrategy.class;
|
||||
}
|
||||
},
|
||||
Indexed {
|
||||
@Override
|
||||
NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
return new IndexingNodeTypeStrategy(graphDatabaseService, graphEntityInstantiator);
|
||||
TypeRepresentationStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
return new IndexingTypeRepresentationStrategy(graphDatabaseService, graphEntityInstantiator);
|
||||
}
|
||||
|
||||
@Override
|
||||
Class<? extends NodeTypeStrategy> getObjectType() {
|
||||
return IndexingNodeTypeStrategy.class;
|
||||
Class<? extends TypeRepresentationStrategy> getObjectType() {
|
||||
return IndexingTypeRepresentationStrategy.class;
|
||||
}
|
||||
},
|
||||
Noop {
|
||||
@Override
|
||||
NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
return new NoopNodeTypeStrategy();
|
||||
TypeRepresentationStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
return new NoopTypeRepresentationStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
Class<? extends NodeTypeStrategy> getObjectType() {
|
||||
return NoopNodeTypeStrategy.class;
|
||||
Class<? extends TypeRepresentationStrategy> getObjectType() {
|
||||
return NoopTypeRepresentationStrategy.class;
|
||||
}
|
||||
};
|
||||
abstract NodeTypeStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator);
|
||||
abstract Class<? extends NodeTypeStrategy> getObjectType();
|
||||
abstract TypeRepresentationStrategy getObject(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator);
|
||||
abstract Class<? extends TypeRepresentationStrategy> getObjectType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,26 +2,26 @@ package org.springframework.data.graph.neo4j.support;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.data.graph.core.NodeBacked;
|
||||
import org.springframework.data.graph.core.NodeTypeStrategy;
|
||||
import org.springframework.data.graph.core.TypeRepresentationStrategy;
|
||||
|
||||
public class NoopNodeTypeStrategy implements NodeTypeStrategy {
|
||||
public class NoopTypeRepresentationStrategy implements TypeRepresentationStrategy {
|
||||
@Override
|
||||
public void postEntityCreation(NodeBacked entity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends NodeBacked> Iterable<T> findAll(Class<T> clazz) {
|
||||
throw new UnsupportedOperationException("findAll not supported by NoopNodeTypeStrategy.");
|
||||
throw new UnsupportedOperationException("findAll not supported by NoopTypeRepresentationStrategy.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count(Class<? extends NodeBacked> entityClass) {
|
||||
throw new UnsupportedOperationException("count not supported by NoopNodeTypeStrategy.");
|
||||
throw new UnsupportedOperationException("count not supported by NoopTypeRepresentationStrategy.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends NodeBacked> Class<T> getJavaType(Node node) {
|
||||
throw new UnsupportedOperationException("getJavaType not supported NoopNodeTypeStrategy.");
|
||||
throw new UnsupportedOperationException("getJavaType not supported NoopTypeRepresentationStrategy.");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -24,13 +24,13 @@ import org.neo4j.helpers.collection.CombiningIterable;
|
||||
import org.neo4j.helpers.collection.IterableWrapper;
|
||||
import org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl;
|
||||
import org.springframework.data.graph.core.NodeBacked;
|
||||
import org.springframework.data.graph.core.NodeTypeStrategy;
|
||||
import org.springframework.data.graph.core.TypeRepresentationStrategy;
|
||||
import org.springframework.data.persistence.EntityInstantiator;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A {@link NodeTypeStrategy} that uses a hierarchy of reference nodes to represent the java type of the entity in the
|
||||
* 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.
|
||||
@@ -38,8 +38,8 @@ import java.util.*;
|
||||
* @author Michael Hunger
|
||||
* @since 13.09.2010
|
||||
*/
|
||||
public class SubReferenceNodeTypeStrategy implements NodeTypeStrategy {
|
||||
private final static Log log = LogFactory.getLog(SubReferenceNodeTypeStrategy.class);
|
||||
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");
|
||||
@@ -51,7 +51,7 @@ public class SubReferenceNodeTypeStrategy implements NodeTypeStrategy {
|
||||
private GraphDatabaseService graphDatabaseService;
|
||||
private EntityInstantiator<NodeBacked, Node> entityInstantiator;
|
||||
|
||||
public SubReferenceNodeTypeStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> entityInstantiator) {
|
||||
public SubReferenceTypeRepresentationStrategy(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> entityInstantiator) {
|
||||
this.graphDatabaseService = graphDatabaseService;
|
||||
this.entityInstantiator = entityInstantiator;
|
||||
}
|
||||
@@ -23,17 +23,18 @@ import org.aspectj.lang.reflect.FieldSignature;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.graphdb.traversal.Traverser;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.data.graph.core.NodeBacked;
|
||||
import org.springframework.data.graph.core.GraphBacked;
|
||||
import org.springframework.data.graph.core.RelationshipBacked;
|
||||
import org.springframework.data.graph.neo4j.fieldaccess.*;
|
||||
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import org.springframework.data.graph.annotation.*;
|
||||
import javax.persistence.Transient;
|
||||
import javax.persistence.Entity;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.springframework.data.graph.neo4j.fieldaccess.DoReturn.unwrap;
|
||||
|
||||
@@ -106,22 +107,18 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* State accessors that encapsulate the underlying state and the behaviour related to it (field access, creation)
|
||||
*/
|
||||
private transient EntityState<NodeBacked,Node> NodeBacked.entityState;
|
||||
|
||||
public <T extends NodeBacked> T NodeBacked.persist() {
|
||||
return (T)this.entityState.persist();
|
||||
}
|
||||
public boolean NodeBacked.refersTo(GraphBacked target) {
|
||||
return this.entityState.refersTo(target);
|
||||
}
|
||||
/**
|
||||
* State accessors that encapsulate the underlying state and the behaviour related to it (field access, creation)
|
||||
*/
|
||||
private transient EntityState<NodeBacked,Node> NodeBacked.entityState;
|
||||
|
||||
/**
|
||||
* sets the underlying state to the given node, creates an {@link org.springframework.data.graph.neo4j.fieldaccess.EntityState} instance on demand for delegating
|
||||
* the behaviour, otherwise just updates the backing state
|
||||
* @param n the node to be the backing state of the entity
|
||||
*/
|
||||
public void NodeBacked.setPersistentState(Node n) {
|
||||
if (this.entityState == null) {
|
||||
this.entityState = Neo4jNodeBacking.aspectOf().entityStateFactory.getEntityState(this);
|
||||
@@ -133,11 +130,11 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
|
||||
return this.entityState!=null ? this.entityState.getPersistentState() : null;
|
||||
}
|
||||
|
||||
public EntityState NodeBacked.getEntityState() {
|
||||
public EntityState<NodeBacked, Node> NodeBacked.getEntityState() {
|
||||
return entityState;
|
||||
}
|
||||
|
||||
public boolean NodeBacked.hasUnderlyingNode() {
|
||||
public boolean NodeBacked.hasPersistentState() {
|
||||
return this.entityState!=null && this.entityState.hasPersistentState();
|
||||
}
|
||||
|
||||
@@ -145,12 +142,6 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
|
||||
return (T)Neo4jNodeBacking.aspectOf().graphDatabaseContext.projectTo( this, targetType);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a relationship to the target node entity with the given relationship type
|
||||
* @param target entity
|
||||
* @param type neo4j relationship type for the underlying relationship
|
||||
* @return the newly created relationship to the target node
|
||||
*/
|
||||
public Relationship NodeBacked.relateTo(NodeBacked target, String type) {
|
||||
if (target==null) throw new IllegalArgumentException("Target entity is null");
|
||||
if (type==null) throw new IllegalArgumentException("Relationshiptype is null");
|
||||
@@ -171,41 +162,17 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return node id or null if there is no underlying state
|
||||
*/
|
||||
public Long NodeBacked.getNodeId() {
|
||||
if (!hasUnderlyingNode()) return null;
|
||||
if (!hasPersistentState()) return null;
|
||||
return getPersistentState().getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* handles traversal from the current node with the given traversal description, the entities returned must be instances of the
|
||||
* provided target type
|
||||
* @param targetType node entity java types of the traversal results
|
||||
* @param traversalDescription
|
||||
* @return lazy Iterable over the traversal results, converted to the expected node entity instances
|
||||
*/
|
||||
public <T extends NodeBacked> Iterable<T> NodeBacked.findAllByTraversal(final Class<T> targetType, TraversalDescription traversalDescription) {
|
||||
if (!hasUnderlyingNode()) throw new IllegalStateException("No node attached to " + this);
|
||||
if (!hasPersistentState()) throw new IllegalStateException("No node attached to " + this);
|
||||
final Traverser traverser = traversalDescription.traverse(this.getPersistentState());
|
||||
return new NodeBackedNodeIterableWrapper<T>(traverser, targetType, Neo4jNodeBacking.aspectOf().graphDatabaseContext);
|
||||
}
|
||||
|
||||
|
||||
// public Iterable<? extends NodeBacked> NodeBacked.traverse(TraversalDescription traversalDescription) {
|
||||
// final Class<? extends NodeBacked> target = this.getClass();
|
||||
// return this.traverse(target,traversalDescription);
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Creates a relationship to the target node with the given relationship type.
|
||||
* @param target node
|
||||
* @param relationshipClass expected relationship class of the resulting relationship entity
|
||||
* @param relationshipType
|
||||
* @return relationship entity, instance of the provided relationshipClass
|
||||
*/
|
||||
public <R extends RelationshipBacked, N extends NodeBacked> R NodeBacked.relateTo(N target, Class<R> relationshipClass, String relationshipType) {
|
||||
if (target==null) throw new IllegalArgumentException("Target entity is null");
|
||||
if (relationshipClass==null) throw new IllegalArgumentException("Relationship class is null");
|
||||
@@ -215,19 +182,10 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
|
||||
return (R)Neo4jNodeBacking.aspectOf().graphDatabaseContext.createEntityFromState(rel, relationshipClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* removes the entity using @{link GraphDatabaseContext.removeNodeEntity}
|
||||
* the entity and relationship are still accessible after removal but before transaction commit
|
||||
* but all modifications will throw an exception
|
||||
*/
|
||||
public void NodeBacked.remove() {
|
||||
Neo4jNodeBacking.aspectOf().graphDatabaseContext.removeNodeEntity(this);
|
||||
}
|
||||
/**
|
||||
* removes the relationship to the target node entity with the given relationship type
|
||||
* @param target node entity
|
||||
* @param relationshipType
|
||||
*/
|
||||
|
||||
public void NodeBacked.removeRelationshipTo(NodeBacked target, String relationshipType) {
|
||||
if (target==null) throw new IllegalArgumentException("Target entity is null");
|
||||
if (relationshipType==null) throw new IllegalArgumentException("Relationshiptype is null");
|
||||
@@ -243,13 +201,6 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* introduced method for accessing and Relationship Entity instance for the given start node and relationship type.
|
||||
* @param target start node
|
||||
* @param relationshipClass class of the relationship entity
|
||||
* @param type type of the graph relationship
|
||||
* @return and instance of the requested relationshipClass if the relationship was found, null otherwise
|
||||
*/
|
||||
public <R extends RelationshipBacked> R NodeBacked.getRelationshipTo( NodeBacked target, Class<R> relationshipClass, String type) {
|
||||
if (target ==null) throw new IllegalArgumentException("Target entity is null");
|
||||
if (relationshipClass==null) throw new IllegalArgumentException("Relationship class is null");
|
||||
@@ -271,7 +222,7 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
|
||||
*/
|
||||
public final boolean NodeBacked.equals(Object obj) {
|
||||
if (obj == this) return true;
|
||||
if (!hasUnderlyingNode()) return false;
|
||||
if (!hasPersistentState()) return false;
|
||||
if (obj instanceof NodeBacked) {
|
||||
return this.getPersistentState().equals(((NodeBacked) obj).getPersistentState());
|
||||
}
|
||||
@@ -282,7 +233,7 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
|
||||
* @return result of the hashCode of the underlying node (if any, otherwise identityHashCode)
|
||||
*/
|
||||
public final int NodeBacked.hashCode() {
|
||||
if (!hasUnderlyingNode()) return System.identityHashCode(this);
|
||||
if (!hasPersistentState()) return System.identityHashCode(this);
|
||||
return getPersistentState().hashCode();
|
||||
}
|
||||
|
||||
|
||||
@@ -73,10 +73,6 @@ public aspect Neo4jRelationshipBacking {
|
||||
*/
|
||||
private EntityState<RelationshipBacked,Relationship> RelationshipBacked.entityState;
|
||||
|
||||
/**
|
||||
* creates a new {@link org.springframework.data.graph.neo4j.fieldaccess.EntityState} instance with the relationship parameter or updates an existing one
|
||||
* @param r
|
||||
*/
|
||||
public void RelationshipBacked.setPersistentState(Relationship r) {
|
||||
if (this.entityState == null) {
|
||||
this.entityState = Neo4jRelationshipBacking.aspectOf().entityStateFactory.getEntityState(this);
|
||||
@@ -88,15 +84,12 @@ public aspect Neo4jRelationshipBacking {
|
||||
return this.entityState!=null ? this.entityState.getPersistentState() : null;
|
||||
}
|
||||
|
||||
public boolean RelationshipBacked.hasUnderlyingRelationship() {
|
||||
public boolean RelationshipBacked.hasPersistentState() {
|
||||
return this.entityState!=null && this.entityState.hasPersistentState();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return relationship id if there is an underlying relationship
|
||||
*/
|
||||
public Long RelationshipBacked.getRelationshipId() {
|
||||
if (!hasUnderlyingRelationship()) return null;
|
||||
if (!hasPersistentState()) return null;
|
||||
return getPersistentState().getId();
|
||||
}
|
||||
|
||||
@@ -107,7 +100,7 @@ public aspect Neo4jRelationshipBacking {
|
||||
*/
|
||||
public final boolean RelationshipBacked.equals(Object obj) {
|
||||
if (this==obj) return true;
|
||||
if (!hasUnderlyingRelationship()) return false;
|
||||
if (!hasPersistentState()) return false;
|
||||
if (obj instanceof RelationshipBacked) {
|
||||
return this.getPersistentState().equals(((RelationshipBacked) obj).getPersistentState());
|
||||
}
|
||||
@@ -118,7 +111,7 @@ public aspect Neo4jRelationshipBacking {
|
||||
* @return hashCode of the underlying relationship
|
||||
*/
|
||||
public final int RelationshipBacked.hashCode() {
|
||||
if (!hasUnderlyingRelationship()) return System.identityHashCode(this);
|
||||
if (!hasPersistentState()) return System.identityHashCode(this);
|
||||
return getPersistentState().hashCode();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
package org.springframework.data.graph.neo4j;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
/**
|
||||
* EXAMPLE OF CODE THAT SHOULD BE GENERATED BY ROO BESIDES EACH GRAPHENTITY CLASS
|
||||
*
|
||||
* Note: Combines X_Roo_Entity with X_Roo_Finder, as
|
||||
* we need only a single aspect for entities.
|
||||
* @author rodjohnson
|
||||
*
|
||||
*/
|
||||
privileged aspect Person_Graph_Entity {
|
||||
|
||||
// TODO should be a better way of getting this? Could at least pull out gdsholder class
|
||||
private static GraphDatabaseContext graphDatabaseContext() {
|
||||
return new Person_Graph_Entity.GdsHolder().graphDatabaseContext;
|
||||
}
|
||||
|
||||
@Configurable
|
||||
public static class GdsHolder {
|
||||
@Autowired
|
||||
public GraphDatabaseContext graphDatabaseContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add constructor that takes node.
|
||||
* @param node
|
||||
*/
|
||||
public Person.new(Node node) {
|
||||
setPersistentState(node);
|
||||
}
|
||||
|
||||
// public static long Person.countPeople() {
|
||||
// return new SubReferenceNodeTypeStrategy(graphDatabaseContext()).count(Person.class);
|
||||
// }
|
||||
//
|
||||
// public static Iterable<Person> Person.findAllPeople() {
|
||||
// final SubReferenceNodeTypeStrategy strategy = new SubReferenceNodeTypeStrategy(graphDatabaseContext());
|
||||
// return strategy.findAll(Person.class);
|
||||
// }
|
||||
//
|
||||
// public static Person Person.findPerson(Long id) {
|
||||
// Node personNode = Person_Graph_Entity.graphDatabaseContext().getNodeById(id);
|
||||
// return new Person(personNode);
|
||||
// }
|
||||
|
||||
|
||||
// Pluggable query executors/resolvers, discussed with PL
|
||||
// public static Person.findFooBars(int a, int b) {
|
||||
// return executeQuery("foobar", a, b);
|
||||
// // First look for String, then for method
|
||||
// // QueryInterceptionResolver
|
||||
// }
|
||||
|
||||
// public static List<Person> Person.findPersonEntries(int firstResult,
|
||||
// int maxResults) {
|
||||
// throw new UnsupportedOperationException();
|
||||
// }
|
||||
}
|
||||
@@ -36,7 +36,7 @@ public class AttachEntityTest {
|
||||
}
|
||||
|
||||
private boolean hasUnderlyingNode(NodeBacked nodeBacked) {
|
||||
return nodeBacked.hasUnderlyingNode();
|
||||
return nodeBacked.hasPersistentState();
|
||||
}
|
||||
|
||||
private Node nodeFor(NodeBacked nodeBacked) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.springframework.data.graph.neo4j.support;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
@@ -39,7 +38,7 @@ public class IndexingNodeTypeStrategyTest {
|
||||
@Autowired
|
||||
private GraphDatabaseService graphDatabaseService;
|
||||
@Autowired
|
||||
private IndexingNodeTypeStrategy nodeTypeStrategy;
|
||||
private IndexingTypeRepresentationStrategy nodeTypeStrategy;
|
||||
|
||||
private Thing thing;
|
||||
private SubThing subThing;
|
||||
|
||||
@@ -161,7 +161,7 @@ public class ModificationOutsideOfTransactionTest
|
||||
|
||||
private boolean hasUnderlyingNode( Person person )
|
||||
{
|
||||
return person.hasUnderlyingNode();
|
||||
return person.hasPersistentState();
|
||||
}
|
||||
|
||||
private Node nodeFor( Person person )
|
||||
|
||||
@@ -25,7 +25,7 @@ public class NoopNodeTypeStrategyTest {
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
@Autowired
|
||||
private NoopNodeTypeStrategy nodeTypeStrategy;
|
||||
private NoopTypeRepresentationStrategy nodeTypeStrategy;
|
||||
|
||||
private Thing thing;
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ 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.core.NodeTypeStrategy;
|
||||
import org.springframework.data.graph.neo4j.Car;
|
||||
import org.springframework.data.graph.neo4j.Person;
|
||||
import static org.springframework.data.graph.neo4j.Person.persistedPerson;
|
||||
@@ -24,7 +23,6 @@ import org.springframework.data.graph.neo4j.finder.FinderFactory;
|
||||
import org.springframework.data.graph.neo4j.finder.NodeFinder;
|
||||
import org.springframework.data.graph.neo4j.support.node.Neo4jHelper;
|
||||
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
@@ -55,7 +53,7 @@ public class SubReferenceNodeTypeStrategyTest {
|
||||
@Autowired
|
||||
private FinderFactory finderFactory;
|
||||
@Autowired
|
||||
private SubReferenceNodeTypeStrategy nodeTypeStrategy;
|
||||
private SubReferenceTypeRepresentationStrategy nodeTypeStrategy;
|
||||
private Node thingNode;
|
||||
private Thing thing;
|
||||
|
||||
@@ -75,8 +73,8 @@ public class SubReferenceNodeTypeStrategyTest {
|
||||
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(SubReferenceNodeTypeStrategy.SUBREF_CLASS_KEY));
|
||||
Assert.assertEquals("one thing has been created", 1, typeNode.getProperty(SubReferenceNodeTypeStrategy.SUBREFERENCE_NODE_COUNTER_KEY));
|
||||
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));
|
||||
}
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void gettingTypeFromNonTypeNodeShouldThrowAnDescriptiveException() throws Exception {
|
||||
@@ -115,13 +113,13 @@ public class SubReferenceNodeTypeStrategyTest {
|
||||
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(SubReferenceNodeTypeStrategy.SUBREFERENCE_NODE_COUNTER_KEY));
|
||||
Assert.assertEquals("no things left after removal", 0, typeNode.getProperty(SubReferenceTypeRepresentationStrategy.SUBREFERENCE_NODE_COUNTER_KEY));
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
private Relationship getInstanceofRelationship() {
|
||||
return thingNode.getSingleRelationship(SubReferenceNodeTypeStrategy.INSTANCE_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
|
||||
return thingNode.getSingleRelationship(SubReferenceTypeRepresentationStrategy.INSTANCE_OF_RELATIONSHIP_TYPE, Direction.OUTGOING);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -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.SubReferenceNodeTypeStrategy=DEBUG
|
||||
#log4j.category.org.springframework.data.graph.neo4j.support.SubReferenceTypeRepresentationStrategyonStrategy=DEBUG
|
||||
#log4j.category.org.springframework.data.graph.neo4j.fieldaccess=DEBUG
|
||||
#log4j.category.org.springframework.data=TRACE
|
||||
#log4j.category.org.springframework.data.support=TRACE
|
||||
|
||||
@@ -100,10 +100,10 @@
|
||||
<property name="conversionService">
|
||||
<bean class="org.springframework.data.graph.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean"/>
|
||||
</property>
|
||||
<property name="nodeTypeStrategy" ref="nodeTypeStrategy"/>
|
||||
<property name="typeRepresentationStrategy" ref="typeRepresentationStrategy"/>
|
||||
</bean>
|
||||
|
||||
<bean id="nodeTypeStrategy" class="org.springframework.data.graph.neo4j.support.NodeTypeStrategyFactoryBean">
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.NodeTypeStrategyFactoryBean">
|
||||
<constructor-arg ref="graphDatabaseService"/>
|
||||
<constructor-arg ref="graphEntityInstantiator"/>
|
||||
</bean>
|
||||
@@ -120,6 +120,7 @@
|
||||
</property>
|
||||
<property name="graphDatabaseContext" ref="graphDatabaseContext"/>
|
||||
<property name="finderFactory" ref="finderFactory"/>
|
||||
<property name="entityManagerFactory" ref="entityManagerFactory"/>
|
||||
</bean>
|
||||
|
||||
<bean id="relationshipEntityStateFactory" class="org.springframework.data.graph.neo4j.fieldaccess.RelationshipEntityStateFactory">
|
||||
|
||||
@@ -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="nodeTypeStrategy" class="org.springframework.data.graph.neo4j.support.IndexingNodeTypeStrategy">
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.IndexingTypeRepresentationStrategy">
|
||||
<constructor-arg ref="graphDatabaseService" />
|
||||
<constructor-arg ref="graphEntityInstantiator" />
|
||||
</bean>
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
<property name="conversionService">
|
||||
<bean class="org.springframework.data.graph.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean"/>
|
||||
</property>
|
||||
<property name="nodeTypeStrategy" ref="nodeTypeStrategy"/>
|
||||
<property name="typeRepresentationStrategy" ref="typeRepresentationStrategy"/>
|
||||
<property name="validator">
|
||||
<bean class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>
|
||||
</property>
|
||||
@@ -100,7 +100,7 @@
|
||||
<bean id="graphEntityInstantiator"
|
||||
class="org.springframework.data.graph.neo4j.support.node.Neo4jConstructorGraphEntityInstantiator"/>
|
||||
|
||||
<bean id="nodeTypeStrategy" class="org.springframework.data.graph.neo4j.support.NodeTypeStrategyFactoryBean">
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.NodeTypeStrategyFactoryBean">
|
||||
<constructor-arg ref="graphDatabaseService" />
|
||||
<constructor-arg ref="graphEntityInstantiator" />
|
||||
</bean>
|
||||
|
||||
@@ -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="nodeTypeStrategy" class="org.springframework.data.graph.neo4j.support.NoopNodeTypeStrategy" />
|
||||
<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="nodeTypeStrategy" class="org.springframework.data.graph.neo4j.support.SubReferenceNodeTypeStrategy">
|
||||
<bean id="typeRepresentationStrategy" class="org.springframework.data.graph.neo4j.support.SubReferenceTypeRepresentationStrategy">
|
||||
<constructor-arg ref="graphDatabaseService"/>
|
||||
<constructor-arg ref="graphEntityInstantiator" />
|
||||
</bean>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
// simplest example
|
||||
@NodeEntity
|
||||
public class Movie {
|
||||
String title;
|
||||
String title;
|
||||
}
|
||||
]]></programlisting>
|
||||
</section>
|
||||
@@ -47,20 +47,30 @@ public class Movie {
|
||||
null. For multi-relationships the field provides a managed collection (Set) that handles addition and
|
||||
removal of node entities and reflects those in the graph relationships.
|
||||
</para>
|
||||
<para>
|
||||
<code>@RelatedTo</code> also ensures that there is only one relationship of the given type between two
|
||||
given entities.
|
||||
</para>
|
||||
<note>
|
||||
By setting direction to BOTH, relationships are created in the outgoing direction, but when the 1:N field
|
||||
is read, it will include relationships in both directions.
|
||||
</note>
|
||||
<programlisting language="java"><![CDATA[
|
||||
@NodeEntity
|
||||
public class Movie {
|
||||
private Actor topActor;
|
||||
private Actor topActor;
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
public class Person {
|
||||
@RelatedTo(type = "topActor", direction = Direction.INCOMING)
|
||||
private Movie wasTopActorIn;
|
||||
@RelatedTo(type = "topActor", direction = Direction.INCOMING)
|
||||
private Movie wasTopActorIn;
|
||||
}
|
||||
|
||||
@NodeEntity
|
||||
public class Actor {
|
||||
@RelatedTo(type = "ACTS_IN", elementClass = Movie.class)
|
||||
private Set<Movie> movies;
|
||||
@RelatedTo(type = "ACTS_IN", elementClass = Movie.class)
|
||||
private Set<Movie> movies;
|
||||
}
|
||||
]]></programlisting>
|
||||
</section>
|
||||
@@ -82,8 +92,8 @@ public class Actor {
|
||||
public class Role {
|
||||
String title;
|
||||
|
||||
@StartNode private Actor actor;
|
||||
@EndNode private Movie movie;
|
||||
@StartNode private Actor actor;
|
||||
@EndNode private Movie movie;
|
||||
}
|
||||
]]></programlisting>
|
||||
</section>
|
||||
@@ -100,13 +110,13 @@ public class Role {
|
||||
<programlisting language="java"><![CDATA[
|
||||
@NodeEntity
|
||||
public class Actor {
|
||||
@RelatedToVia(type = "ACTS_IN", elementClass = Role.class)
|
||||
private Iterable<Role> roles;
|
||||
@RelatedToVia(type = "ACTS_IN", elementClass = Role.class)
|
||||
private Iterable<Role> roles;
|
||||
|
||||
public Role playedIn(Movie movie, String title) {
|
||||
Role role=relateTo(movie,Role.class,"ACTS_IN");
|
||||
role.setTitle(title);
|
||||
return role;
|
||||
public Role playedIn(Movie movie, String title) {
|
||||
Role role=relateTo(movie,Role.class,"ACTS_IN");
|
||||
role.setTitle(title);
|
||||
return role;
|
||||
}
|
||||
}
|
||||
]]></programlisting>
|
||||
@@ -153,21 +163,19 @@ public class Actor {
|
||||
<programlisting language="java"><![CDATA[
|
||||
@NodeEntity
|
||||
public class Group {
|
||||
@GraphTraversal(traversalBuilder = PeopleTraversalBuilder.class,
|
||||
elementClass = Person.class, params = "persons")
|
||||
private Iterable<Person> people;
|
||||
@GraphTraversal(traversalBuilder = PeopleTraversalBuilder.class,
|
||||
elementClass = Person.class, params = "persons")
|
||||
private Iterable<Person> people;
|
||||
|
||||
private static class PeopleTraversalBuilder implements FieldTraversalDescriptionBuilder {
|
||||
@Override
|
||||
public TraversalDescription build(NodeBacked start, Field field, String...params) {
|
||||
return new TraversalDescriptionImpl()
|
||||
.relationships(DynamicRelationshipType.withName(params[0]))
|
||||
.filter(Traversal.returnAllButStartNode());
|
||||
|
||||
}
|
||||
}
|
||||
private static class PeopleTraversalBuilder implements FieldTraversalDescriptionBuilder {
|
||||
@Override
|
||||
public TraversalDescription build(NodeBacked start, Field field, String...params) {
|
||||
return new TraversalDescriptionImpl()
|
||||
.relationships(DynamicRelationshipType.withName(params[0]))
|
||||
.filter(Traversal.returnAllButStartNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user