added id and transient-field fieldFor in DelegatingFactory now iterates, start with EntityStateAccessors
This commit is contained in:
@@ -41,27 +41,30 @@ public class ConvertingNodePropertyFieldAccessor extends NodePropertyFieldAccess
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new FieldAccessorFactory<NodeBacked>() {
|
||||
@Autowired
|
||||
ConversionService conversionService;
|
||||
return new ConvertingNodePropertyFieldAccessorFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(final Field field) {
|
||||
return isSerializableField(field) && isDeserializableField(field);
|
||||
}
|
||||
@Configurable
|
||||
private static class ConvertingNodePropertyFieldAccessorFactory implements FieldAccessorFactory<NodeBacked> {
|
||||
@Autowired
|
||||
ConversionService conversionService;
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked,?> forField(final Field field) {
|
||||
return new ConvertingNodePropertyFieldAccessor(field,conversionService);
|
||||
}
|
||||
@Override
|
||||
public boolean accept(final Field field) {
|
||||
return isSerializableField(field) && isDeserializableField(field);
|
||||
}
|
||||
|
||||
private boolean isSerializableField(final Field field) {
|
||||
return !DelegatingFieldAccessorFactory.isRelationshipField(field) && conversionService.canConvert(field.getType(), String.class);
|
||||
}
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked,?> forField(final Field field) {
|
||||
return new ConvertingNodePropertyFieldAccessor(field,conversionService);
|
||||
}
|
||||
|
||||
private boolean isDeserializableField(final Field field) {
|
||||
return !DelegatingFieldAccessorFactory.isRelationshipField(field) && conversionService.canConvert(String.class, field.getType());
|
||||
}
|
||||
};
|
||||
private boolean isSerializableField(final Field field) {
|
||||
return !DelegatingFieldAccessorFactory.isRelationshipField(field) && conversionService.canConvert(field.getType(), String.class);
|
||||
}
|
||||
|
||||
private boolean isDeserializableField(final Field field) {
|
||||
return !DelegatingFieldAccessorFactory.isRelationshipField(field) && conversionService.canConvert(String.class, field.getType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.datastore.graph.api.*;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.DynamicRelationshipType;
|
||||
import org.springframework.datastore.graph.api.*;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
public class DelegatingFieldAccessorFactory<T> implements FieldAccessorFactory<T> {
|
||||
private final GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
@@ -25,6 +22,8 @@ public class DelegatingFieldAccessorFactory<T> implements FieldAccessorFactory<T
|
||||
}
|
||||
|
||||
final Collection<FieldAccessorFactory<?>> fieldAccessorFactories = Arrays.<FieldAccessorFactory<?>>asList(
|
||||
IdFieldAccessor.factory(),
|
||||
TransientFieldAccessor.factory(),
|
||||
NodePropertyFieldAccessor.factory(),
|
||||
ConvertingNodePropertyFieldAccessor.factory(),
|
||||
SingleRelationshipFieldAccessor.factory(),
|
||||
@@ -37,7 +36,7 @@ public class DelegatingFieldAccessorFactory<T> implements FieldAccessorFactory<T
|
||||
);
|
||||
|
||||
public FieldAccessor forField(Field field) {
|
||||
if (Modifier.isTransient(field.getModifiers())) return null;
|
||||
if (field.getName().startsWith("ajc")) return null;
|
||||
for (FieldAccessorFactory<?> fieldAccessorFactory : fieldAccessorFactories) {
|
||||
if (fieldAccessorFactory.accept(field)) {
|
||||
System.out.println("Factory " + fieldAccessorFactory + " used for field: " + field);
|
||||
@@ -48,37 +47,6 @@ public class DelegatingFieldAccessorFactory<T> implements FieldAccessorFactory<T
|
||||
}
|
||||
|
||||
|
||||
private Class<? extends NodeBacked> targetFrom(Field field) {
|
||||
return (Class<? extends NodeBacked>) field.getType();
|
||||
}
|
||||
|
||||
private Class<? extends NodeBacked> targetFrom(GraphEntityRelationship relAnnotation) {
|
||||
return relAnnotation.elementClass();
|
||||
}
|
||||
|
||||
private Direction dirFrom(GraphEntityRelationship relAnnotation) {
|
||||
return relAnnotation.direction().toNeo4jDir();
|
||||
}
|
||||
|
||||
private DynamicRelationshipType typeFrom(Field field) {
|
||||
return DynamicRelationshipType.withName(getNeo4jPropertyName(field));
|
||||
}
|
||||
|
||||
private Class<? extends RelationshipBacked> targetFrom(GraphEntityRelationshipEntity relEntityAnnotation) {
|
||||
return relEntityAnnotation.elementClass();
|
||||
}
|
||||
|
||||
private Direction dirFrom(GraphEntityRelationshipEntity relEntityAnnotation) {
|
||||
return relEntityAnnotation.direction().toNeo4jDir();
|
||||
}
|
||||
private DynamicRelationshipType typeFrom(GraphEntityRelationshipEntity relEntityAnnotation) {
|
||||
return DynamicRelationshipType.withName(relEntityAnnotation.type());
|
||||
}
|
||||
|
||||
private DynamicRelationshipType typeFrom(GraphEntityRelationship relAnnotation) {
|
||||
return DynamicRelationshipType.withName(relAnnotation.type());
|
||||
}
|
||||
|
||||
public static boolean isRelationshipField(Field f) {
|
||||
return isSingleRelationshipField(f)
|
||||
|| isOneToNRelationshipField(f)
|
||||
@@ -124,11 +92,11 @@ public class DelegatingFieldAccessorFactory<T> implements FieldAccessorFactory<T
|
||||
return false;
|
||||
}
|
||||
|
||||
public List<FieldAccessor<T, ?>> listenersFor(Field field) {
|
||||
List<FieldAccessor<T,?>> result=new ArrayList<FieldAccessor<T,?>>();
|
||||
public List<FieldAccessListener<T, ?>> listenersFor(Field field) {
|
||||
List<FieldAccessListener<T,?>> result=new ArrayList<FieldAccessListener<T,?>>();
|
||||
for (FieldAccessorListenerFactory<?> fieldAccessorListenerFactory : fieldAccessorListenerFactories) {
|
||||
if (fieldAccessorListenerFactory.accept(field)) {
|
||||
final FieldAccessor<T, ?> listener = (FieldAccessor<T, ?>) fieldAccessorListenerFactory.forField(field);
|
||||
final FieldAccessListener<T, ?> listener = (FieldAccessListener<T, ?>) fieldAccessorListenerFactory.forField(field);
|
||||
result.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.api.RelationshipBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public class IdFieldAccessor implements FieldAccessor<NodeBacked, Object> {
|
||||
protected final Field field;
|
||||
|
||||
public IdFieldAccessor(final Field field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked nodeBacked) {
|
||||
return nodeBacked.getUnderlyingNode().getId();
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new FieldAccessorFactory<NodeBacked>() {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return isIdField(f);
|
||||
}
|
||||
|
||||
private boolean isIdField(Field field) {
|
||||
if (!field.getName().equals("id")) return false;
|
||||
final Class<?> type = field.getType();
|
||||
return type.equals(Long.class) || type.equals(long.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked,?> forField(final Field field) {
|
||||
return new IdFieldAccessor(field);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public class TransientFieldAccessor implements FieldAccessor<NodeBacked, Object> {
|
||||
protected final Field field;
|
||||
|
||||
public TransientFieldAccessor(final Field field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
return newVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked nodeBacked) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new FieldAccessorFactory<NodeBacked>() {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return Modifier.isTransient(f.getModifiers());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked,?> forField(final Field field) {
|
||||
return new TransientFieldAccessor(field);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import org.aspectj.lang.reflect.FieldSignature;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.traversal.*;
|
||||
import org.neo4j.graphdb.traversal.Traverser;
|
||||
import org.neo4j.helpers.collection.IterableWrapper;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.datastore.graph.api.GraphEntityProperty;
|
||||
@@ -17,10 +16,10 @@ import org.springframework.datastore.graph.api.RelationshipBacked;
|
||||
|
||||
import org.springframework.datastore.graph.api.GraphEntity;
|
||||
import org.springframework.datastore.graph.neo4j.fieldaccess.DelegatingFieldAccessorFactory;
|
||||
import org.springframework.datastore.graph.neo4j.fieldaccess.EntityStateAccessors;
|
||||
import org.springframework.datastore.graph.neo4j.fieldaccess.FieldAccessor;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.persistence.support.AbstractTypeAnnotatingMixinFields;
|
||||
import org.springframework.persistence.support.EntityInstantiator;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
@@ -69,7 +68,9 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
|
||||
private void createAndAssignNode(NodeBacked entity) {
|
||||
try {
|
||||
entity.setUnderlyingNode(graphDatabaseContext.createNode());
|
||||
Node node=graphDatabaseContext.createNode();
|
||||
entity.setUnderlyingNode(node);
|
||||
entity.underlyingState=new EntityStateAccessors<NodeBacked,Node>(node,entity,entity.getClass(),graphDatabaseContext);
|
||||
log.info("User-defined constructor called on class " + entity.getClass() + "; created Node [" + entity.getUnderlyingNode() +"]; " +
|
||||
"Updating metamodel");
|
||||
graphDatabaseContext.postEntityCreation(entity);
|
||||
@@ -80,6 +81,8 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
|
||||
// Introduced field
|
||||
private Node NodeBacked.underlyingNode;
|
||||
private EntityStateAccessors<NodeBacked,Node> NodeBacked.underlyingState;
|
||||
|
||||
private Map<Field,Object> NodeBacked.dirty;
|
||||
|
||||
public void NodeBacked.setUnderlyingNode(Node n) {
|
||||
@@ -127,7 +130,7 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
public Iterable<? extends NodeBacked> NodeBacked.find(final Class<? extends NodeBacked> targetType, TraversalDescription traversalDescription) {
|
||||
if (!hasUnderlyingNode()) throw new IllegalStateException("No node attached to " + this);
|
||||
final Traverser traverser = traversalDescription.traverse(this.getUnderlyingNode());
|
||||
return new Neo4jNodeBacking.NodeBackedNodeIterableWrapper(traverser, targetType);
|
||||
return new NodeBackedNodeIterableWrapper(traverser, targetType, Neo4jNodeBacking.aspectOf().graphDatabaseContext);
|
||||
}
|
||||
/*
|
||||
public Iterable<? extends NodeBacked> NodeBacked.traverse(TraversalDescription traversalDescription) {
|
||||
@@ -179,8 +182,6 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
return getUnderlyingNode().hashCode();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Object getValueFromEntity(Field field, NodeBacked entity) {
|
||||
try {
|
||||
field.setAccessible(true);
|
||||
@@ -386,17 +387,4 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<GraphEn
|
||||
return graphEntityProperty!=null && graphEntityProperty.index();
|
||||
}
|
||||
|
||||
public static class NodeBackedNodeIterableWrapper extends IterableWrapper<NodeBacked, Node> {
|
||||
private final Class<? extends NodeBacked> targetType;
|
||||
|
||||
public NodeBackedNodeIterableWrapper(Traverser traverser, Class<? extends NodeBacked> targetType) {
|
||||
super(traverser.nodes());
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeBacked underlyingObjectToObject(Node node) {
|
||||
return Neo4jNodeBacking.aspectOf().graphDatabaseContext.createEntityFromState(node,targetType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.springframework.datastore.graph.neo4j.spi.node;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.traversal.Traverser;
|
||||
import org.neo4j.helpers.collection.IterableWrapper;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 14.09.2010
|
||||
*/
|
||||
public class NodeBackedNodeIterableWrapper extends IterableWrapper<NodeBacked, Node> {
|
||||
private final Class<? extends NodeBacked> targetType;
|
||||
private final GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
public NodeBackedNodeIterableWrapper(Traverser traverser, Class<? extends NodeBacked> targetType, final GraphDatabaseContext graphDatabaseContext) {
|
||||
super(traverser.nodes());
|
||||
this.targetType = targetType;
|
||||
this.graphDatabaseContext = graphDatabaseContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected NodeBacked underlyingObjectToObject(Node node) {
|
||||
return graphDatabaseContext.createEntityFromState(node, targetType);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user