API refactoring, method names of the template and some cleanup

This commit is contained in:
Michael Hunger
2011-10-17 02:02:45 +02:00
parent b779521382
commit 3013bebb47
22 changed files with 133 additions and 227 deletions

View File

@@ -160,7 +160,7 @@ public privileged aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMix
}
public <T extends NodeBacked> T NodeBacked.projectTo(Class<T> targetType) {
return (T)graphDatabaseContext().projectTo( this, targetType);
return (T) template().projectTo( this, targetType);
}
public Relationship NodeBacked.relateTo(NodeBacked target, String type) {
@@ -172,7 +172,7 @@ public privileged aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMix
}
public Relationship NodeBacked.getRelationshipTo(NodeBacked target, String type) {
return graphDatabaseContext().getRelationshipTo(this,target,null,type);
return template().getRelationshipBetween(this, target, null, type);
}
public Long NodeBacked.getNodeId() {
@@ -182,51 +182,50 @@ public privileged aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMix
public <T> Iterable<T> NodeBacked.findAllByTraversal(final Class<T> targetType, TraversalDescription traversalDescription) {
if (!hasPersistentState()) throw new IllegalStateException("No node attached to " + this);
final Traverser traverser = traversalDescription.traverse(this.getPersistentState());
return graphDatabaseContext().convertResultsTo(traverser, targetType);
return template().traverse(this.getPersistentState(), traversalDescription).to(targetType);
}
public <T> Iterable<T> NodeBacked.findAllByQuery(final String query, final Class<T> targetType, Map<String,Object> params) {
final CypherQueryExecutor executor = new CypherQueryExecutor(graphDatabaseContext());
final CypherQueryExecutor executor = new CypherQueryExecutor(template());
return executor.query(query, targetType,params);
}
public Iterable<Map<String,Object>> NodeBacked.findAllByQuery(final String query,Map<String,Object> params) {
final CypherQueryExecutor executor = new CypherQueryExecutor(graphDatabaseContext());
final CypherQueryExecutor executor = new CypherQueryExecutor(template());
return executor.queryForList(query,params);
}
public <T> T NodeBacked.findByQuery(final String query, final Class<T> targetType,Map<String,Object> params) {
final CypherQueryExecutor executor = new CypherQueryExecutor(graphDatabaseContext());
final CypherQueryExecutor executor = new CypherQueryExecutor(template());
return executor.queryForObject(query, targetType,params);
}
public <S extends NodeBacked, E extends NodeBacked> Iterable<EntityPath<S,E>> NodeBacked.findAllPathsByTraversal(TraversalDescription traversalDescription) {
if (!hasPersistentState()) throw new IllegalStateException("No node attached to " + this);
final Traverser traverser = traversalDescription.traverse(this.getPersistentState());
return new EntityPathPathIterableWrapper<S, E>(traverser, graphDatabaseContext());
return new EntityPathPathIterableWrapper<S, E>(traverser, template());
}
public <R extends RelationshipBacked, N extends NodeBacked> R NodeBacked.relateTo(N target, Class<R> relationshipClass, String relationshipType) {
return graphDatabaseContext().relateTo(this, target, relationshipClass, relationshipType, false);
return template().createRelationshipBetween(this, target, relationshipClass, relationshipType, false);
}
public <R extends RelationshipBacked, N extends NodeBacked> R NodeBacked.relateTo(N target, Class<R> relationshipClass, String relationshipType, boolean allowDuplicates) {
return graphDatabaseContext().relateTo(this,target,relationshipClass, relationshipType,allowDuplicates);
return template().createRelationshipBetween(this, target, relationshipClass, relationshipType, allowDuplicates);
}
public void NodeBacked.remove() {
graphDatabaseContext().removeNodeEntity(this);
template().removeNodeEntity(this);
}
public void NodeBacked.removeRelationshipTo(NodeBacked target, String relationshipType) {
graphDatabaseContext().removeRelationshipTo(this,target,relationshipType);
template().removeRelationshipBetween(this, target, relationshipType);
}
public <R extends RelationshipBacked> R NodeBacked.getRelationshipTo( NodeBacked target, Class<R> relationshipClass, String type) {
return (R)graphDatabaseContext().getRelationshipTo(this,target,relationshipClass,type);
return (R) template().getRelationshipBetween(this, target, relationshipClass, type);
}
public static Neo4jTemplate graphDatabaseContext() {
public static Neo4jTemplate template() {
return Neo4jNodeBacking.aspectOf().template;
}
@@ -239,7 +238,7 @@ public privileged aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMix
}
public static EntityStateHandler entityStateHandler() {
return graphDatabaseContext().getEntityStateHandler();
return template().getEntityStateHandler();
}
/**

View File

@@ -46,7 +46,7 @@ public class NodeEntityInstantiationTest extends EntityTestBase {
Person p = persistedPerson("Rod", 39);
long nodeId = getNodeId(p);
Node node = neo4jTemplate.getNodeById(nodeId);
Node node = neo4jTemplate.getNode(nodeId);
Person person1 = (Person) neo4jTemplate.createEntityFromStoredType(node);
assertEquals("Rod", person1.getName());
Person person2 = neo4jTemplate.createEntityFromState(node,Person.class);

View File

@@ -232,9 +232,9 @@ public class NodeEntityRelationshipTest extends EntityTestBase {
public void multipleRelationshipsOfSameTypeBetweenTwoEntities() {
Person michael = persistedPerson("Michael", 35);
Person david = persistedPerson("David", 25);
Friendship friendship1 = neo4jTemplate.relateTo(michael,david, Friendship.class, "knows", true);
Friendship friendship1 = neo4jTemplate.createRelationshipBetween(michael, david, Friendship.class, "knows", true);
friendship1.setYears(1);
Friendship friendship2 = neo4jTemplate.relateTo(michael,david, Friendship.class, "knows",true);
Friendship friendship2 = neo4jTemplate.createRelationshipBetween(michael, david, Friendship.class, "knows", true);
friendship2.setYears(2);
assertTrue("two different relationships", friendship1 != friendship2);
assertTrue("two different relationships", getRelationshipState(friendship1) != getRelationshipState(friendship2));

View File

@@ -19,8 +19,8 @@ package org.springframework.data.neo4j.aspects.support;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.Transaction;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.neo4j.aspects.Attribute;
import org.springframework.data.neo4j.aspects.Group;
import org.springframework.data.neo4j.aspects.Person;
@@ -42,7 +42,7 @@ public class NodeEntityTest extends EntityTestBase {
Person p = persistedPerson("Rod", 39);
assertEquals(p.getName(), getNodeState(p).getProperty("name"));
assertEquals(p.getAge(), getNodeState(p).getProperty("age"));
Person found = neo4jTemplate.createEntityFromState(neo4jTemplate.getNodeById(getNodeId(p)), Person.class);
Person found = neo4jTemplate.createEntityFromState(neo4jTemplate.getNode(getNodeId(p)), Person.class);
assertEquals("Rod", getNodeState(found).getProperty("name"));
assertEquals(39, getNodeState(found).getProperty("age"));
}
@@ -79,7 +79,7 @@ public class NodeEntityTest extends EntityTestBase {
assertEquals("developers", getNodeState(group).getProperty("name"));
}
// own transaction handling because of http://wiki.neo4j.org/content/Delete_Semantics
@Test(expected = NotFoundException.class)
@Test(expected = DataRetrievalFailureException.class)
public void testDeleteEntityFromGDC() {
Transaction tx = neo4jTemplate.beginTx();
Person p = persistedPerson("Michael", 35);
@@ -92,10 +92,10 @@ public class NodeEntityTest extends EntityTestBase {
Assert.assertNull("spouse removed " + p.getSpouse(), p.getSpouse());
Person spouseFromIndex = personRepository.findByPropertyValue(Person.NAME_INDEX, "name", "Tina");
Assert.assertNull("spouse not found in index",spouseFromIndex);
Assert.assertNull("node deleted " + id, neo4jTemplate.getNodeById(id));
Assert.assertNull("node deleted " + id, neo4jTemplate.getNode(id));
}
@Test(expected = NotFoundException.class)
@Test(expected = DataRetrievalFailureException.class)
public void testDeleteEntity() {
Transaction tx = neo4jTemplate.beginTx();
Person p = persistedPerson("Michael", 35);
@@ -108,7 +108,7 @@ public class NodeEntityTest extends EntityTestBase {
Assert.assertNull("spouse removed " + p.getSpouse(), p.getSpouse());
Person spouseFromIndex = personRepository.findByPropertyValue(Person.NAME_INDEX, "name", "Tina");
Assert.assertNull("spouse not found in index", spouseFromIndex);
Assert.assertNull("node deleted " + id, neo4jTemplate.getNodeById(id));
Assert.assertNull("node deleted " + id, neo4jTemplate.getNode(id));
}
@Test

View File

@@ -96,7 +96,7 @@ public class RelationshipEntityTest extends EntityTestBase {
Person p = persistedPerson("Michael", 35);
Person p2 = persistedPerson("David", 25);
Friendship f = p.knows(p2);
assertEquals(f, neo4jTemplate.getRelationshipTo(p,p2, Friendship.class, "knows"));
assertEquals(f, neo4jTemplate.getRelationshipBetween(p, p2, Friendship.class, "knows"));
}
@Test

View File

@@ -43,6 +43,7 @@ public class DefaultConverter<T,R> implements ResultConverter<T,R> {
}
protected Object extractValue(Object value) {
if (value instanceof Path) return value; // todo is this sensible to do?
if (value instanceof Map) return extractSingle(((Map)value).values());
if (value instanceof Iterable) return extractSingle((Iterable)value);
return value;
@@ -76,6 +77,7 @@ public class DefaultConverter<T,R> implements ResultConverter<T,R> {
protected Path toPath(Object value, Class<?> sourceType) {
if (Node.class.isAssignableFrom(sourceType)) return new NodePath((Node) value);
if (Relationship.class.isAssignableFrom(sourceType)) return new RelationshipPath((Relationship) value);
if (Path.class.isAssignableFrom(sourceType)) return (Path) value;
return null;
}

View File

@@ -20,7 +20,7 @@ package org.springframework.data.neo4j.conversion;
* @author mh
* @since 28.06.11
*/
public interface Result<T> extends Iterable<T>, EndResult<T> {
public interface Result<T> extends EndResult<T> {
<R> EndResult<R> to(Class<R> type);
<R> EndResult<R> to(Class<R> type, ResultConverter<T, R> resultConverter);
}

View File

@@ -1,68 +0,0 @@
/**
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.conversion;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Path;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.traversal.Traverser;
import org.neo4j.helpers.collection.IterableWrapper;
import org.springframework.data.neo4j.core.EntityPath;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.path.EntityPathPathIterableWrapper;
/**
* @author mh
* @since 16.10.11
*/ // todo integrate in result conversion handling
public class TraverserConverter<T> {
private final Neo4jTemplate ctx;
public TraverserConverter(Neo4jTemplate ctx) {
this.ctx = ctx;
}
@SuppressWarnings("unchecked")
public Iterable<T> convert(Traverser traverser, Class<T> targetType) {
if (Node.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.nodes();
if (Relationship.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.relationships();
if (EntityPath.class.isAssignableFrom(targetType)) return new EntityPathPathIterableWrapper(traverser, ctx);
if (Path.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser;
return (Iterable<T>) convertToGraphEntity(traverser, targetType);
}
private Iterable<?> convertToGraphEntity(Traverser traverser, final Class<?> targetType) {
if (ctx.isNodeEntity(targetType)) {
return new IterableWrapper<Object, Node>(traverser.nodes()) {
@Override
protected Object underlyingObjectToObject(Node node) {
return ctx.createEntityFromState(node, targetType);
}
};
}
if (ctx.isRelationshipEntity(targetType)) {
return new IterableWrapper<Object, Relationship>(traverser.relationships()) {
@Override
protected Object underlyingObjectToObject(Relationship relationship) {
return ctx.createEntityFromState(relationship, targetType);
}
};
}
throw new IllegalStateException("Can't determine valid type for traversal target " + targetType);
}
}

View File

@@ -151,7 +151,7 @@ public class SourceStateTransmitter<S extends PropertyContainer> {
return newNode;
}
try {
return getGraphDatabaseContext().getNodeById(id);
return getGraphDatabaseContext().getNode(id);
} catch (NotFoundException nfe) {
throw new MappingException("Could not find node with id " + id);
}

View File

@@ -25,6 +25,7 @@ import org.neo4j.graphdb.index.IndexHits;
import org.neo4j.graphdb.index.ReadableIndex;
import org.neo4j.helpers.collection.ClosableIterable;
import org.neo4j.helpers.collection.IterableWrapper;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
@@ -93,7 +94,7 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
public T findOne(final Long id) {
try {
return createEntity(getById(id));
} catch (NotFoundException e) {
} catch (DataRetrievalFailureException e) {
return null;
}
}
@@ -248,7 +249,7 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
public boolean exists(Long id) {
try {
return getById(id)!=null;
} catch (NotFoundException e) {
} catch (DataRetrievalFailureException e) {
return false;
}
}

View File

@@ -29,7 +29,7 @@ public class NodeGraphRepository<T> extends AbstractGraphRepository<Node, T> imp
@Override
protected Node getById(long id) {
return template.getNodeById(id);
return template.getNode(id);
}
@Override

View File

@@ -30,7 +30,7 @@ public class RelationshipGraphRepository<T> extends AbstractGraphRepository<Rela
@Override
protected Relationship getById(long id) {
return template.getRelationshipById(id);
return template.getRelationship(id);
}
@Override

View File

@@ -65,4 +65,25 @@ public class EntityRemover {
relationshipTypeRepresentationStrategy.preEntityRemoval(result.relationship);
}
}
public void remove(Object entity) {
if (entity instanceof Node) {
graphDatabase.remove((Node)entity);
return;
}
if (entity instanceof Relationship) {
graphDatabase.remove((Relationship)entity);
return;
}
final Class<?> type = entity.getClass();
if (entityStateHandler.isNodeEntity(type)) {
removeNodeEntity(entity);
return;
}
if (entityStateHandler.isRelationshipEntity(type)) {
removeRelationshipEntity(entity);
return;
}
throw new IllegalArgumentException("@NodeEntity or @RelationshipEntity annotation required on domain class"+type);
}
}

View File

@@ -21,7 +21,6 @@ import org.apache.commons.logging.LogFactory;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.graphdb.traversal.Traverser;
import org.neo4j.helpers.collection.ClosableIterable;
import org.springframework.core.convert.ConversionService;
import org.springframework.dao.DataAccessException;
@@ -33,12 +32,9 @@ import org.springframework.data.neo4j.annotation.RelationshipEntity;
import org.springframework.data.neo4j.conversion.QueryResultBuilder;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.conversion.ResultConverter;
import org.springframework.data.neo4j.conversion.TraverserConverter;
import org.springframework.data.neo4j.core.EntityPath;
import org.springframework.data.neo4j.core.GraphDatabase;
import org.springframework.data.neo4j.core.TypeRepresentationStrategy;
import org.springframework.data.neo4j.core.UncategorizedGraphStoreException;
import org.springframework.data.neo4j.fieldaccess.GraphBackedEntityIterableWrapper;
import org.springframework.data.neo4j.mapping.Neo4jEntityPersister;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntityImpl;
@@ -48,7 +44,6 @@ import org.springframework.data.neo4j.repository.RelationshipGraphRepository;
import org.springframework.data.neo4j.support.conversion.EntityResultConverter;
import org.springframework.data.neo4j.support.node.EntityStateFactory;
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
import org.springframework.data.neo4j.support.path.EntityPathPathIterableWrapper;
import org.springframework.data.neo4j.support.query.CypherQueryExecutor;
import org.springframework.data.neo4j.support.query.QueryEngine;
import org.springframework.data.neo4j.support.relationship.RelationshipEntityInstantiator;
@@ -110,7 +105,7 @@ public class Neo4jTemplate implements Neo4jOperations {
}
/**
* @param graphDatabase the neo4j graph database
* @param graphDatabase the neo4j graph database
* @param transactionManager if passed in, will be used to create implicit transactions whenever needed
*/
public Neo4jTemplate(final GraphDatabase graphDatabase, PlatformTransactionManager transactionManager) {
@@ -130,7 +125,7 @@ public class Neo4jTemplate implements Neo4jOperations {
public <T> GraphRepository<T> repositoryFor(Class<T> clazz) {
if (isNodeEntity(clazz)) return new NodeGraphRepository(clazz, this);
if (isRelationshipEntity(clazz)) return new RelationshipGraphRepository(clazz, this);
throw new IllegalArgumentException("Can't create graph repository for non graph entity of type "+clazz);
throw new IllegalArgumentException("Can't create graph repository for non graph entity of type " + clazz);
}
public GraphDatabase getGraphDatabase() {
@@ -156,8 +151,8 @@ public class Neo4jTemplate implements Neo4jOperations {
@SuppressWarnings("unchecked")
public <S extends PropertyContainer, T> Index<S> getIndex(Class<T> type, String indexName, Boolean fullText) {
if (type==null) {
notNull(indexName,"indexName");
if (type == null) {
notNull(indexName, "indexName");
return getIndex(indexName);
}
@@ -172,7 +167,8 @@ public class Neo4jTemplate implements Neo4jOperations {
}
if (persistentEntity.isNodeEntity()) return (Index<S>) createIndex(Node.class, indexName, fullText);
if (persistentEntity.isRelationshipEntity()) return (Index<S>) createIndex(Relationship.class, indexName, fullText);
if (persistentEntity.isRelationshipEntity())
return (Index<S>) createIndex(Relationship.class, indexName, fullText);
throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity");
}
@@ -184,19 +180,20 @@ public class Neo4jTemplate implements Neo4jOperations {
public boolean isNode(Class<? extends PropertyContainer> type) {
if (type.equals(Node.class)) return true;
if (type.equals(Relationship.class)) return false;
throw new IllegalArgumentException("Unknown Graph Primitive, neither Node nor Relationship"+type);
throw new IllegalArgumentException("Unknown Graph Primitive, neither Node nor Relationship" + type);
}
// TODO handle existing indexes
@SuppressWarnings("unchecked")
public <T extends PropertyContainer> Index<T> createIndex(Class<T> type, String indexName, boolean fullText) {
return graphDatabase.createIndex(type,indexName,fullText);
return graphDatabase.createIndex(type, indexName, fullText);
}
}
public <S extends PropertyContainer, T> Index<S> getIndex(Class<T> type) {
return indexProvider.getIndex(type, null);
}
public <S extends PropertyContainer> Index<S> getIndex(String name) {
return indexProvider.getIndex(null, name);
}
@@ -207,7 +204,7 @@ public class Neo4jTemplate implements Neo4jOperations {
@SuppressWarnings("unchecked")
public <S extends PropertyContainer, T> Index<S> getIndex(Class<T> type, String indexName, Boolean fullText) {
return indexProvider.getIndex(type,indexName,fullText);
return indexProvider.getIndex(type, indexName, fullText);
}
/**
@@ -245,7 +242,7 @@ public class Neo4jTemplate implements Neo4jOperations {
// todo depending on type of mapping
@SuppressWarnings("unchecked")
public <S extends PropertyContainer,T> T setPersistentState(T entity, S state) {
public <S extends PropertyContainer, T> T setPersistentState(T entity, S state) {
entityPersister.setPersistentState(entity, state);
return entity;
}
@@ -256,25 +253,9 @@ public class Neo4jTemplate implements Neo4jOperations {
}
public void remove(Object entity) {
if (entity instanceof Node) {
((Node)entity).delete();
return;
}
if (entity instanceof Relationship) {
((Relationship)entity).delete();
return;
}
final Class<?> type = entity.getClass();
if (isNodeEntity(type)) {
entityRemover.removeNodeEntity(entity);
return;
}
if (isRelationshipEntity(type)) {
entityRemover.removeRelationshipEntity(entity);
return;
}
throw new IllegalArgumentException("@NodeEntity or @RelationshipEntity annotation required on domain class"+type);
entityRemover.remove(entity);
}
public void removeNodeEntity(Object entity) {
entityRemover.removeNodeEntity(entity);
}
@@ -292,44 +273,43 @@ public class Neo4jTemplate implements Neo4jOperations {
}
@Override
public Node createNode(final Map<String,Object> properties) {
public Node createNode(final Map<String, Object> properties) {
return graphDatabase.createNode(properties);
}
public <T> T createNode(Class<T> target, Map<String,Object> properties) {
public <T> T createNode(Class<T> target, Map<String, Object> properties) {
final Node node = createNode(properties);
if (isNodeEntity(target)) {
typeRepresentationStrategies.postEntityCreation(node,target);
typeRepresentationStrategies.postEntityCreation(node, target);
}
return convert(node, target);
}
public Result<Node> createNodes(Map<String,Object>...allNodes) {
Collection<Node> result=new ArrayList<Node>(allNodes.length);
for (Map<String, Object> properties : allNodes) {
public Result<Node> createNodes(Map<String, Object> firstNode, Map<String, Object>... otherNodes) {
Collection<Node> result = new ArrayList<Node>(otherNodes.length + 1);
result.add(createNode(firstNode));
for (Map<String, Object> properties : otherNodes) {
result.add(createNode(properties));
}
return convert(result);
}
public <T> Iterable<T> createNodes(Class<T> target, Map<String,Object>...allNodes) {
public <T> Iterable<T> createNodes(Class<T> target, Map<String, Object> firstNode, Map<String, Object>... otherNodes) {
final TypeRepresentationStrategy<Node> nodeTypeRepresentationStrategy = isNodeEntity(target) ? typeRepresentationStrategies.getNodeTypeRepresentationStrategy() : null;
Collection<Node> result=new ArrayList<Node>(allNodes.length);
for (Map<String, Object> properties : allNodes) {
final Node node = createNode(properties);
if (nodeTypeRepresentationStrategy!=null) {
nodeTypeRepresentationStrategy.postEntityCreation(node,target);
}
result.add(node);
Collection<Node> result = new ArrayList<Node>(otherNodes.length + 1);
result.add(createNode(firstNode, target, nodeTypeRepresentationStrategy));
for (Map<String, Object> properties : otherNodes) {
result.add(createNode(properties, target, nodeTypeRepresentationStrategy));
}
return convert(result).to(target);
}
/**
* Delegates to {@link GraphDatabaseService}
*/
public Node getNodeById(final long nodeId) {
return graphDatabase.getNodeById(nodeId);
private <T> Node createNode(Map<String, Object> properties, Class<T> target, TypeRepresentationStrategy<Node> nodeTypeRepresentationStrategy) {
final Node node = createNode(properties);
if (nodeTypeRepresentationStrategy != null) {
nodeTypeRepresentationStrategy.postEntityCreation(node, target);
}
return node;
}
/**
@@ -339,33 +319,26 @@ public class Neo4jTemplate implements Neo4jOperations {
return graphDatabaseService.beginTx();
}
/**
* Delegates to {@link GraphDatabaseService}
*/
public Relationship getRelationshipById(final long id) {
return graphDatabase.getRelationshipById(id);
}
@PostConstruct
public Neo4jTemplate postConstruct() {
this.resultConverter = new EntityResultConverter<Object, Object>(this);
if (this.graphDatabase==null) {
this.graphDatabase=new DelegatingGraphDatabase(graphDatabaseService,resultConverter);
if (this.graphDatabase == null) {
this.graphDatabase = new DelegatingGraphDatabase(graphDatabaseService, resultConverter);
}
this.typeRepresentationStrategies = new TypeRepresentationStrategies(mappingContext, nodeTypeRepresentationStrategy, relationshipTypeRepresentationStrategy);
this.cypherQueryExecutor = new CypherQueryExecutor(this);
final EntityStateHandler entityStateHandler = new EntityStateHandler(mappingContext, graphDatabase);
if (nodeEntityInstantiator==null) {
if (nodeEntityInstantiator == null) {
nodeEntityInstantiator = new NodeEntityInstantiator(entityStateHandler);
}
EntityTools<Node> nodeEntityTools = new EntityTools<Node>(nodeTypeRepresentationStrategy, nodeEntityStateFactory, nodeEntityInstantiator);
if (relationshipEntityInstantiator==null) {
if (relationshipEntityInstantiator == null) {
relationshipEntityInstantiator = new RelationshipEntityInstantiator(entityStateHandler);
}
EntityTools<Relationship> relationshipEntityTools = new EntityTools<Relationship>(relationshipTypeRepresentationStrategy, relationshipEntityStateFactory, relationshipEntityInstantiator);
this.entityPersister = new Neo4jEntityPersister(conversionService, nodeEntityTools, relationshipEntityTools,mappingContext, entityStateHandler);
this.entityPersister = new Neo4jEntityPersister(conversionService, nodeEntityTools, relationshipEntityTools, mappingContext, entityStateHandler);
this.entityRemover = new EntityRemover(this.entityStateHandler, nodeTypeRepresentationStrategy, relationshipTypeRepresentationStrategy, graphDatabase);
this.indexProvider = new IndexProvider(mappingContext,graphDatabase);
this.indexProvider = new IndexProvider(mappingContext, graphDatabase);
return this;
}
@@ -380,7 +353,7 @@ public class Neo4jTemplate implements Neo4jOperations {
@SuppressWarnings("unchecked")
public <T> T save(T entity) {
return (T)entityPersister.persist(entity);
return (T) entityPersister.persist(entity);
}
public boolean isManaged(Object entity) {
@@ -399,34 +372,17 @@ public class Neo4jTemplate implements Neo4jOperations {
return cypherQueryExecutor.queryForObject(statement, targetType, params);
}
// todo have an result converter that is able to handle iterable input and output types
@SuppressWarnings("unchecked")
public <T> Iterable<T> convertResultsTo(Traverser traverser, Class<T> targetType) {
if (Node.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.nodes();
if (Relationship.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.relationships();
if (EntityPath.class.isAssignableFrom(targetType)) return new EntityPathPathIterableWrapper(traverser,this);
if (Path.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser;
if (isNodeEntity(targetType)) {
return GraphBackedEntityIterableWrapper.create(traverser.nodes(), targetType, this);
}
if (isRelationshipEntity(targetType)) {
return GraphBackedEntityIterableWrapper.create(traverser.relationships(), targetType, this);
}
throw new IllegalStateException("Can't determine valid type for traversal target " + targetType);
}
public <R> R getRelationshipTo(Object source, Object target, Class<R> relationshipClass, String type) {
public <R> R getRelationshipBetween(Object source, Object target, Class<R> relationshipClass, String type) {
final Relationship relationship = entityStateHandler.getRelationshipTo(source, target, type);
if (relationship == null) return null;
return entityPersister.createEntityFromState(relationship, relationshipClass);
}
public void removeRelationshipTo(Object start, Object target, String type) {
public void removeRelationshipBetween(Object start, Object target, String type) {
entityRemover.removeRelationshipTo(start, target, type);
}
public <R> R relateTo(Object source, Object target, Class<R> relationshipClass, String relationshipType, boolean allowDuplicates) {
public <R> R createRelationshipBetween(Object source, Object target, Class<R> relationshipClass, String relationshipType, boolean allowDuplicates) {
final RelationshipResult result = entityStateHandler.relateTo(source, target, relationshipType, allowDuplicates);
if (result.type == RelationshipResult.Type.NEW) {
// TODO
@@ -436,7 +392,7 @@ public class Neo4jTemplate implements Neo4jOperations {
}
@Override
public Relationship createRelationship(final Node startNode, final Node endNode, final RelationshipType relationshipType, final Map<String,Object> properties) {
public Relationship createRelationshipBetween(final Node startNode, final Node endNode, final RelationshipType relationshipType, final Map<String, Object> properties) {
notNull(startNode, "startNode", endNode, "endNode", relationshipType, "relationshipType", properties, "properties");
return exec(new GraphCallback<Relationship>() {
@Override
@@ -446,9 +402,6 @@ public class Neo4jTemplate implements Neo4jOperations {
});
}
private final Neo4jExceptionTranslator exceptionTranslator = new Neo4jExceptionTranslator();
private static void notNull(Object... pairs) {
@@ -464,7 +417,7 @@ public class Neo4jTemplate implements Neo4jOperations {
if (ex instanceof RuntimeException) {
return exceptionTranslator.translateExceptionIfPossible((RuntimeException) ex);
}
return new UncategorizedGraphStoreException("Error executing callback",ex);
return new UncategorizedGraphStoreException("Error executing callback", ex);
}
@@ -520,7 +473,7 @@ public class Neo4jTemplate implements Neo4jOperations {
@Override
public <T extends PropertyContainer> T index(final String indexName, final T element, final String field, final Object value) {
notNull(element, "element", field, "field", value, "value",indexName,"indexName");
notNull(element, "element", field, "field", value, "value", indexName, "indexName");
exec(new GraphCallback.WithoutResult() {
@Override
public void doWithGraphWithoutResult(GraphDatabase graph) throws Exception {
@@ -540,27 +493,29 @@ public class Neo4jTemplate implements Neo4jOperations {
@Override
@SuppressWarnings("unchecked")
public <T> Result<T> convert(Iterable<T> iterable) {
return new QueryResultBuilder<T>(iterable, (ResultConverter<T,?>) resultConverter);
return new QueryResultBuilder<T>(iterable, (ResultConverter<T, ?>) resultConverter);
}
@Override
@SuppressWarnings("unchecked")
public <T> T convert(Object value, Class<T> type) {
return (T) resultConverter.convert(value,type);
return (T) resultConverter.convert(value, type);
}
@Override
public QueryEngine queryEngineFor(QueryType type) {
return graphDatabase.queryEngineFor(type,resultConverter);
return graphDatabase.queryEngineFor(type, resultConverter);
}
@Override
@SuppressWarnings("unchecked")
public Result<Map<String, Object>> query(String statement, Map<String, Object> params) {
notNull(statement, "statement");
return queryEngineFor(QueryType.Cypher).query(statement, params);
}
@SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
public Result<Object> execute(String statement, Map<String, Object> params) {
notNull(statement, "statement");
return queryEngineFor(QueryType.Gremlin).query(statement, params);
@@ -568,19 +523,14 @@ public class Neo4jTemplate implements Neo4jOperations {
@Override
public Result<Path> traverse(Object start, TraversalDescription traversal) {
return traverse((Node)getPersistentState(start),traversal);
return traverse((Node) getPersistentState(start), traversal);
}
// TODO result handling !!
@SuppressWarnings("unchecked")
public <T> Iterable<T> findAllByTraversal(Object entity, Class<?> targetType, TraversalDescription traversalDescription) {
final PropertyContainer state = entityPersister.getPersistentState(entity);
if (state instanceof Node) {
final Traverser traverser = traversalDescription.traverse((Node) state);
return new TraverserConverter<T>(this).convert(traverser, (Class<T>) targetType);
}
throw new IllegalStateException("No node attached to " + entity);
return traverse(entity, traversalDescription).to((Class<T>) targetType);
}
@Override
@@ -603,6 +553,7 @@ public class Neo4jTemplate implements Neo4jOperations {
throw translateExceptionIfPossible(e);
}
}
@Override
public <T extends PropertyContainer> Result<T> lookup(final Class<?> indexedType, final Object query) {
notNull(query, "valueOrQueryObject", indexedType, "indexedType");
@@ -613,6 +564,7 @@ public class Neo4jTemplate implements Neo4jOperations {
throw translateExceptionIfPossible(e);
}
}
@Override
public <T extends PropertyContainer> Result<T> lookup(String indexName, Object query) {
notNull(query, "valueOrQueryObject", indexName, "indexName");
@@ -625,9 +577,6 @@ public class Neo4jTemplate implements Neo4jOperations {
}
public void setTransactionManager(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@@ -706,4 +655,3 @@ public class Neo4jTemplate implements Neo4jOperations {
this.graphDatabase = graphDatabase;
}
}

View File

@@ -27,25 +27,25 @@ import org.springframework.data.neo4j.support.path.ConvertingEntityPath;
* @since 28.06.11
*/
public class EntityResultConverter<T,R> extends DefaultConverter<T,R> {
private final Neo4jTemplate ctx;
private final Neo4jTemplate template;
private final ConversionService conversionService;
public EntityResultConverter(Neo4jTemplate ctx) {
this.ctx = ctx;
conversionService = this.ctx.getConversionService();
public EntityResultConverter(Neo4jTemplate template) {
this.template = template;
conversionService = this.template.getConversionService();
}
@SuppressWarnings("unchecked")
@Override
protected Object doConvert(Object value, Class<?> sourceType, Class targetType) {
if (ctx.isNodeEntity(targetType)) {
return ctx.projectTo(toNode(value, sourceType), targetType);
if (template.isNodeEntity(targetType)) {
return template.projectTo(toNode(value, sourceType), targetType);
}
if (ctx.isRelationshipEntity(targetType)) {
return ctx.projectTo(toRelationship(value, sourceType), targetType);
if (template.isRelationshipEntity(targetType)) {
return template.projectTo(toRelationship(value, sourceType), targetType);
}
if (EntityPath.class.isAssignableFrom(targetType)) {
return new ConvertingEntityPath(ctx,toPath(value,sourceType));
return new ConvertingEntityPath(template,toPath(value,sourceType));
}
final Object result = super.doConvert(value, sourceType, targetType);

View File

@@ -48,7 +48,7 @@ public class NodeEntityState extends DefaultEntityState<Node> {
try {
final Object id = getIdFromEntity();
if (id instanceof Number) {
final Node node = template.getNodeById(((Number) id).longValue());
final Node node = template.getNode(((Number) id).longValue());
setPersistentState(node);
if (log.isInfoEnabled())
log.info("Entity reattached " + entity.getClass() + "; used Node [" + getPersistentState() + "];");

View File

@@ -47,7 +47,7 @@ public class RelationshipEntityState extends DefaultEntityState<Relationship> {
try {
final Object id = getIdFromEntity();
if (id instanceof Number) {
final Relationship relationship = template.getRelationshipById(((Number) id).longValue());
final Relationship relationship = template.getRelationship(((Number) id).longValue());
setPersistentState(relationship);
if (log.isInfoEnabled())
log.info("Entity reattached " + entity.getClass() + "; used Relationship [" + state + "];");

View File

@@ -18,7 +18,9 @@ package org.springframework.data.neo4j.template;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.springframework.data.neo4j.annotation.QueryType;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.support.query.QueryEngine;
import java.util.Map;
@@ -78,7 +80,7 @@ public interface Neo4jOperations {
* @param props optional initial properties
* @return the newly created relationship
*/
Relationship createRelationship(Node startNode, Node endNode, RelationshipType type, Map<String,Object> props);
Relationship createRelationshipBetween(Node startNode, Node endNode, RelationshipType type, Map<String, Object> props);
/**
* Indexes the given field and value for the element.
@@ -143,4 +145,6 @@ public interface Neo4jOperations {
* @return the reference node of the underlying graph database
*/
<T> T getReferenceNode(Class<T> target);
QueryEngine queryEngineFor(QueryType type);
}

View File

@@ -165,7 +165,7 @@ public class Neo4jPersistentTestBase {
}
protected Node michaelNode() {
return gdc.getNodeById(michael.getId());
return gdc.getNode(michael.getId());
}
protected Node createNewNode() {
@@ -175,7 +175,7 @@ public class Neo4jPersistentTestBase {
protected Group storeInGraph(Group g) {
final Long id = g.getId();
if (id != null) {
write(g, gdc.getNodeById(id));
write(g, gdc.getNode(id));
} else {
write(g, null);
}
@@ -185,7 +185,7 @@ public class Neo4jPersistentTestBase {
protected Person storeInGraph(Person p) {
final Long id = p.getId();
if (id != null) {
write(p, gdc.getNodeById(id));
write(p, gdc.getNode(id));
} else {
write(p,null);
}
@@ -203,7 +203,7 @@ public class Neo4jPersistentTestBase {
}
protected Node groupNode() {
return gdc.getNodeById(group.getId());
return gdc.getNode(group.getId());
}
protected <T> Set<T> set(T... objs) {
@@ -215,11 +215,11 @@ public class Neo4jPersistentTestBase {
}
protected Node andresNode() {
return gdc.getNodeById(andres.getId());
return gdc.getNode(andres.getId());
}
protected Node emilNode() {
return gdc.getNodeById(emil.getId());
return gdc.getNode(emil.getId());
}
public Person readPerson(Node node) {

View File

@@ -315,7 +315,7 @@ public class GraphDatabaseContextTemplateTest {
@Test
public void shouldCreateRelationshipWithProperty() throws Exception {
Relationship relationship = neo4jTemplate.createRelationship(referenceNode, node1, HAS, map("name", "rel2"));
Relationship relationship = neo4jTemplate.createRelationshipBetween(referenceNode, node1, HAS, map("name", "rel2"));
assertNotNull(relationship);
assertEquals(referenceNode, relationship.getStartNode());
assertEquals(node1, relationship.getEndNode());

View File

@@ -35,7 +35,6 @@ import org.springframework.data.neo4j.support.DelegatingGraphDatabase;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
@@ -319,7 +318,7 @@ public class Neo4jTemplateApiTest {
@Test
public void shouldCreateRelationshipWithProperty() throws Exception {
Relationship relationship = template.createRelationship(referenceNode, node1, HAS,map("name", "rel2"));
Relationship relationship = template.createRelationshipBetween(referenceNode, node1, HAS, map("name", "rel2"));
assertNotNull(relationship);
assertEquals(referenceNode, relationship.getStartNode());
assertEquals(node1,relationship.getEndNode());

View File

@@ -61,7 +61,7 @@ public class SnippetNeo4jTemplateMethodsTest extends DocumentingTestBase {
Node mark = neo.createNode(map("name", "Mark"));
Node thomas = neo.createNode(map("name", "Thomas"));
neo.createRelationship(mark, thomas, WORKS_WITH, map("project", "spring-data"));
neo.createRelationshipBetween(mark, thomas, WORKS_WITH, map("project", "spring-data"));
neo.index("devs", thomas, "name", "Thomas");
// Cypher TODO