generified accessors
This commit is contained in:
@@ -1,110 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 11.09.2010
|
||||
*/
|
||||
public abstract class AbstractFieldAccessor implements FieldAccessor {
|
||||
protected final RelationshipType type;
|
||||
protected final Direction direction;
|
||||
protected final Class<? extends NodeBacked> relatedType;
|
||||
protected final EntityInstantiator<NodeBacked, Node> graphEntityInstantiator;
|
||||
|
||||
public AbstractFieldAccessor(Class<? extends NodeBacked> clazz, EntityInstantiator<NodeBacked, Node> graphEntityInstantiator, Direction direction, RelationshipType type) {
|
||||
this.relatedType = clazz;
|
||||
this.graphEntityInstantiator = graphEntityInstantiator;
|
||||
this.direction = direction;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
protected void createSingleRelationship(Node start, Node end) {
|
||||
if (end==null) return;
|
||||
switch(direction) {
|
||||
case OUTGOING : {
|
||||
obtainSingleRelationship(start, end);
|
||||
break;
|
||||
}
|
||||
case INCOMING :
|
||||
obtainSingleRelationship(end, start);
|
||||
break;
|
||||
default : throw new InvalidDataAccessApiUsageException("invalid direction " + direction);
|
||||
}
|
||||
}
|
||||
|
||||
private Relationship obtainSingleRelationship(Node start, Node end) {
|
||||
final Relationship existingRelationship = start.getSingleRelationship(type, direction);
|
||||
if (existingRelationship!=null && existingRelationship.getOtherNode(start).equals(end)) return existingRelationship;
|
||||
return start.createRelationshipTo(end, type);
|
||||
}
|
||||
|
||||
protected Node checkUnderlyingNode(NodeBacked entity) {
|
||||
if (entity==null) throw new IllegalStateException("Entity is null");
|
||||
Node node = entity.getUnderlyingNode();
|
||||
if (node != null) return node;
|
||||
throw new IllegalStateException("Entity must have a backing Node");
|
||||
}
|
||||
|
||||
protected void removeMissingRelationships(Node node, Set<Node> targetNodes) {
|
||||
for ( Relationship relationship : node.getRelationships(type, direction) ) {
|
||||
if (!targetNodes.remove(relationship.getOtherNode(node)))
|
||||
relationship.delete();
|
||||
}
|
||||
}
|
||||
|
||||
protected void createAddedRelationships(Node node, Set<Node> targetNodes) {
|
||||
for (Node targetNode : targetNodes) {
|
||||
createSingleRelationship(node,targetNode);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkNoCircularReference(Node node, Set<Node> targetNodes) {
|
||||
if (targetNodes.contains(node)) throw new InvalidDataAccessApiUsageException("Cannot create a circular reference to "+ targetNodes);
|
||||
}
|
||||
|
||||
protected Set<Node> checkTargetIsSetOfNodebacked(Object newVal) {
|
||||
if (!(newVal instanceof Set)) {
|
||||
throw new IllegalArgumentException("New value must be a Set, was: " + newVal.getClass());
|
||||
}
|
||||
Set<Node> nodes=new HashSet<Node>();
|
||||
for (Object value : (Set<Object>) newVal) {
|
||||
if (!(value instanceof NodeBacked)) {
|
||||
throw new IllegalArgumentException("New value elements must be NodeBacked.");
|
||||
}
|
||||
nodes.add(((NodeBacked)value).getUnderlyingNode());
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
protected ManagedFieldAccessorSet<NodeBacked> createManagedSet(NodeBacked entity, Set<NodeBacked> result) {
|
||||
return new ManagedFieldAccessorSet<NodeBacked>(entity, result, this);
|
||||
}
|
||||
|
||||
protected Set<NodeBacked> createEntitySetFromRelationshipEndNodes(NodeBacked entity) {
|
||||
final Set<Node> nodes = getStatesFromEntity(entity);
|
||||
final Set<NodeBacked> result = new HashSet<NodeBacked>();
|
||||
for (final Node otherNode : nodes) {
|
||||
result.add(graphEntityInstantiator.createEntityFromState(otherNode, relatedType));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Set<Node> getStatesFromEntity(NodeBacked entity) {
|
||||
final Node entityNode = entity.getUnderlyingNode();
|
||||
final Set<Node> result = new HashSet<Node>();
|
||||
for (final Relationship rel : entityNode.getRelationships(type, direction)) {
|
||||
result.add(rel.getOtherNode(entityNode));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 11.09.2010
|
||||
*/
|
||||
public abstract class AbstractRelationshipFieldAccessor<ENTITY,STATE,TARGET,TSTATE> implements FieldAccessor<ENTITY,TARGET> {
|
||||
protected final RelationshipType type;
|
||||
protected final Direction direction;
|
||||
protected final Class<? extends TARGET> relatedType;
|
||||
protected final EntityInstantiator<TARGET, TSTATE> graphEntityInstantiator;
|
||||
|
||||
public AbstractRelationshipFieldAccessor(Class<? extends TARGET> clazz, EntityInstantiator<TARGET, TSTATE> graphEntityInstantiator, Direction direction, RelationshipType type) {
|
||||
this.relatedType = clazz;
|
||||
this.graphEntityInstantiator = graphEntityInstantiator;
|
||||
this.direction = direction;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
protected STATE checkUnderlyingNode(ENTITY entity) {
|
||||
if (entity==null) throw new IllegalStateException("Entity is null");
|
||||
STATE node = getState(entity);
|
||||
if (node != null) return node;
|
||||
throw new IllegalStateException("Entity must have a backing Node");
|
||||
}
|
||||
|
||||
protected void removeMissingRelationships(Node node, Set<Node> targetNodes) {
|
||||
for ( Relationship relationship : node.getRelationships(type, direction) ) {
|
||||
if (!targetNodes.remove(relationship.getOtherNode(node)))
|
||||
relationship.delete();
|
||||
}
|
||||
}
|
||||
|
||||
protected void createAddedRelationships(STATE node, Set<TSTATE> targetNodes) {
|
||||
for (TSTATE targetNode : targetNodes) {
|
||||
createSingleRelationship(node,targetNode);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkNoCircularReference(Node node, Set<STATE> targetNodes) {
|
||||
if (targetNodes.contains(node)) throw new InvalidDataAccessApiUsageException("Cannot create a circular reference to "+ targetNodes);
|
||||
}
|
||||
|
||||
protected Set<STATE> checkTargetIsSetOfNodebacked(Object newVal) {
|
||||
if (!(newVal instanceof Set)) {
|
||||
throw new IllegalArgumentException("New value must be a Set, was: " + newVal.getClass());
|
||||
}
|
||||
Set<STATE> nodes=new HashSet<STATE>();
|
||||
for (Object value : (Set<Object>) newVal) {
|
||||
if (!relatedType.isInstance(value)) {
|
||||
throw new IllegalArgumentException("New value elements must be "+relatedType);
|
||||
}
|
||||
nodes.add(getState((ENTITY)value));
|
||||
}
|
||||
return nodes;
|
||||
}
|
||||
|
||||
protected ManagedFieldAccessorSet<ENTITY,TARGET> createManagedSet(ENTITY entity, Set<TARGET> result) {
|
||||
return new ManagedFieldAccessorSet<ENTITY,TARGET>(entity, result, this);
|
||||
}
|
||||
|
||||
protected Set<TARGET> createEntitySetFromRelationshipEndNodes(ENTITY entity) {
|
||||
final Iterable<TSTATE> nodes = getStatesFromEntity(entity);
|
||||
final Set<TARGET> result = new HashSet<TARGET>();
|
||||
for (final TSTATE otherNode : nodes) {
|
||||
result.add(graphEntityInstantiator.createEntityFromState(otherNode, relatedType));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
protected void createSingleRelationship(STATE start, TSTATE end) {
|
||||
if (end==null) return;
|
||||
switch(direction) {
|
||||
case OUTGOING : {
|
||||
obtainSingleRelationship(start, end);
|
||||
break;
|
||||
}
|
||||
case INCOMING :
|
||||
obtainSingleRelationship((STATE)end, (TSTATE)start);
|
||||
break;
|
||||
default : throw new InvalidDataAccessApiUsageException("invalid direction " + direction);
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Relationship obtainSingleRelationship(STATE start, TSTATE end);
|
||||
|
||||
protected abstract Iterable<TSTATE> getStatesFromEntity(ENTITY entity);
|
||||
|
||||
protected abstract STATE getState(ENTITY entity);
|
||||
}
|
||||
@@ -2,10 +2,10 @@ package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
public interface FieldAccessor {
|
||||
public interface FieldAccessor<ENTITY, TARGET> {
|
||||
|
||||
Object setValue(NodeBacked entity, Object newVal);
|
||||
Object setValue(ENTITY entity, Object newVal);
|
||||
|
||||
Object getValue(NodeBacked entity);
|
||||
Object getValue(ENTITY entity);
|
||||
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ import java.util.Set;
|
||||
* TODO handle all mutating methods
|
||||
* @param <T>
|
||||
*/
|
||||
public class ManagedFieldAccessorSet<T> extends AbstractSet<T> {
|
||||
private final NodeBacked entity;
|
||||
public class ManagedFieldAccessorSet<ENTITY,T> extends AbstractSet<T> {
|
||||
private final ENTITY entity;
|
||||
final Set<T> delegate;
|
||||
private final FieldAccessor fieldAccessor;
|
||||
private final FieldAccessor<ENTITY,T> fieldAccessor;
|
||||
|
||||
public ManagedFieldAccessorSet(final NodeBacked entity, final Object newVal, final FieldAccessor fieldAccessor) {
|
||||
public ManagedFieldAccessorSet(final ENTITY entity, final Object newVal, final FieldAccessor fieldAccessor) {
|
||||
this.entity = entity;
|
||||
this.fieldAccessor = fieldAccessor;
|
||||
delegate = (Set<T>) newVal;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public abstract class NodeToNodesRelationshipFieldAccessor<TARGET> extends AbstractRelationshipFieldAccessor<NodeBacked, Node, TARGET, Node> {
|
||||
public NodeToNodesRelationshipFieldAccessor(Class<? extends TARGET> clazz, EntityInstantiator<TARGET, Node> graphEntityInstantiator, Direction direction, RelationshipType type) {
|
||||
super(clazz, graphEntityInstantiator, direction, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Relationship obtainSingleRelationship(Node start, Node end) {
|
||||
final Relationship existingRelationship = start.getSingleRelationship(type, direction);
|
||||
if (existingRelationship!=null && existingRelationship.getOtherNode(start).equals(end)) return existingRelationship;
|
||||
return start.createRelationshipTo(end, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Node> getStatesFromEntity(NodeBacked entity) {
|
||||
final Node entityNode = getState(entity);
|
||||
final Set<Node> result = new HashSet<Node>();
|
||||
for (final Relationship rel : entityNode.getRelationships(type, direction)) {
|
||||
result.add(rel.getOtherNode(entityNode));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node getState(NodeBacked entity) {
|
||||
return entity.getUnderlyingNode();
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
@@ -11,15 +12,10 @@ import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.api.RelationshipBacked;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
|
||||
public class OneToNRelationshipEntityFieldAccessor extends AbstractFieldAccessor {
|
||||
|
||||
private final Class<? extends RelationshipBacked> elementClass;
|
||||
private final EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator;
|
||||
public class OneToNRelationshipEntityFieldAccessor extends AbstractRelationshipFieldAccessor<NodeBacked, Node, RelationshipBacked,Relationship> {
|
||||
|
||||
public OneToNRelationshipEntityFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends RelationshipBacked> elementClass, final EntityInstantiator<RelationshipBacked, Relationship> relationshipEntityInstantiator) {
|
||||
super(null,null,direction,type);
|
||||
this.elementClass = elementClass;
|
||||
this.relationshipEntityInstantiator = relationshipEntityInstantiator;
|
||||
super(elementClass,relationshipEntityInstantiator,direction,type);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,18 +27,29 @@ public class OneToNRelationshipEntityFieldAccessor extends AbstractFieldAccessor
|
||||
public Object getValue(final NodeBacked entity) {
|
||||
checkUnderlyingNode(entity);
|
||||
final Set<RelationshipBacked> result = createEntitySetFromRelationships(entity);
|
||||
return new ManagedFieldAccessorSet<RelationshipBacked>(entity, result, this);
|
||||
return new ManagedFieldAccessorSet<NodeBacked, RelationshipBacked>(entity, result, this);
|
||||
}
|
||||
|
||||
private Set<RelationshipBacked> createEntitySetFromRelationships(final NodeBacked entity) {
|
||||
final Set<RelationshipBacked> result = new HashSet<RelationshipBacked>();
|
||||
for (final Relationship rel : getStatesFromEntity(entity)) {
|
||||
result.add(relationshipEntityInstantiator.createEntityFromState(rel, elementClass));
|
||||
result.add(graphEntityInstantiator.createEntityFromState(rel, relatedType));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Iterable<Relationship> getStatesFromEntity(NodeBacked entity) {
|
||||
@Override
|
||||
protected Iterable<Relationship> getStatesFromEntity(NodeBacked entity) {
|
||||
return entity.getUnderlyingNode().getRelationships(type, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Relationship obtainSingleRelationship(Node start, Relationship end) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node getState(NodeBacked nodeBacked) {
|
||||
return nodeBacked.getUnderlyingNode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
|
||||
public class OneToNRelationshipFieldAccessor extends AbstractFieldAccessor {
|
||||
public class OneToNRelationshipFieldAccessor extends NodeToNodesRelationshipFieldAccessor<NodeBacked> {
|
||||
|
||||
public OneToNRelationshipFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends NodeBacked> elementClass, final EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
super(elementClass, graphEntityInstantiator, direction, type);
|
||||
|
||||
@@ -4,12 +4,13 @@ import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.api.RelationshipBacked;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class SingleRelationshipFieldAccessor extends AbstractFieldAccessor {
|
||||
public class SingleRelationshipFieldAccessor extends NodeToNodesRelationshipFieldAccessor<NodeBacked> {
|
||||
public SingleRelationshipFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends NodeBacked> clazz, final EntityInstantiator<NodeBacked, Node> graphEntityInstantiator) {
|
||||
super(clazz, graphEntityInstantiator, direction, type);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user