Intermediate step in refactoring of FieldAccessorFactories.
This commit is contained in:
@@ -1,78 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.api.RelationshipBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
@Configurable
|
||||
public class ConvertingNodePropertyFieldAccessor extends NodePropertyFieldAccessor {
|
||||
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public ConvertingNodePropertyFieldAccessor(final Field field, final ConversionService conversionService) {
|
||||
super(field);
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
super.setValue(nodeBacked, serializePropertyValue(newVal));
|
||||
return newVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object doGetValue(final NodeBacked nodeBacked) {
|
||||
return deserializePropertyValue(super.doGetValue(nodeBacked));
|
||||
}
|
||||
|
||||
private Object serializePropertyValue(final Object newVal) {
|
||||
return conversionService.convert(newVal, String.class);
|
||||
}
|
||||
|
||||
private Object deserializePropertyValue(final Object value) {
|
||||
return conversionService.convert(value, field.getType());
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new ConvertingNodePropertyFieldAccessorFactory();
|
||||
}
|
||||
|
||||
@Configurable
|
||||
private static class ConvertingNodePropertyFieldAccessorFactory implements FieldAccessorFactory<NodeBacked> {
|
||||
@Autowired
|
||||
ConversionService conversionService;
|
||||
|
||||
@Override
|
||||
public boolean accept(final Field field) {
|
||||
return isSerializableField(field) && isDeserializableField(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
return new ConvertingNodePropertyFieldAccessor(field, conversionService);
|
||||
}
|
||||
|
||||
private boolean isSerializableField(final Field field) {
|
||||
return isSimpleValueField(field) && conversionService.canConvert(field.getType(), String.class);
|
||||
}
|
||||
|
||||
private boolean isDeserializableField(final Field field) {
|
||||
return isSimpleValueField(field) && conversionService.canConvert(String.class, field.getType());
|
||||
}
|
||||
|
||||
private boolean isSimpleValueField(final Field field) {
|
||||
final Class<?> type = field.getType();
|
||||
if (Iterable.class.isAssignableFrom(type) || NodeBacked.class.isAssignableFrom(type) || RelationshipBacked.class.isAssignableFrom(type))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.api.RelationshipBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
@Configurable
|
||||
public class ConvertingNodePropertyFieldAccessorFactory implements FieldAccessorFactory<NodeBacked> {
|
||||
@Autowired
|
||||
ConversionService conversionService;
|
||||
|
||||
@Override
|
||||
public boolean accept(final Field field) {
|
||||
return isSerializableField(field) && isDeserializableField(field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
return new ConvertingNodePropertyFieldAccessor(field, conversionService);
|
||||
}
|
||||
|
||||
private boolean isSerializableField(final Field field) {
|
||||
return isSimpleValueField(field) && conversionService.canConvert(field.getType(), String.class);
|
||||
}
|
||||
|
||||
private boolean isDeserializableField(final Field field) {
|
||||
return isSimpleValueField(field) && conversionService.canConvert(String.class, field.getType());
|
||||
}
|
||||
|
||||
private boolean isSimpleValueField(final Field field) {
|
||||
final Class<?> type = field.getType();
|
||||
if (Iterable.class.isAssignableFrom(type) || NodeBacked.class.isAssignableFrom(type) || RelationshipBacked.class.isAssignableFrom(type))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Configurable
|
||||
public static class ConvertingNodePropertyFieldAccessor extends NodePropertyFieldAccessorFactory.NodePropertyFieldAccessor {
|
||||
|
||||
private final ConversionService conversionService;
|
||||
|
||||
public ConvertingNodePropertyFieldAccessor(final Field field, final ConversionService conversionService) {
|
||||
super(field);
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
super.setValue(nodeBacked, serializePropertyValue(newVal));
|
||||
return newVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object doGetValue(final NodeBacked nodeBacked) {
|
||||
return deserializePropertyValue(super.doGetValue(nodeBacked));
|
||||
}
|
||||
|
||||
private Object serializePropertyValue(final Object newVal) {
|
||||
return conversionService.convert(newVal, String.class);
|
||||
}
|
||||
|
||||
private Object deserializePropertyValue(final Object value) {
|
||||
return conversionService.convert(value, field.getType());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -26,18 +26,18 @@ public class DelegatingFieldAccessorFactory<T> implements FieldAccessorFactory<T
|
||||
}
|
||||
|
||||
final Collection<FieldAccessorFactory<?>> fieldAccessorFactories = Arrays.<FieldAccessorFactory<?>>asList(
|
||||
IdFieldAccessor.factory(),
|
||||
TransientFieldAccessor.factory(),
|
||||
NodePropertyFieldAccessor.factory(),
|
||||
ConvertingNodePropertyFieldAccessor.factory(),
|
||||
SingleRelationshipFieldAccessor.factory(),
|
||||
OneToNRelationshipFieldAccessor.factory(),
|
||||
ReadOnlyOneToNRelationshipFieldAccessor.factory(),
|
||||
TraversalFieldAccessor.factory(),
|
||||
OneToNRelationshipEntityFieldAccessor.factory()
|
||||
new IdFieldAccessorFactory(),
|
||||
new TransientFieldAccessorFactory(),
|
||||
new NodePropertyFieldAccessorFactory(),
|
||||
new ConvertingNodePropertyFieldAccessorFactory(),
|
||||
new SingleRelationshipFieldAccessorFactory(),
|
||||
new OneToNRelationshipFieldAccessorFactory(),
|
||||
new ReadOnlyOneToNRelationshipFieldAccessorFactory(),
|
||||
new TraversalFieldAccessorFactory(),
|
||||
new OneToNRelationshipEntityFieldAccessorFactory()
|
||||
);
|
||||
final Collection<FieldAccessorListenerFactory<?>> fieldAccessorListenerFactories = Arrays.<FieldAccessorListenerFactory<?>>asList(
|
||||
IndexingNodePropertyFieldAccessorListener.factory()
|
||||
final Collection<FieldAccessorListenerFactory<?>> fieldAccessorListenerFactories = Arrays.<FieldAccessorListenerFactory<?>>asList(
|
||||
IndexingNodePropertyFieldAccessorListenerFactory.IndexingNodePropertyFieldAccessorListener.factory()
|
||||
);
|
||||
|
||||
public FieldAccessor forField(Field field) {
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
/**
|
||||
* @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 boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
return doReturn(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked nodeBacked) {
|
||||
return doReturn(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,53 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public class IdFieldAccessorFactory implements 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);
|
||||
}
|
||||
|
||||
public static class IdFieldAccessor implements FieldAccessor<NodeBacked, Object> {
|
||||
protected final Field field;
|
||||
|
||||
public IdFieldAccessor(final Field field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
return doReturn(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked nodeBacked) {
|
||||
return doReturn(nodeBacked.getUnderlyingNode().getId());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.index.IndexService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public class IndexingNodePropertyFieldAccessorListener implements FieldAccessListener<NodeBacked, Object> {
|
||||
protected final Field field;
|
||||
private final IndexService indexService;
|
||||
|
||||
public IndexingNodePropertyFieldAccessorListener(final Field field, final IndexService indexService) {
|
||||
this.field = field;
|
||||
this.indexService = indexService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(final NodeBacked nodeBacked, final Object oldVal, final Object newVal) {
|
||||
if (newVal==null) indexService.removeIndex(nodeBacked.getUnderlyingNode(),getPropertyName());
|
||||
else indexService.index(nodeBacked.getUnderlyingNode(), getPropertyName(),newVal);
|
||||
}
|
||||
|
||||
// todo
|
||||
private String getPropertyName() {
|
||||
return DelegatingFieldAccessorFactory.getNeo4jPropertyName(field);
|
||||
}
|
||||
|
||||
public static FieldAccessorListenerFactory<NodeBacked> factory() {
|
||||
return new NodeBackedFieldAccessorListenerFactory();
|
||||
}
|
||||
|
||||
@Configurable
|
||||
private static class NodeBackedFieldAccessorListenerFactory implements FieldAccessorListenerFactory<NodeBacked> {
|
||||
@Autowired
|
||||
IndexService indexService;
|
||||
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return NodePropertyFieldAccessor.factory().accept(f) || ConvertingNodePropertyFieldAccessor.factory().accept(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessListener<NodeBacked,?> forField(final Field field) {
|
||||
return new IndexingNodePropertyFieldAccessorListener(field,indexService);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.index.IndexService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
@Configurable
|
||||
class IndexingNodePropertyFieldAccessorListenerFactory implements FieldAccessorListenerFactory<NodeBacked> {
|
||||
@Autowired
|
||||
IndexService indexService;
|
||||
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return new NodePropertyFieldAccessorFactory().accept(f) || new ConvertingNodePropertyFieldAccessorFactory().accept(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessListener<NodeBacked,?> forField(final Field field) {
|
||||
return new IndexingNodePropertyFieldAccessorListener(field,indexService);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public static class IndexingNodePropertyFieldAccessorListener implements FieldAccessListener<NodeBacked, Object> {
|
||||
protected final Field field;
|
||||
private final IndexService indexService;
|
||||
|
||||
public IndexingNodePropertyFieldAccessorListener(final Field field, final IndexService indexService) {
|
||||
this.field = field;
|
||||
this.indexService = indexService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void valueChanged(final NodeBacked nodeBacked, final Object oldVal, final Object newVal) {
|
||||
if (newVal==null) indexService.removeIndex(nodeBacked.getUnderlyingNode(),getPropertyName());
|
||||
else indexService.index(nodeBacked.getUnderlyingNode(), getPropertyName(),newVal);
|
||||
}
|
||||
|
||||
// todo
|
||||
private String getPropertyName() {
|
||||
return DelegatingFieldAccessorFactory.getNeo4jPropertyName(field);
|
||||
}
|
||||
|
||||
public static FieldAccessorListenerFactory<NodeBacked> factory() {
|
||||
return new IndexingNodePropertyFieldAccessorListenerFactory();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public class NodePropertyFieldAccessor implements FieldAccessor<NodeBacked, Object> {
|
||||
protected final Field field;
|
||||
|
||||
public NodePropertyFieldAccessor(final Field field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
nodeBacked.getUnderlyingNode().setProperty(getPropertyName(),newVal);
|
||||
return newVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object getValue(final NodeBacked nodeBacked) {
|
||||
return doReturn(doGetValue(nodeBacked));
|
||||
}
|
||||
|
||||
protected Object doGetValue(NodeBacked nodeBacked) {
|
||||
return nodeBacked.getUnderlyingNode().getProperty(getPropertyName());
|
||||
}
|
||||
|
||||
private String getPropertyName() {
|
||||
return DelegatingFieldAccessorFactory.getNeo4jPropertyName(field);
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new FieldAccessorFactory<NodeBacked>() {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return isNeo4jPropertyType(f.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked,?> forField(final Field field) {
|
||||
return new NodePropertyFieldAccessor(field);
|
||||
}
|
||||
|
||||
private boolean isNeo4jPropertyType(final Class<?> fieldType) {
|
||||
// todo: add array support
|
||||
return fieldType.isPrimitive()
|
||||
|| (fieldType.isArray() && !fieldType.getComponentType().isArray() && isNeo4jPropertyType(fieldType.getComponentType()))
|
||||
|| fieldType.equals(String.class)
|
||||
|| fieldType.equals(Character.class)
|
||||
|| fieldType.equals(Boolean.class)
|
||||
|| (fieldType.getName().startsWith("java.lang") && Number.class.isAssignableFrom(fieldType));
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public class NodePropertyFieldAccessorFactory implements FieldAccessorFactory<NodeBacked> {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return isNeo4jPropertyType(f.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked,?> forField(final Field field) {
|
||||
return new NodePropertyFieldAccessor(field);
|
||||
}
|
||||
|
||||
private boolean isNeo4jPropertyType(final Class<?> fieldType) {
|
||||
// todo: add array support
|
||||
return fieldType.isPrimitive()
|
||||
|| (fieldType.isArray() && !fieldType.getComponentType().isArray() && isNeo4jPropertyType(fieldType.getComponentType()))
|
||||
|| fieldType.equals(String.class)
|
||||
|| fieldType.equals(Character.class)
|
||||
|| fieldType.equals(Boolean.class)
|
||||
|| (fieldType.getName().startsWith("java.lang") && Number.class.isAssignableFrom(fieldType));
|
||||
}
|
||||
|
||||
public static class NodePropertyFieldAccessor implements FieldAccessor<NodeBacked, Object> {
|
||||
protected final Field field;
|
||||
|
||||
public NodePropertyFieldAccessor(final Field field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
nodeBacked.getUnderlyingNode().setProperty(getPropertyName(),newVal);
|
||||
return newVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Object getValue(final NodeBacked nodeBacked) {
|
||||
return doReturn(doGetValue(nodeBacked));
|
||||
}
|
||||
|
||||
protected Object doGetValue(NodeBacked nodeBacked) {
|
||||
return nodeBacked.getUnderlyingNode().getProperty(getPropertyName());
|
||||
}
|
||||
|
||||
private String getPropertyName() {
|
||||
return DelegatingFieldAccessorFactory.getNeo4jPropertyName(field);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.datastore.graph.api.GraphEntityRelationshipEntity;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.api.RelationshipBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
public class OneToNRelationshipEntityFieldAccessor extends AbstractRelationshipFieldAccessor<NodeBacked, Node, RelationshipBacked, Relationship> {
|
||||
|
||||
public OneToNRelationshipEntityFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends RelationshipBacked> elementClass, final GraphDatabaseContext graphDatabaseContext) {
|
||||
super(elementClass, graphDatabaseContext, direction, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked entity, final Object newVal) {
|
||||
throw new InvalidDataAccessApiUsageException("Cannot set read-only relationship entity field.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked entity) {
|
||||
checkUnderlyingNode(entity);
|
||||
final Set<RelationshipBacked> result = createEntitySetFromRelationships(entity);
|
||||
return doReturn(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)) {
|
||||
final RelationshipBacked relationshipEntity = (RelationshipBacked) graphDatabaseContext.createEntityFromState(rel, (Class<?>) relatedType);
|
||||
result.add(relationshipEntity);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Relationship> getStatesFromEntity(final NodeBacked entity) {
|
||||
return entity.getUnderlyingNode().getRelationships(type, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Relationship obtainSingleRelationship(final Node start, final Relationship end) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node getState(final NodeBacked nodeBacked) {
|
||||
return nodeBacked.getUnderlyingNode();
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new RelationshipEntityFieldAccessorFactory();
|
||||
}
|
||||
|
||||
@Configurable
|
||||
private static class RelationshipEntityFieldAccessorFactory implements FieldAccessorFactory<NodeBacked> {
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return Iterable.class.isAssignableFrom(f.getType()) && hasValidRelationshipAnnotation(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
final GraphEntityRelationshipEntity relEntityAnnotation = getRelationshipAnnotation(field);
|
||||
return new OneToNRelationshipEntityFieldAccessor(typeFrom(relEntityAnnotation), dirFrom(relEntityAnnotation), targetFrom(relEntityAnnotation), graphDatabaseContext);
|
||||
}
|
||||
|
||||
private boolean hasValidRelationshipAnnotation(final Field f) {
|
||||
final GraphEntityRelationshipEntity relEntityAnnotation = getRelationshipAnnotation(f);
|
||||
return relEntityAnnotation != null && !RelationshipBacked.class.equals(relEntityAnnotation.elementClass());
|
||||
}
|
||||
|
||||
private GraphEntityRelationshipEntity getRelationshipAnnotation(final Field field) {
|
||||
return field.getAnnotation(GraphEntityRelationshipEntity.class);
|
||||
}
|
||||
|
||||
private Class<? extends RelationshipBacked> targetFrom(final GraphEntityRelationshipEntity relEntityAnnotation) {
|
||||
return relEntityAnnotation.elementClass();
|
||||
}
|
||||
|
||||
private Direction dirFrom(final GraphEntityRelationshipEntity relEntityAnnotation) {
|
||||
return relEntityAnnotation.direction().toNeo4jDir();
|
||||
}
|
||||
|
||||
private DynamicRelationshipType typeFrom(final GraphEntityRelationshipEntity relEntityAnnotation) {
|
||||
return DynamicRelationshipType.withName(relEntityAnnotation.type());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.datastore.graph.api.GraphEntityRelationshipEntity;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.api.RelationshipBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
@Configurable
|
||||
public class OneToNRelationshipEntityFieldAccessorFactory implements FieldAccessorFactory<NodeBacked> {
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return Iterable.class.isAssignableFrom(f.getType()) && hasValidRelationshipAnnotation(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
final GraphEntityRelationshipEntity relEntityAnnotation = getRelationshipAnnotation(field);
|
||||
return new OneToNRelationshipEntityFieldAccessor(typeFrom(relEntityAnnotation), dirFrom(relEntityAnnotation), targetFrom(relEntityAnnotation), graphDatabaseContext);
|
||||
}
|
||||
|
||||
private boolean hasValidRelationshipAnnotation(final Field f) {
|
||||
final GraphEntityRelationshipEntity relEntityAnnotation = getRelationshipAnnotation(f);
|
||||
return relEntityAnnotation != null && !RelationshipBacked.class.equals(relEntityAnnotation.elementClass());
|
||||
}
|
||||
|
||||
private GraphEntityRelationshipEntity getRelationshipAnnotation(final Field field) {
|
||||
return field.getAnnotation(GraphEntityRelationshipEntity.class);
|
||||
}
|
||||
|
||||
private Class<? extends RelationshipBacked> targetFrom(final GraphEntityRelationshipEntity relEntityAnnotation) {
|
||||
return relEntityAnnotation.elementClass();
|
||||
}
|
||||
|
||||
private Direction dirFrom(final GraphEntityRelationshipEntity relEntityAnnotation) {
|
||||
return relEntityAnnotation.direction().toNeo4jDir();
|
||||
}
|
||||
|
||||
private DynamicRelationshipType typeFrom(final GraphEntityRelationshipEntity relEntityAnnotation) {
|
||||
return DynamicRelationshipType.withName(relEntityAnnotation.type());
|
||||
}
|
||||
|
||||
public static class OneToNRelationshipEntityFieldAccessor extends AbstractRelationshipFieldAccessor<NodeBacked, Node, RelationshipBacked, Relationship> {
|
||||
|
||||
public OneToNRelationshipEntityFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends RelationshipBacked> elementClass, final GraphDatabaseContext graphDatabaseContext) {
|
||||
super(elementClass, graphDatabaseContext, direction, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked entity, final Object newVal) {
|
||||
throw new InvalidDataAccessApiUsageException("Cannot set read-only relationship entity field.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked entity) {
|
||||
checkUnderlyingNode(entity);
|
||||
final Set<RelationshipBacked> result = createEntitySetFromRelationships(entity);
|
||||
return doReturn(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)) {
|
||||
final RelationshipBacked relationshipEntity = (RelationshipBacked) graphDatabaseContext.createEntityFromState(rel, (Class<?>) relatedType);
|
||||
result.add(relationshipEntity);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Iterable<Relationship> getStatesFromEntity(final NodeBacked entity) {
|
||||
return entity.getUnderlyingNode().getRelationships(type, direction);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Relationship obtainSingleRelationship(final Node start, final Relationship end) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node getState(final NodeBacked nodeBacked) {
|
||||
return nodeBacked.getUnderlyingNode();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.datastore.graph.api.GraphEntityRelationship;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
public class OneToNRelationshipFieldAccessor extends NodeToNodesRelationshipFieldAccessor<NodeBacked> {
|
||||
|
||||
public OneToNRelationshipFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends NodeBacked> elementClass, final GraphDatabaseContext graphDatabaseContext) {
|
||||
super(elementClass, graphDatabaseContext, direction, type);
|
||||
}
|
||||
|
||||
public Object setValue(final NodeBacked entity, final Object newVal) {
|
||||
final Node node = checkUnderlyingNode(entity);
|
||||
if (newVal == null) {
|
||||
removeMissingRelationships(node, Collections.<Node>emptySet());
|
||||
return null;
|
||||
}
|
||||
final Set<Node> targetNodes = checkTargetIsSetOfNodebacked(newVal);
|
||||
checkNoCircularReference(node, targetNodes);
|
||||
removeMissingRelationships(node, targetNodes);
|
||||
createAddedRelationships(node, targetNodes);
|
||||
return createManagedSet(entity, (Set<NodeBacked>) newVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked entity) {
|
||||
checkUnderlyingNode(entity);
|
||||
final Set<NodeBacked> result = createEntitySetFromRelationshipEndNodes(entity);
|
||||
return doReturn(createManagedSet(entity, result));
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new RelationshipFieldAccessorFactory() {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return Collection.class.isAssignableFrom(f.getType()) && hasValidRelationshipAnnotation(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
final GraphEntityRelationship relAnnotation = getRelationshipAnnotation(field);
|
||||
return new OneToNRelationshipFieldAccessor(typeFrom(relAnnotation), dirFrom(relAnnotation), targetFrom(relAnnotation), graphDatabaseContext);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.datastore.graph.api.GraphEntityRelationship;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
public class OneToNRelationshipFieldAccessorFactory extends RelationshipFieldAccessorFactory {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return Collection.class.isAssignableFrom(f.getType()) && hasValidRelationshipAnnotation(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
final GraphEntityRelationship relAnnotation = getRelationshipAnnotation(field);
|
||||
return new OneToNRelationshipFieldAccessor(typeFrom(relAnnotation), dirFrom(relAnnotation), targetFrom(relAnnotation), graphDatabaseContext);
|
||||
}
|
||||
|
||||
public static class OneToNRelationshipFieldAccessor extends NodeToNodesRelationshipFieldAccessor<NodeBacked> {
|
||||
|
||||
public OneToNRelationshipFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends NodeBacked> elementClass, final GraphDatabaseContext graphDatabaseContext) {
|
||||
super(elementClass, graphDatabaseContext, direction, type);
|
||||
}
|
||||
|
||||
public Object setValue(final NodeBacked entity, final Object newVal) {
|
||||
final Node node = checkUnderlyingNode(entity);
|
||||
if (newVal == null) {
|
||||
removeMissingRelationships(node, Collections.<Node>emptySet());
|
||||
return null;
|
||||
}
|
||||
final Set<Node> targetNodes = checkTargetIsSetOfNodebacked(newVal);
|
||||
checkNoCircularReference(node, targetNodes);
|
||||
removeMissingRelationships(node, targetNodes);
|
||||
createAddedRelationships(node, targetNodes);
|
||||
return createManagedSet(entity, (Set<NodeBacked>) newVal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked entity) {
|
||||
checkUnderlyingNode(entity);
|
||||
final Set<NodeBacked> result = createEntitySetFromRelationshipEndNodes(entity);
|
||||
return doReturn(createManagedSet(entity, result));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.datastore.graph.api.GraphEntityRelationship;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
public class ReadOnlyOneToNRelationshipFieldAccessor extends OneToNRelationshipFieldAccessor {
|
||||
|
||||
public ReadOnlyOneToNRelationshipFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends NodeBacked> elementClass, final GraphDatabaseContext graphDatabaseContext) {
|
||||
super(type,direction,elementClass, graphDatabaseContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object setValue(final NodeBacked entity, final Object newVal) {
|
||||
throw new InvalidDataAccessApiUsageException("Cannot set read-only relationship entity field.");
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new RelationshipFieldAccessorFactory() {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return Iterable.class.equals(f.getType()) && hasValidRelationshipAnnotation(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
final GraphEntityRelationship relAnnotation = getRelationshipAnnotation(field);
|
||||
return new ReadOnlyOneToNRelationshipFieldAccessor(typeFrom(relAnnotation), dirFrom(relAnnotation), targetFrom(relAnnotation), graphDatabaseContext);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.datastore.graph.api.GraphEntityRelationship;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
public class ReadOnlyOneToNRelationshipFieldAccessorFactory extends RelationshipFieldAccessorFactory {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return Iterable.class.equals(f.getType()) && hasValidRelationshipAnnotation(f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
final GraphEntityRelationship relAnnotation = getRelationshipAnnotation(field);
|
||||
return new ReadOnlyOneToNRelationshipFieldAccessor(typeFrom(relAnnotation), dirFrom(relAnnotation), targetFrom(relAnnotation), graphDatabaseContext);
|
||||
}
|
||||
|
||||
public static class ReadOnlyOneToNRelationshipFieldAccessor extends OneToNRelationshipFieldAccessorFactory.OneToNRelationshipFieldAccessor {
|
||||
|
||||
public ReadOnlyOneToNRelationshipFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends NodeBacked> elementClass, final GraphDatabaseContext graphDatabaseContext) {
|
||||
super(type,direction,elementClass, graphDatabaseContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object setValue(final NodeBacked entity, final Object newVal) {
|
||||
throw new InvalidDataAccessApiUsageException("Cannot set read-only relationship entity field.");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.datastore.graph.api.GraphEntityRelationship;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class SingleRelationshipFieldAccessor extends NodeToNodesRelationshipFieldAccessor<NodeBacked> {
|
||||
public SingleRelationshipFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends NodeBacked> clazz, final GraphDatabaseContext graphDatabaseContext) {
|
||||
super(clazz, graphDatabaseContext, direction, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked entity, final Object newVal) {
|
||||
final Node node=checkUnderlyingNode(entity);
|
||||
if (newVal == null) {
|
||||
removeMissingRelationships(node, Collections.<Node>emptySet());
|
||||
return null;
|
||||
}
|
||||
final Set<Node> target=checkTargetIsSetOfNodebacked(Collections.singleton(newVal));
|
||||
checkNoCircularReference(node,target);
|
||||
removeMissingRelationships(node, target);
|
||||
createAddedRelationships(node,target);
|
||||
return newVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked entity) {
|
||||
checkUnderlyingNode(entity);
|
||||
final Set<NodeBacked> result = createEntitySetFromRelationshipEndNodes(entity);
|
||||
return result.isEmpty() ? null : result.iterator().next();
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new RelationshipFieldAccessorFactory() {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return NodeBacked.class.isAssignableFrom(f.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
final GraphEntityRelationship relAnnotation = getRelationshipAnnotation(field);
|
||||
if (relAnnotation == null)
|
||||
return new SingleRelationshipFieldAccessor(typeFrom(field), Direction.OUTGOING, targetFrom(field), graphDatabaseContext);
|
||||
return new SingleRelationshipFieldAccessor(typeFrom(relAnnotation), dirFrom(relAnnotation), targetFrom(field), graphDatabaseContext);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.RelationshipType;
|
||||
import org.springframework.datastore.graph.api.GraphEntityRelationship;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class SingleRelationshipFieldAccessorFactory extends RelationshipFieldAccessorFactory {
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
return NodeBacked.class.isAssignableFrom(f.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
final GraphEntityRelationship relAnnotation = getRelationshipAnnotation(field);
|
||||
if (relAnnotation == null)
|
||||
return new SingleRelationshipFieldAccessor(typeFrom(field), Direction.OUTGOING, targetFrom(field), graphDatabaseContext);
|
||||
return new SingleRelationshipFieldAccessor(typeFrom(relAnnotation), dirFrom(relAnnotation), targetFrom(field), graphDatabaseContext);
|
||||
}
|
||||
|
||||
public static class SingleRelationshipFieldAccessor extends NodeToNodesRelationshipFieldAccessor<NodeBacked> {
|
||||
public SingleRelationshipFieldAccessor(final RelationshipType type, final Direction direction, final Class<? extends NodeBacked> clazz, final GraphDatabaseContext graphDatabaseContext) {
|
||||
super(clazz, graphDatabaseContext, direction, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked entity, final Object newVal) {
|
||||
final Node node=checkUnderlyingNode(entity);
|
||||
if (newVal == null) {
|
||||
removeMissingRelationships(node, Collections.<Node>emptySet());
|
||||
return null;
|
||||
}
|
||||
final Set<Node> target=checkTargetIsSetOfNodebacked(Collections.singleton(newVal));
|
||||
checkNoCircularReference(node,target);
|
||||
removeMissingRelationships(node, target);
|
||||
createAddedRelationships(node,target);
|
||||
return newVal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked entity) {
|
||||
checkUnderlyingNode(entity);
|
||||
final Set<NodeBacked> result = createEntitySetFromRelationshipEndNodes(entity);
|
||||
return result.isEmpty() ? null : result.iterator().next();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
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 boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class TransientFieldAccessorFactory implements 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public static 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 boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked nodeBacked) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.datastore.graph.api.FieldTraversalDescriptionBuilder;
|
||||
import org.springframework.datastore.graph.api.GraphEntityTraversal;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.finder.Finder;
|
||||
import org.springframework.datastore.graph.neo4j.finder.FinderFactory;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public class TraversalFieldAccessor implements FieldAccessor<NodeBacked, Object> {
|
||||
protected final Field field;
|
||||
private final FinderFactory finderFactory;
|
||||
private final FieldTraversalDescriptionBuilder fieldTraversalDescriptionBuilder;
|
||||
private Class<? extends NodeBacked> target;
|
||||
|
||||
public TraversalFieldAccessor(final Field field, FinderFactory finderFactory) {
|
||||
this.field = field;
|
||||
this.finderFactory = finderFactory;
|
||||
final GraphEntityTraversal graphEntityTraversal = field.getAnnotation(GraphEntityTraversal.class);
|
||||
this.target = graphEntityTraversal.elementClass();
|
||||
this.fieldTraversalDescriptionBuilder = createTraversalDescription(graphEntityTraversal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
throw new InvalidDataAccessApiUsageException("Cannot set readonly traversal description field " + field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked nodeBacked) {
|
||||
final Finder<? extends NodeBacked> finder = finderFactory.getFinderForClass(target);
|
||||
final TraversalDescription traversalDescription = fieldTraversalDescriptionBuilder.build(nodeBacked,field);
|
||||
return doReturn(finder.findAllByTraversal(nodeBacked, traversalDescription));
|
||||
}
|
||||
|
||||
|
||||
private FieldTraversalDescriptionBuilder createTraversalDescription(final GraphEntityTraversal graphEntityTraversal) {
|
||||
try {
|
||||
final Class<? extends FieldTraversalDescriptionBuilder> traversalDescriptionClass = graphEntityTraversal.traversalBuilder();
|
||||
final Constructor<? extends FieldTraversalDescriptionBuilder> constructor = traversalDescriptionClass.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error creating TraversalDescription from " + field,e);
|
||||
}
|
||||
}
|
||||
|
||||
public static FieldAccessorFactory<NodeBacked> factory() {
|
||||
return new TraversalFieldAccessorFactory();
|
||||
}
|
||||
|
||||
@Configurable
|
||||
private static class TraversalFieldAccessorFactory implements FieldAccessorFactory<NodeBacked> {
|
||||
@Autowired
|
||||
private FinderFactory finderFactory;
|
||||
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
final GraphEntityTraversal graphEntityTraversal = f.getAnnotation(GraphEntityTraversal.class);
|
||||
return graphEntityTraversal != null
|
||||
&& graphEntityTraversal.traversalBuilder() != TraversalDescription.class
|
||||
&& f.getType().equals(Iterable.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
return new TraversalFieldAccessor(field, finderFactory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package org.springframework.datastore.graph.neo4j.fieldaccess;
|
||||
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.datastore.graph.api.FieldTraversalDescriptionBuilder;
|
||||
import org.springframework.datastore.graph.api.GraphEntityTraversal;
|
||||
import org.springframework.datastore.graph.api.NodeBacked;
|
||||
import org.springframework.datastore.graph.neo4j.finder.Finder;
|
||||
import org.springframework.datastore.graph.neo4j.finder.FinderFactory;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import static org.springframework.datastore.graph.neo4j.fieldaccess.DoReturn.doReturn;
|
||||
|
||||
@Configurable
|
||||
public class TraversalFieldAccessorFactory implements FieldAccessorFactory<NodeBacked> {
|
||||
@Autowired
|
||||
private FinderFactory finderFactory;
|
||||
|
||||
@Override
|
||||
public boolean accept(final Field f) {
|
||||
final GraphEntityTraversal graphEntityTraversal = f.getAnnotation(GraphEntityTraversal.class);
|
||||
return graphEntityTraversal != null
|
||||
&& graphEntityTraversal.traversalBuilder() != TraversalDescription.class
|
||||
&& f.getType().equals(Iterable.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FieldAccessor<NodeBacked, ?> forField(final Field field) {
|
||||
return new TraversalFieldAccessor(field, finderFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Michael Hunger
|
||||
* @since 12.09.2010
|
||||
*/
|
||||
public static class TraversalFieldAccessor implements FieldAccessor<NodeBacked, Object> {
|
||||
protected final Field field;
|
||||
private final FinderFactory finderFactory;
|
||||
private final FieldTraversalDescriptionBuilder fieldTraversalDescriptionBuilder;
|
||||
private Class<? extends NodeBacked> target;
|
||||
|
||||
public TraversalFieldAccessor(final Field field, FinderFactory finderFactory) {
|
||||
this.field = field;
|
||||
this.finderFactory = finderFactory;
|
||||
final GraphEntityTraversal graphEntityTraversal = field.getAnnotation(GraphEntityTraversal.class);
|
||||
this.target = graphEntityTraversal.elementClass();
|
||||
this.fieldTraversalDescriptionBuilder = createTraversalDescription(graphEntityTraversal);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWriteable(NodeBacked nodeBacked) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object setValue(final NodeBacked nodeBacked, final Object newVal) {
|
||||
throw new InvalidDataAccessApiUsageException("Cannot set readonly traversal description field " + field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(final NodeBacked nodeBacked) {
|
||||
final Finder<? extends NodeBacked> finder = finderFactory.getFinderForClass(target);
|
||||
final TraversalDescription traversalDescription = fieldTraversalDescriptionBuilder.build(nodeBacked,field);
|
||||
return doReturn(finder.findAllByTraversal(nodeBacked, traversalDescription));
|
||||
}
|
||||
|
||||
|
||||
private FieldTraversalDescriptionBuilder createTraversalDescription(final GraphEntityTraversal graphEntityTraversal) {
|
||||
try {
|
||||
final Class<? extends FieldTraversalDescriptionBuilder> traversalDescriptionClass = graphEntityTraversal.traversalBuilder();
|
||||
final Constructor<? extends FieldTraversalDescriptionBuilder> constructor = traversalDescriptionClass.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
return constructor.newInstance();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error creating TraversalDescription from " + field,e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user