diff --git a/spring-data-neo4j-aspects/src/main/aspect/org/springframework/data/neo4j/aspects/support/node/Neo4jNodeBacking.aj b/spring-data-neo4j-aspects/src/main/aspect/org/springframework/data/neo4j/aspects/support/node/Neo4jNodeBacking.aj index 7548e2874..da1ca1f3b 100644 --- a/spring-data-neo4j-aspects/src/main/aspect/org/springframework/data/neo4j/aspects/support/node/Neo4jNodeBacking.aj +++ b/spring-data-neo4j-aspects/src/main/aspect/org/springframework/data/neo4j/aspects/support/node/Neo4jNodeBacking.aj @@ -28,15 +28,7 @@ import org.neo4j.graphdb.Relationship; import org.neo4j.graphdb.traversal.TraversalDescription; import org.neo4j.graphdb.traversal.Traverser; -import org.springframework.data.neo4j.annotation.NodeEntity; -import org.springframework.data.neo4j.annotation.NodeEntity; -import org.springframework.data.neo4j.annotation.RelationshipEntity; -import org.springframework.data.neo4j.annotation.RelatedTo; -import org.springframework.data.neo4j.annotation.GraphProperty; -import org.springframework.data.neo4j.annotation.GraphId; -import org.springframework.data.neo4j.annotation.Query; -import org.springframework.data.neo4j.annotation.RelatedToVia; -import org.springframework.data.neo4j.annotation.GraphTraversal; +import org.springframework.data.neo4j.annotation.*; import org.springframework.data.neo4j.aspects.core.NodeBacked; import org.springframework.data.neo4j.aspects.core.RelationshipBacked; @@ -186,17 +178,17 @@ public privileged aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMix } public Iterable NodeBacked.findAllByQuery(final String query, final Class targetType, Map params) { - final CypherQueryExecutor executor = new CypherQueryExecutor(template()); + final CypherQueryExecutor executor = new CypherQueryExecutor(template().queryEngineFor(QueryType.Cypher)); return executor.query(query, targetType,params); } public Iterable> NodeBacked.findAllByQuery(final String query,Map params) { - final CypherQueryExecutor executor = new CypherQueryExecutor(template()); + final CypherQueryExecutor executor = new CypherQueryExecutor(template().queryEngineFor(QueryType.Cypher)); return executor.queryForList(query,params); } public T NodeBacked.findByQuery(final String query, final Class targetType,Map params) { - final CypherQueryExecutor executor = new CypherQueryExecutor(template()); + final CypherQueryExecutor executor = new CypherQueryExecutor(template().queryEngineFor(QueryType.Cypher)); return executor.queryForObject(query, targetType,params); } diff --git a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTest.java b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTest.java index 6745089fa..c63cdc2a0 100644 --- a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTest.java +++ b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/query/QueryEngineTest.java @@ -92,10 +92,11 @@ public class QueryEngineTest extends EntityTestBase { assertEquals(asList(getNodeState(testTeam.emil)),result); } + @SuppressWarnings("unchecked") @Test public void testQueryListOfTypePerson() throws Exception { final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss"; - final Collection result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter(template))); + final Collection result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter(conversionService, template))); assertEquals(asList(testTeam.emil),result); } @@ -107,7 +108,7 @@ public class QueryEngineTest extends EntityTestBase { @Test public void testQuerySingleOfTypePerson() throws Exception { final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss"; - final Person result = queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter,Person>(template)).single(); + final Person result = queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter,Person>(conversionService, template)).single(); assertEquals(testTeam.emil,result); } diff --git a/spring-data-neo4j-aspects/src/test/resources/org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTest-context.xml b/spring-data-neo4j-aspects/src/test/resources/org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTest-context.xml index c6221387a..281e75cd0 100644 --- a/spring-data-neo4j-aspects/src/test/resources/org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTest-context.xml +++ b/spring-data-neo4j-aspects/src/test/resources/org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTest-context.xml @@ -30,7 +30,9 @@ - + + + @@ -43,12 +45,15 @@ - + + + + diff --git a/spring-data-neo4j-cross-store/src/test/resources/org/springframework/data/neo4j/partial/Neo4jGraphRecommendationTest-context.xml b/spring-data-neo4j-cross-store/src/test/resources/org/springframework/data/neo4j/partial/Neo4jGraphRecommendationTest-context.xml index 375e66e24..1e32acbf6 100644 --- a/spring-data-neo4j-cross-store/src/test/resources/org/springframework/data/neo4j/partial/Neo4jGraphRecommendationTest-context.xml +++ b/spring-data-neo4j-cross-store/src/test/resources/org/springframework/data/neo4j/partial/Neo4jGraphRecommendationTest-context.xml @@ -90,7 +90,7 @@ - + @@ -102,6 +102,10 @@ + + + + diff --git a/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/SpringRestGraphDatabase.java b/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/SpringRestGraphDatabase.java index 6580e204b..36c83267f 100644 --- a/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/SpringRestGraphDatabase.java +++ b/spring-data-neo4j-rest/src/main/java/org/springframework/data/neo4j/rest/SpringRestGraphDatabase.java @@ -38,6 +38,8 @@ import java.util.Map; public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDatabase implements GraphDatabase{ private ConversionService conversionService; + private ResultConverter resultConverter; + public SpringRestGraphDatabase( RestAPI api){ super(api); } @@ -100,8 +102,13 @@ public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDat } private ResultConverter createResultConverter() { - if (conversionService==null) return new DefaultConverter(); - return new ConversionServiceQueryResultConverter(conversionService); + if (resultConverter!=null) return resultConverter; + if (conversionService != null) { + this.resultConverter = new ConversionServiceQueryResultConverter(conversionService); + } else { + this.resultConverter = new DefaultConverter(); + } + return resultConverter; } private static class SpringResultConverter implements org.neo4j.rest.graphdb.util.ResultConverter { @@ -112,6 +119,7 @@ public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDat } @Override + @SuppressWarnings("unchecked") public Object convert(Object value, Class target) { return resultConverter.convert(value,target); } @@ -134,6 +142,12 @@ public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDat relationship.delete(); } + @Override + public void setResultConverter(ResultConverter resultConverter) { + + + } + private void removeFromIndexes(Node node) { final RestIndexManager indexManager = index(); for (String indexName : indexManager.nodeIndexNames()) { diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/ConfigurationCheck.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/ConfigurationCheck.java index 4704e7ad3..c0e59a633 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/ConfigurationCheck.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/ConfigurationCheck.java @@ -18,16 +18,17 @@ package org.springframework.data.neo4j.config; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Transaction; +import org.springframework.beans.factory.BeanCreationException; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextStartedEvent; import org.springframework.data.neo4j.support.Neo4jTemplate; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionStatus; -import javax.annotation.PostConstruct; - /** * Validates correct configuration of Neo4j and Spring, especially transaction-managers */ -public class ConfigurationCheck { +public class ConfigurationCheck implements ApplicationListener { Neo4jTemplate template; PlatformTransactionManager transactionManager; @@ -36,7 +37,12 @@ public class ConfigurationCheck { this.transactionManager = transactionManager; } - @PostConstruct + @Override + public void onApplicationEvent(ContextStartedEvent event) { + checkConfiguration(); + } + + //@PostConstruct private void checkConfiguration() { checkInjection(); checkSpringTransactionManager(); @@ -44,7 +50,9 @@ public class ConfigurationCheck { } private void checkInjection() { - assert template.getGraphDatabaseService()!=null : "graphDatabaseService not correctly configured, please refer to the manual, setup section"; + if (template.getGraphDatabaseService()==null) { + throw new BeanCreationException("graphDatabaseService not correctly configured, please refer to the manual, setup section"); + } } private void checkSpringTransactionManager() { @@ -53,9 +61,7 @@ public class ConfigurationCheck { updateStartTime(); transactionManager.commit(transaction); } catch(Exception e) { - AssertionError error = new AssertionError("transactionManager not correctly configured, please refer to the manual, setup section"); - error.initCause(e); - throw error; + throw new BeanCreationException("transactionManager not correctly configured, please refer to the manual, setup section",e); } } @@ -66,9 +72,7 @@ public class ConfigurationCheck { updateStartTime(); tx.success(); } catch (Exception e) { - AssertionError error = new AssertionError("transactionManager not correctly configured, please refer to the manual, setup section"); - error.initCause(e); - throw error; + throw new BeanCreationException("transactionManager not correctly configured, please refer to the manual, setup section",e); } finally { try { if (tx != null) tx.finish(); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jConfiguration.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jConfiguration.java index f796c7d93..44c102dc6 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jConfiguration.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/config/Neo4jConfiguration.java @@ -37,10 +37,7 @@ import org.springframework.data.neo4j.fieldaccess.Neo4jConversionServiceFactoryB import org.springframework.data.neo4j.fieldaccess.NodeDelegatingFieldAccessorFactory; import org.springframework.data.neo4j.fieldaccess.RelationshipDelegatingFieldAccessorFactory; import org.springframework.data.neo4j.mapping.*; -import org.springframework.data.neo4j.support.DelegatingGraphDatabase; -import org.springframework.data.neo4j.support.EntityInstantiator; -import org.springframework.data.neo4j.support.EntityStateHandler; -import org.springframework.data.neo4j.support.Neo4jTemplate; +import org.springframework.data.neo4j.support.*; import org.springframework.data.neo4j.support.node.NodeEntityInstantiator; import org.springframework.data.neo4j.support.node.NodeEntityStateFactory; import org.springframework.data.neo4j.support.relationship.RelationshipEntityInstantiator; @@ -80,29 +77,34 @@ public abstract class Neo4jConfiguration { } @Bean - public Neo4jTemplate neo4jTemplate() throws Exception { + public MappingInfrastructure mappingInfrastructure() throws Exception { + MappingInfrastructure infrastructure = new MappingInfrastructure(); + infrastructure.setGraphDatabaseService(getGraphDatabaseService()); + infrastructure.setConversionService(conversionService()); + infrastructure.setMappingContext(mappingContext()); + infrastructure.setEntityStateHandler(entityStateHandler()); - Neo4jTemplate neo4jTemplate = new Neo4jTemplate(); - neo4jTemplate.setGraphDatabaseService(getGraphDatabaseService()); - neo4jTemplate.setConversionService(conversionService()); - neo4jTemplate.setMappingContext(mappingContext()); - neo4jTemplate.setEntityStateHandler(entityStateHandler()); + infrastructure.setNodeEntityStateFactory(nodeEntityStateFactory()); + infrastructure.setNodeTypeRepresentationStrategy(nodeTypeRepresentationStrategy()); + infrastructure.setNodeEntityInstantiator(graphEntityInstantiator()); - neo4jTemplate.setNodeEntityStateFactory(nodeEntityStateFactory()); - neo4jTemplate.setNodeTypeRepresentationStrategy(nodeTypeRepresentationStrategy()); - neo4jTemplate.setNodeEntityInstantiator(graphEntityInstantiator()); + infrastructure.setRelationshipEntityStateFactory(relationshipEntityStateFactory()); + infrastructure.setRelationshipTypeRepresentationStrategy(relationshipTypeRepresentationStrategy()); + infrastructure.setRelationshipEntityInstantiator(graphRelationshipInstantiator()); - neo4jTemplate.setRelationshipEntityStateFactory(relationshipEntityStateFactory()); - neo4jTemplate.setRelationshipTypeRepresentationStrategy(relationshipTypeRepresentationStrategy()); - neo4jTemplate.setRelationshipEntityInstantiator(graphRelationshipInstantiator()); - - neo4jTemplate.setTransactionManager(neo4jTransactionManager()); - neo4jTemplate.setGraphDatabase(graphDatabase()); + infrastructure.setTransactionManager(neo4jTransactionManager()); + infrastructure.setGraphDatabase(graphDatabase()); if (validator!=null) { - neo4jTemplate.setValidator(validator); + infrastructure.setValidator(validator); } - return neo4jTemplate; + return infrastructure; + } + @Bean + public Neo4jTemplate neo4jTemplate() throws Exception { + final Neo4jTemplate neo4jTemplate = new Neo4jTemplate(); + neo4jTemplate.setInfrastructure(mappingInfrastructure()); + return neo4jTemplate; } @Bean diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/core/GraphDatabase.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/core/GraphDatabase.java index cdc6f863b..8ee57789f 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/core/GraphDatabase.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/core/GraphDatabase.java @@ -111,4 +111,6 @@ public interface GraphDatabase { void remove(Node node); void remove(Relationship relationship); + + void setResultConverter(ResultConverter resultConverter); } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/EntityPersister.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/EntityPersister.java new file mode 100644 index 000000000..ff18ddb12 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/EntityPersister.java @@ -0,0 +1,31 @@ +/** + * 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.mapping; + +import org.neo4j.graphdb.PropertyContainer; + +/** + * @author mh + * @since 17.10.11 + */ +public interface EntityPersister { + + T projectTo(Object entity, Class targetType); + T createEntityFromState(S state, Class type); + T createEntityFromStoredType(S state); + boolean isNodeEntity(Class targetType); + boolean isRelationshipEntity(Class targetType); +} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersister.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersister.java index 352c7cabb..12c7ae20f 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersister.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersister.java @@ -32,7 +32,7 @@ import java.util.Map; * @author mh * @since 11.10.11 */ -public class Neo4jEntityPersister implements Neo4jEntityConverter { +public class Neo4jEntityPersister implements EntityPersister, Neo4jEntityConverter { Neo4jEntityConverter nodeConverter; Neo4jEntityConverter relationshipConverter; private EntityStateHandler entityStateHandler; diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jMappingContext.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jMappingContext.java index b8f699d87..05825c7ba 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jMappingContext.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/Neo4jMappingContext.java @@ -31,7 +31,7 @@ import java.lang.reflect.Field; /** * Neo4J specific {@link MappingContext} implementation. Simply creates {@link Neo4jPersistentEntityImpl} and * {@link Neo4jPersistentProperty} instances. - * + * * @author Oliver Gierke */ public class Neo4jMappingContext extends AbstractMappingContext, Neo4jPersistentProperty> { @@ -44,21 +44,29 @@ public class Neo4jMappingContext extends AbstractMappingContext(typeInformation); } - throw new MappingException("Type "+type+" is neither a @NodeEntity nor a @RelationshipEntity"); + throw new MappingException("Type " + type + " is neither a @NodeEntity nor a @RelationshipEntity"); } @Override protected Neo4jPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor, - Neo4jPersistentEntityImpl owner, SimpleTypeHolder simpleTypeHolder) { + Neo4jPersistentEntityImpl owner, SimpleTypeHolder simpleTypeHolder) { return new Neo4jPersistentPropertyImpl(field, descriptor, owner, simpleTypeHolder); } public boolean isNodeEntity(Class type) { - return getPersistentEntity(type).isNodeEntity(); + try { + return getPersistentEntity(type).isNodeEntity(); + } catch (MappingException me) { + return false; + } } public boolean isRelationshipEntity(Class type) { - return getPersistentEntity(type).isRelationshipEntity(); + try { + return getPersistentEntity(type).isRelationshipEntity(); + } catch (MappingException me) { + return false; + } } public void setPersistentState(Object entity, PropertyContainer pc) { diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/SourceStateTransmitter.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/SourceStateTransmitter.java index d6a1f1a7a..a5e9c5736 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/SourceStateTransmitter.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/mapping/SourceStateTransmitter.java @@ -15,8 +15,6 @@ */ package org.springframework.data.neo4j.mapping; -import org.neo4j.graphdb.Node; -import org.neo4j.graphdb.NotFoundException; import org.neo4j.graphdb.PropertyContainer; import org.neo4j.graphdb.Transaction; import org.springframework.data.mapping.Association; @@ -44,7 +42,7 @@ public class SourceStateTransmitter { public R copyPropertiesFrom(final BeanWrapper, R> wrapper, S source, Neo4jPersistentEntity persistentEntity) { final R entity = wrapper.getBean(); - final Transaction tx = getGraphDatabaseContext().beginTx(); + final Transaction tx = getTemplate().beginTx(); try { final EntityState entityState = entityStateFactory.getEntityState(entity, false); entityState.setPersistentState(source); @@ -75,7 +73,7 @@ public class SourceStateTransmitter { entityState.setValue(property, value); } - private Neo4jTemplate getGraphDatabaseContext() { + private Neo4jTemplate getTemplate() { return entityStateFactory.getTemplate(); } @@ -116,7 +114,7 @@ public class SourceStateTransmitter { } public void copyPropertiesTo(final BeanWrapper, R> wrapper, S target, Neo4jPersistentEntity persistentEntity) { - final Transaction tx = getGraphDatabaseContext().beginTx(); + final Transaction tx = getTemplate().beginTx(); try { //final Node targetNode = useGetOrCreateNode(node, persistentEntity, wrapper); final EntityState entityState = entityStateFactory.getEntityState(wrapper.getBean(), false); @@ -141,19 +139,4 @@ public class SourceStateTransmitter { } } - private Node useGetOrCreateNode(Node node, Neo4jPersistentEntity persistentEntity, BeanWrapper, Object> wrapper) { - if (node != null) return node; - final Neo4jPersistentProperty idProperty = persistentEntity.getIdProperty(); - final Long id = getProperty(wrapper, idProperty, Long.class, true); - if (id == null) { - final Node newNode = getGraphDatabaseContext().createNode(); - setProperty(wrapper, idProperty, newNode.getId()); - return newNode; - } - try { - return getGraphDatabaseContext().getNode(id); - } catch (NotFoundException nfe) { - throw new MappingException("Could not find node with id " + id); - } - } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java index 145e52141..e00ab4110 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/GraphRepositoryFactory.java @@ -25,14 +25,14 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.mapping.context.MappingContext; import org.springframework.data.neo4j.annotation.Query; +import org.springframework.data.neo4j.annotation.QueryType; import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity; import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty; import org.springframework.data.neo4j.repository.query.DerivedCypherRepositoryQuery; import org.springframework.data.neo4j.support.GenericTypeExtractor; import org.springframework.data.neo4j.support.Neo4jTemplate; -import org.springframework.data.neo4j.support.conversion.EntityResultConverter; import org.springframework.data.neo4j.support.query.CypherQueryExecutor; -import org.springframework.data.neo4j.support.query.GremlinQueryEngine; +import org.springframework.data.neo4j.support.query.QueryEngine; import org.springframework.data.repository.core.EntityInformation; import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryMetadata; @@ -291,7 +291,12 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { public CypherGraphRepositoryQuery(GraphQueryMethod queryMethod, RepositoryMetadata metadata, final Neo4jTemplate template) { super(queryMethod, metadata, template); - queryExecutor = new CypherQueryExecutor(template); + } + + private CypherQueryExecutor getQueryExecutor() { + if (this.queryExecutor!=null) return this.queryExecutor; + this.queryExecutor = new CypherQueryExecutor(getTemplate().queryEngineFor(QueryType.Cypher)); + return this.queryExecutor; } @Override @@ -303,27 +308,34 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { } if (queryMethod.isIterableResult()) { if (compoundType.isAssignableFrom(Map.class)) { - return queryExecutor.queryForList(queryString,params); + return getQueryExecutor().queryForList(queryString, params); } - return queryExecutor.query(queryString, queryMethod.getCompoundType(),params); + return getQueryExecutor().query(queryString, queryMethod.getCompoundType(), params); } - return queryExecutor.queryForObject(queryString, queryMethod.getReturnType(),params); + return getQueryExecutor().queryForObject(queryString, queryMethod.getReturnType(), params); } private Object queryPaged(String queryString, Map params, Pageable pageable) { - final Iterable result = queryExecutor.query(queryString, getQueryMethod().getCompoundType(),params); + final Iterable result = getQueryExecutor().query(queryString, getQueryMethod().getCompoundType(), params); return createPage(result, pageable); } } private static class GremlinGraphRepositoryQuery extends GraphRepositoryQuery { - private GremlinQueryEngine queryExecutor; + private QueryEngine queryEngine; public GremlinGraphRepositoryQuery(GraphQueryMethod queryMethod, RepositoryMetadata metadata, final Neo4jTemplate template) { super(queryMethod, metadata, template); - queryExecutor = new GremlinQueryEngine(template.getGraphDatabaseService(), new EntityResultConverter(template)); } + private QueryEngine getQueryEngine() { + if (this.queryEngine !=null) return queryEngine; + this.queryEngine = getTemplate().queryEngineFor(QueryType.Gremlin); + return this.queryEngine; + } + + + @SuppressWarnings("unchecked") @Override protected Object dispatchQuery(String queryString, Map params, Pageable pageable) { GraphQueryMethod queryMethod = getQueryMethod(); @@ -331,13 +343,13 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { return queryPaged(queryString,params,pageable); } if (queryMethod.isIterableResult()) { - return queryExecutor.query(queryString,params).to(queryMethod.getCompoundType()); + return getQueryEngine().query(queryString, params).to(queryMethod.getCompoundType()); } - return queryExecutor.query(queryString, params).to(queryMethod.getReturnType()).single(); + return getQueryEngine().query(queryString, params).to(queryMethod.getReturnType()).single(); } private Object queryPaged(String queryString, Map params, Pageable pageable) { - final Iterable result = queryExecutor.query(queryString, params).to(getQueryMethod().getCompoundType()); + @SuppressWarnings("unchecked") final Iterable result = getQueryEngine().query(queryString, params).to(getQueryMethod().getCompoundType()); return createPage(result, pageable); } @@ -352,6 +364,10 @@ public class GraphRepositoryFactory extends RepositoryFactorySupport { this.template = template; } + protected Neo4jTemplate getTemplate() { + return template; + } + @Override public Object execute(Object[] parameters) { Map params = queryMethod.resolveParams(parameters, template); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/DerivedCypherRepositoryQuery.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/DerivedCypherRepositoryQuery.java index aa8a1ecc3..25d9573d7 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/DerivedCypherRepositoryQuery.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/repository/query/DerivedCypherRepositoryQuery.java @@ -21,6 +21,7 @@ import java.util.Map; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.neo4j.annotation.QueryType; import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity; import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty; import org.springframework.data.neo4j.repository.GraphRepositoryFactory.GraphQueryMethod; @@ -64,7 +65,7 @@ public class DerivedCypherRepositoryQuery implements RepositoryQuery { this.query = new CypherQueryCreator(tree, context, info.getJavaType()).createQuery(); this.method = method; - this.executor = new CypherQueryExecutor(database); + this.executor = new CypherQueryExecutor(database.queryEngineFor(QueryType.Cypher)); } /* diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java index b3c2324ad..c94c32368 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/DelegatingGraphDatabase.java @@ -27,6 +27,7 @@ import org.neo4j.kernel.AbstractGraphDatabase; import org.neo4j.kernel.Traversal; import org.springframework.core.convert.ConversionService; import org.springframework.data.neo4j.annotation.QueryType; +import org.springframework.data.neo4j.conversion.DefaultConverter; import org.springframework.data.neo4j.conversion.Result; import org.springframework.data.neo4j.conversion.ResultConverter; import org.springframework.data.neo4j.core.GraphDatabase; @@ -66,6 +67,11 @@ public class DelegatingGraphDatabase implements GraphDatabase { this.conversionService = conversionService; } + @Override + public void setResultConverter(ResultConverter resultConverter) { + this.resultConverter = resultConverter; + } + @Override public Node getNodeById(long id) { return delegate.getNodeById(id); @@ -217,8 +223,10 @@ public class DelegatingGraphDatabase implements GraphDatabase { if (resultConverter!=null) return resultConverter; if (conversionService != null) { this.resultConverter = new ConversionServiceQueryResultConverter(conversionService); + } else { + this.resultConverter = new DefaultConverter(); } - return null; + return resultConverter; } public void shutdown() { diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/IndexProvider.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/IndexProvider.java new file mode 100644 index 000000000..2d42c5dc7 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/IndexProvider.java @@ -0,0 +1,89 @@ +/** + * 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.support; + +import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.PropertyContainer; +import org.neo4j.graphdb.Relationship; +import org.neo4j.graphdb.index.Index; +import org.springframework.data.neo4j.annotation.Indexed; +import org.springframework.data.neo4j.core.GraphDatabase; +import org.springframework.data.neo4j.mapping.Neo4jMappingContext; +import org.springframework.data.neo4j.mapping.Neo4jPersistentEntityImpl; + +import static org.springframework.data.neo4j.support.ParameterCheck.notNull; + +/** + * @author mh + * @since 17.10.11 + */ +class IndexProvider { + private Neo4jMappingContext mappingContext; + private final GraphDatabase graphDatabase; + + IndexProvider(Neo4jMappingContext mappingContext, GraphDatabase graphDatabase) { + this.mappingContext = mappingContext; + this.graphDatabase = graphDatabase; + } + + public Index getIndex(Class type) { + return getIndex(type, null); + } + + public Index getIndex(Class type, String indexName) { + return getIndex(type, indexName, null); + } + + @SuppressWarnings("unchecked") + public Index getIndex(Class type, String indexName, Boolean fullText) { + if (type == null) { + notNull(indexName, "indexName"); + return getIndex(indexName); + } + + final Neo4jPersistentEntityImpl persistentEntity = mappingContext.getPersistentEntity(type); + if (indexName == null) indexName = Indexed.Name.get(type); + final boolean useExistingIndex = fullText == null; + + if (useExistingIndex) { + if (persistentEntity.isNodeEntity()) return (Index) graphDatabase.getIndex(indexName); + if (persistentEntity.isRelationshipEntity()) return (Index) graphDatabase.getIndex(indexName); + throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity"); + } + + if (persistentEntity.isNodeEntity()) return (Index) createIndex(Node.class, indexName, fullText); + if (persistentEntity.isRelationshipEntity()) + return (Index) createIndex(Relationship.class, indexName, fullText); + throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity"); + } + + @SuppressWarnings("unchecked") + public Index getIndex(String indexName) { + return graphDatabase.getIndex(indexName); + } + + public boolean isNode(Class 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); + } + + // TODO handle existing indexes + @SuppressWarnings("unchecked") + public Index createIndex(Class type, String indexName, boolean fullText) { + return graphDatabase.createIndex(type, indexName, fullText); + } +} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/MappingInfrastructure.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/MappingInfrastructure.java new file mode 100644 index 000000000..cd2c17be6 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/MappingInfrastructure.java @@ -0,0 +1,216 @@ +/** + * 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.support; + +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.Relationship; +import org.springframework.core.convert.ConversionService; +import org.springframework.data.neo4j.annotation.QueryType; +import org.springframework.data.neo4j.conversion.ResultConverter; +import org.springframework.data.neo4j.core.GraphDatabase; +import org.springframework.data.neo4j.core.TypeRepresentationStrategy; +import org.springframework.data.neo4j.mapping.Neo4jEntityPersister; +import org.springframework.data.neo4j.mapping.Neo4jMappingContext; +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.query.CypherQueryExecutor; +import org.springframework.data.neo4j.support.relationship.RelationshipEntityInstantiator; +import org.springframework.data.neo4j.support.typerepresentation.NoopNodeTypeRepresentationStrategy; +import org.springframework.data.neo4j.support.typerepresentation.NoopRelationshipTypeRepresentationStrategy; +import org.springframework.transaction.PlatformTransactionManager; + +import javax.validation.Validator; + +/** + * @author mh + * @since 17.10.11 + */ +public class MappingInfrastructure { + private ConversionService conversionService; + private Validator validator; + private TypeRepresentationStrategy nodeTypeRepresentationStrategy; + + private TypeRepresentationStrategy relationshipTypeRepresentationStrategy; + + private Neo4jMappingContext mappingContext; + private CypherQueryExecutor cypherQueryExecutor; + private EntityStateHandler entityStateHandler; + private Neo4jEntityPersister entityPersister; + private EntityStateFactory nodeEntityStateFactory; + private EntityStateFactory relationshipEntityStateFactory; + private EntityRemover entityRemover; + private TypeRepresentationStrategies typeRepresentationStrategies; + private EntityInstantiator relationshipEntityInstantiator; + private EntityInstantiator nodeEntityInstantiator; + private PlatformTransactionManager transactionManager; + private ResultConverter resultConverter; + private IndexProvider indexProvider; + private GraphDatabaseService graphDatabaseService; + private GraphDatabase graphDatabase; + + public MappingInfrastructure(GraphDatabase graphDatabase, PlatformTransactionManager transactionManager) { + this.graphDatabase = graphDatabase; + this.transactionManager = transactionManager; + } + + public MappingInfrastructure() { + } + + // @PostConstruct // TODO + public void postConstruct() { + if (this.mappingContext == null) this.mappingContext = new Neo4jMappingContext(); + if (this.graphDatabase == null) { + this.graphDatabase = new DelegatingGraphDatabase(graphDatabaseService); + } + if (nodeEntityInstantiator == null) { + nodeEntityInstantiator = new NodeEntityInstantiator(entityStateHandler); + } + if (relationshipEntityInstantiator == null) { + relationshipEntityInstantiator = new RelationshipEntityInstantiator(entityStateHandler); + } + if (this.nodeTypeRepresentationStrategy == null) + this.nodeTypeRepresentationStrategy = new NoopNodeTypeRepresentationStrategy(nodeEntityInstantiator); + if (this.relationshipTypeRepresentationStrategy == null) + this.relationshipTypeRepresentationStrategy = new NoopRelationshipTypeRepresentationStrategy(relationshipEntityInstantiator); + this.typeRepresentationStrategies = new TypeRepresentationStrategies(mappingContext, nodeTypeRepresentationStrategy, relationshipTypeRepresentationStrategy); + + final EntityStateHandler entityStateHandler = new EntityStateHandler(mappingContext, graphDatabase); + EntityTools nodeEntityTools = new EntityTools(nodeTypeRepresentationStrategy, nodeEntityStateFactory, nodeEntityInstantiator); + EntityTools relationshipEntityTools = new EntityTools(relationshipTypeRepresentationStrategy, relationshipEntityStateFactory, relationshipEntityInstantiator); + this.entityPersister = new Neo4jEntityPersister(conversionService, nodeEntityTools, relationshipEntityTools, mappingContext, entityStateHandler); + this.entityRemover = new EntityRemover(this.entityStateHandler, nodeTypeRepresentationStrategy, relationshipTypeRepresentationStrategy, graphDatabase); + this.indexProvider = new IndexProvider(mappingContext, graphDatabase); + if (this.resultConverter==null) { + this.resultConverter = new EntityResultConverter(conversionService,entityPersister); + } + this.graphDatabase.setResultConverter(resultConverter); + this.cypherQueryExecutor = new CypherQueryExecutor(graphDatabase.queryEngineFor(QueryType.Cypher, resultConverter)); + } + + + public void setTransactionManager(PlatformTransactionManager transactionManager) { + this.transactionManager = transactionManager; + } + + public void setRelationshipEntityInstantiator(EntityInstantiator relationshipEntityInstantiator) { + this.relationshipEntityInstantiator = relationshipEntityInstantiator; + } + + public void setNodeEntityInstantiator(EntityInstantiator nodeEntityInstantiator) { + this.nodeEntityInstantiator = nodeEntityInstantiator; + } + + + public void setEntityStateHandler(EntityStateHandler entityStateHandler) { + this.entityStateHandler = entityStateHandler; + } + + public void setNodeEntityStateFactory(EntityStateFactory nodeEntityStateFactory) { + this.nodeEntityStateFactory = nodeEntityStateFactory; + } + + public void setRelationshipEntityStateFactory(EntityStateFactory relationshipEntityStateFactory) { + this.relationshipEntityStateFactory = relationshipEntityStateFactory; + } + + public EntityStateHandler getEntityStateHandler() { + return entityStateHandler; + } + + public TypeRepresentationStrategy getNodeTypeRepresentationStrategy() { + return nodeTypeRepresentationStrategy; + } + + public void setNodeTypeRepresentationStrategy(TypeRepresentationStrategy nodeTypeRepresentationStrategy) { + this.nodeTypeRepresentationStrategy = nodeTypeRepresentationStrategy; + } + + public TypeRepresentationStrategy getRelationshipTypeRepresentationStrategy() { + return relationshipTypeRepresentationStrategy; + } + + public void setRelationshipTypeRepresentationStrategy(TypeRepresentationStrategy relationshipTypeRepresentationStrategy) { + this.relationshipTypeRepresentationStrategy = relationshipTypeRepresentationStrategy; + } + + public ConversionService getConversionService() { + return conversionService; + } + + public void setConversionService(ConversionService conversionService) { + this.conversionService = conversionService; + } + + public Validator getValidator() { + return validator; + } + + public void setValidator(Validator validatorFactory) { + this.validator = validatorFactory; + } + + public void setMappingContext(Neo4jMappingContext mappingContext) { + this.mappingContext = mappingContext; + } + + + public GraphDatabaseService getGraphDatabaseService() { + return graphDatabaseService; + } + + public void setGraphDatabaseService(GraphDatabaseService graphDatabaseService) { + this.graphDatabaseService = graphDatabaseService; + } + + public void setGraphDatabase(GraphDatabase graphDatabase) { + this.graphDatabase = graphDatabase; + } + + public GraphDatabase getGraphDatabase() { + return graphDatabase; + } + + public ResultConverter getResultConverter() { + return resultConverter; + } + + public EntityRemover getEntityRemover() { + return entityRemover; + } + + public IndexProvider getIndexProvider() { + return indexProvider; + } + + public Neo4jEntityPersister getEntityPersister() { + return entityPersister; + } + + public PlatformTransactionManager getTransactionManager() { + return transactionManager; + } + + public TypeRepresentationStrategies getTypeRepresentationStrategies() { + return typeRepresentationStrategies; + } + + + public CypherQueryExecutor getCypherQueryExecutor() { + return cypherQueryExecutor; + } +} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jTemplate.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jTemplate.java index 0611951e3..9b6cd84c9 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jTemplate.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/Neo4jTemplate.java @@ -25,7 +25,6 @@ import org.neo4j.helpers.collection.ClosableIterable; import org.springframework.core.convert.ConversionService; import org.springframework.dao.DataAccessException; import org.springframework.dao.InvalidDataAccessApiUsageException; -import org.springframework.data.neo4j.annotation.Indexed; import org.springframework.data.neo4j.annotation.NodeEntity; import org.springframework.data.neo4j.annotation.QueryType; import org.springframework.data.neo4j.annotation.RelationshipEntity; @@ -35,18 +34,11 @@ import org.springframework.data.neo4j.conversion.ResultConverter; 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.mapping.Neo4jEntityPersister; -import org.springframework.data.neo4j.mapping.Neo4jMappingContext; -import org.springframework.data.neo4j.mapping.Neo4jPersistentEntityImpl; +import org.springframework.data.neo4j.mapping.EntityPersister; import org.springframework.data.neo4j.repository.GraphRepository; import org.springframework.data.neo4j.repository.NodeGraphRepository; 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.query.CypherQueryExecutor; import org.springframework.data.neo4j.support.query.QueryEngine; -import org.springframework.data.neo4j.support.relationship.RelationshipEntityInstantiator; import org.springframework.data.neo4j.template.GraphCallback; import org.springframework.data.neo4j.template.Neo4jExceptionTranslator; import org.springframework.data.neo4j.template.Neo4jOperations; @@ -62,6 +54,8 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Map; +import static org.springframework.data.neo4j.support.ParameterCheck.notNull; + /** * Mediator class for the graph related services like the {@link GraphDatabaseService}, the used * {@link org.springframework.data.neo4j.core.TypeRepresentationStrategy}, entity instantiators for nodes and relationships as well as a spring conversion service. @@ -71,37 +65,19 @@ import java.util.Map; * @author Michael Hunger * @since 13.09.2010 */ -public class Neo4jTemplate implements Neo4jOperations { - +/* +TODO This is a merge of GraphDatabaseContext and the previous Neo4jTemplate, so it still contains inconsistencies, if you spot them, please mark them with a TODO + */ +public class Neo4jTemplate implements Neo4jOperations, EntityPersister { private static final Log log = LogFactory.getLog(Neo4jTemplate.class); - private GraphDatabaseService graphDatabaseService; - private ConversionService conversionService; - private Validator validator; - private TypeRepresentationStrategy nodeTypeRepresentationStrategy; - - private TypeRepresentationStrategy relationshipTypeRepresentationStrategy; - - private Neo4jMappingContext mappingContext; - private CypherQueryExecutor cypherQueryExecutor; - private EntityStateHandler entityStateHandler; - private Neo4jEntityPersister entityPersister; - private EntityStateFactory nodeEntityStateFactory; - private EntityStateFactory relationshipEntityStateFactory; - private EntityRemover entityRemover; - private TypeRepresentationStrategies typeRepresentationStrategies; - private EntityInstantiator relationshipEntityInstantiator; - private EntityInstantiator nodeEntityInstantiator; - private PlatformTransactionManager transactionManager; - private GraphDatabase graphDatabase; - private ResultConverter resultConverter; - private IndexProvider indexProvider; - + private MappingInfrastructure infrastructure = new MappingInfrastructure(); /** * default constructor for dependency injection, TODO provide dependencies at creation time */ public Neo4jTemplate() { + this.infrastructure = new MappingInfrastructure(); } /** @@ -110,14 +86,16 @@ public class Neo4jTemplate implements Neo4jOperations { */ public Neo4jTemplate(final GraphDatabase graphDatabase, PlatformTransactionManager transactionManager) { notNull(graphDatabase, "graphDatabase"); - this.transactionManager = transactionManager; - this.graphDatabase = graphDatabase; + this.infrastructure = new MappingInfrastructure(graphDatabase,transactionManager); } public Neo4jTemplate(final GraphDatabase graphDatabase) { notNull(graphDatabase, "graphDatabase"); - transactionManager = null; - this.graphDatabase = graphDatabase; + this.infrastructure = new MappingInfrastructure(graphDatabase,null); + } + + public Neo4jTemplate(MappingInfrastructure infrastructure) { + this.infrastructure = infrastructure; } @@ -128,140 +106,78 @@ public class Neo4jTemplate implements Neo4jOperations { throw new IllegalArgumentException("Can't create graph repository for non graph entity of type " + clazz); } - public GraphDatabase getGraphDatabase() { - return graphDatabase; - } - - static class IndexProvider { - private Neo4jMappingContext mappingContext; - private final GraphDatabase graphDatabase; - - IndexProvider(Neo4jMappingContext mappingContext, GraphDatabase graphDatabase) { - this.mappingContext = mappingContext; - this.graphDatabase = graphDatabase; - } - - public Index getIndex(Class type) { - return getIndex(type, null); - } - - public Index getIndex(Class type, String indexName) { - return getIndex(type, indexName, null); - } - - @SuppressWarnings("unchecked") - public Index getIndex(Class type, String indexName, Boolean fullText) { - if (type == null) { - notNull(indexName, "indexName"); - return getIndex(indexName); - } - - final Neo4jPersistentEntityImpl persistentEntity = mappingContext.getPersistentEntity(type); - if (indexName == null) indexName = Indexed.Name.get(type); - final boolean useExistingIndex = fullText == null; - - if (useExistingIndex) { - if (persistentEntity.isNodeEntity()) return (Index) graphDatabase.getIndex(indexName); - if (persistentEntity.isRelationshipEntity()) return (Index) graphDatabase.getIndex(indexName); - throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity"); - } - - if (persistentEntity.isNodeEntity()) return (Index) createIndex(Node.class, indexName, fullText); - if (persistentEntity.isRelationshipEntity()) - return (Index) createIndex(Relationship.class, indexName, fullText); - throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity"); - } - - @SuppressWarnings("unchecked") - public Index getIndex(String indexName) { - return graphDatabase.getIndex(indexName); - } - - public boolean isNode(Class 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); - } - - // TODO handle existing indexes - @SuppressWarnings("unchecked") - public Index createIndex(Class type, String indexName, boolean fullText) { - return graphDatabase.createIndex(type, indexName, fullText); - } - } public Index getIndex(Class type) { - return indexProvider.getIndex(type, null); + return infrastructure.getIndexProvider().getIndex(type, null); } public Index getIndex(String name) { - return indexProvider.getIndex(null, name); + return infrastructure.getIndexProvider().getIndex(null, name); } public Index getIndex(Class type, String indexName) { - return indexProvider.getIndex(type, indexName, null); + return infrastructure.getIndexProvider().getIndex(type, indexName, null); } @SuppressWarnings("unchecked") public Index getIndex(Class type, String indexName, Boolean fullText) { - return indexProvider.getIndex(type, indexName, fullText); + return infrastructure.getIndexProvider().getIndex(type, indexName, fullText); } /** * @return true if a transaction manager is available and a transaction is currently running */ public boolean transactionIsRunning() { - return graphDatabase.transactionIsRunning(); + return infrastructure.getGraphDatabase().transactionIsRunning(); } public ClosableIterable findAll(final Class entityClass) { - return typeRepresentationStrategies.findAll(entityClass); + return infrastructure.getTypeRepresentationStrategies().findAll(entityClass); } public long count(final Class entityClass) { - return typeRepresentationStrategies.count(entityClass); + return infrastructure.getTypeRepresentationStrategies().count(entityClass); } public T createEntityFromStoredType(S state) { - return entityPersister.createEntityFromStoredType(state); + return infrastructure.getEntityPersister().createEntityFromStoredType(state); } public T createEntityFromState(S state, Class type) { - return entityPersister.createEntityFromState(state, type); + return infrastructure.getEntityPersister().createEntityFromState(state, type); } public T projectTo(Object entity, Class targetType) { - return entityPersister.projectTo(entity, targetType); + return infrastructure.getEntityPersister().projectTo(entity, targetType); } @SuppressWarnings("unchecked") public S getPersistentState(Object entity) { - return entityPersister.getPersistentState(entity); + return infrastructure.getEntityPersister().getPersistentState(entity); } - // todo depending on type of mapping @SuppressWarnings("unchecked") public T setPersistentState(T entity, S state) { - entityPersister.setPersistentState(entity, state); + infrastructure.getEntityPersister().setPersistentState(entity, state); return entity; } @Deprecated() // TODO remove public void postEntityCreation(S node, Class entityClass) { - typeRepresentationStrategies.postEntityCreation(node, entityClass); + infrastructure.getTypeRepresentationStrategies().postEntityCreation(node, entityClass); } public void remove(Object entity) { - entityRemover.remove(entity); + infrastructure.getEntityRemover().remove(entity); } public void removeNodeEntity(Object entity) { - entityRemover.removeNodeEntity(entity); + infrastructure.getEntityRemover().removeNodeEntity(entity); } public void removeRelationshipEntity(Object entity) { - entityRemover.removeRelationshipEntity(entity); + infrastructure.getEntityRemover().removeRelationshipEntity(entity); } /** @@ -269,18 +185,18 @@ public class Neo4jTemplate implements Neo4jOperations { */ @Override public Node createNode() { - return graphDatabase.createNode(null); + return infrastructure.getGraphDatabase().createNode(null); } @Override public Node createNode(final Map properties) { - return graphDatabase.createNode(properties); + return infrastructure.getGraphDatabase().createNode(properties); } public T createNode(Class target, Map properties) { final Node node = createNode(properties); if (isNodeEntity(target)) { - typeRepresentationStrategies.postEntityCreation(node, target); + infrastructure.getTypeRepresentationStrategies().postEntityCreation(node, target); } return convert(node, target); } @@ -295,7 +211,7 @@ public class Neo4jTemplate implements Neo4jOperations { } public Iterable createNodes(Class target, Map firstNode, Map... otherNodes) { - final TypeRepresentationStrategy nodeTypeRepresentationStrategy = isNodeEntity(target) ? typeRepresentationStrategies.getNodeTypeRepresentationStrategy() : null; + final TypeRepresentationStrategy nodeTypeRepresentationStrategy = isNodeEntity(target) ? infrastructure.getTypeRepresentationStrategies().getNodeTypeRepresentationStrategy() : null; Collection result = new ArrayList(otherNodes.length + 1); result.add(createNode(firstNode, target, nodeTypeRepresentationStrategy)); for (Map properties : otherNodes) { @@ -316,29 +232,12 @@ public class Neo4jTemplate implements Neo4jOperations { * Delegates to {@link GraphDatabaseService} */ public Transaction beginTx() { // todo remove ! - return graphDatabaseService.beginTx(); + return infrastructure.getGraphDatabaseService().beginTx(); } @PostConstruct public Neo4jTemplate postConstruct() { - this.resultConverter = new EntityResultConverter(this); - 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) { - nodeEntityInstantiator = new NodeEntityInstantiator(entityStateHandler); - } - EntityTools nodeEntityTools = new EntityTools(nodeTypeRepresentationStrategy, nodeEntityStateFactory, nodeEntityInstantiator); - if (relationshipEntityInstantiator == null) { - relationshipEntityInstantiator = new RelationshipEntityInstantiator(entityStateHandler); - } - EntityTools relationshipEntityTools = new EntityTools(relationshipTypeRepresentationStrategy, relationshipEntityStateFactory, relationshipEntityInstantiator); - this.entityPersister = new Neo4jEntityPersister(conversionService, nodeEntityTools, relationshipEntityTools, mappingContext, entityStateHandler); - this.entityRemover = new EntityRemover(this.entityStateHandler, nodeTypeRepresentationStrategy, relationshipTypeRepresentationStrategy, graphDatabase); - this.indexProvider = new IndexProvider(mappingContext, graphDatabase); + infrastructure.postConstruct(); return this; } @@ -353,42 +252,45 @@ public class Neo4jTemplate implements Neo4jOperations { @SuppressWarnings("unchecked") public T save(T entity) { - return (T) entityPersister.persist(entity); + return (T) infrastructure.getEntityPersister().persist(entity); } public boolean isManaged(Object entity) { - return entityStateHandler.isManaged(entity); + return infrastructure.getEntityStateHandler().isManaged(entity); } public Object query(String statement, Map params, final TypeInformation typeInformation) { final TypeInformation actualType = typeInformation.getActualType(); final Class targetType = actualType.getType(); if (actualType.isMap()) { - return cypherQueryExecutor.queryForList(statement, params); + return infrastructure.getCypherQueryExecutor().queryForList(statement, params); } if (typeInformation.isCollectionLike()) { - return cypherQueryExecutor.query(statement, targetType, params); + return infrastructure.getCypherQueryExecutor().query(statement, targetType, params); } - return cypherQueryExecutor.queryForObject(statement, targetType, params); + return infrastructure.getCypherQueryExecutor().queryForObject(statement, targetType, params); } - public R getRelationshipBetween(Object source, Object target, Class relationshipClass, String type) { - final Relationship relationship = entityStateHandler.getRelationshipTo(source, target, type); + public R getRelationshipBetween(Object start, Object end, Class relationshipEntityClass, String relationshipType) { + notNull(start,"start",end,"end",relationshipEntityClass,"relationshipEntityClass",relationshipType,"relationshipType"); + final Relationship relationship = infrastructure.getEntityStateHandler().getRelationshipTo(start, end, relationshipType); if (relationship == null) return null; - return entityPersister.createEntityFromState(relationship, relationshipClass); + return infrastructure.getEntityPersister().createEntityFromState(relationship, relationshipEntityClass); } - public void removeRelationshipBetween(Object start, Object target, String type) { - entityRemover.removeRelationshipTo(start, target, type); + public void removeRelationshipBetween(Object start, Object end, String type) { + notNull(start,"start",end,"end",type,"relationshipType"); + infrastructure.getEntityRemover().removeRelationshipTo(start, end, type); } - public R createRelationshipBetween(Object source, Object target, Class relationshipClass, String relationshipType, boolean allowDuplicates) { - final RelationshipResult result = entityStateHandler.relateTo(source, target, relationshipType, allowDuplicates); + public R createRelationshipBetween(Object start, Object end, Class relationshipEntityClass, String relationshipType, boolean allowDuplicates) { + notNull(start,"start",end,"end",relationshipEntityClass,"relationshipEntityClass",relationshipType,"relationshipType"); + final RelationshipResult result = infrastructure.getEntityStateHandler().relateTo(start, end, relationshipType, allowDuplicates); if (result.type == RelationshipResult.Type.NEW) { // TODO - postEntityCreation(result.relationship, relationshipClass); + postEntityCreation(result.relationship, relationshipEntityClass); } - return createEntityFromState(result.relationship, relationshipClass); + return createEntityFromState(result.relationship, relationshipEntityClass); } @Override @@ -404,15 +306,6 @@ public class Neo4jTemplate implements Neo4jOperations { private final Neo4jExceptionTranslator exceptionTranslator = new Neo4jExceptionTranslator(); - private static void notNull(Object... pairs) { - assert pairs.length % 2 == 0 : "wrong number of pairs to check"; - for (int i = 0; i < pairs.length; i += 2) { - if (pairs[i] == null) { - throw new InvalidDataAccessApiUsageException("[Assertion failed] - " + pairs[i + 1] + " is required; it must not be null"); - } - } - } - public DataAccessException translateExceptionIfPossible(Exception ex) { if (ex instanceof RuntimeException) { return exceptionTranslator.translateExceptionIfPossible((RuntimeException) ex); @@ -424,7 +317,7 @@ public class Neo4jTemplate implements Neo4jOperations { private T doExecute(final GraphCallback callback) { notNull(callback, "callback"); try { - return callback.doWithGraph(graphDatabase); + return callback.doWithGraph(infrastructure.getGraphDatabase()); } catch (Exception e) { throw translateExceptionIfPossible(e); } @@ -432,9 +325,9 @@ public class Neo4jTemplate implements Neo4jOperations { @Override public T exec(final GraphCallback callback) { - if (transactionManager == null) return doExecute(callback); + if (infrastructure.getTransactionManager() == null) return doExecute(callback); - TransactionTemplate template = new TransactionTemplate(transactionManager); + TransactionTemplate template = new TransactionTemplate(infrastructure.getTransactionManager()); return template.execute(new TransactionCallback() { public T doInTransaction(TransactionStatus status) { return doExecute(callback); @@ -445,7 +338,7 @@ public class Neo4jTemplate implements Neo4jOperations { @Override public T getReferenceNode(Class target) { try { - return convert(graphDatabase.getReferenceNode(), target); + return convert(infrastructure.getGraphDatabase().getReferenceNode(), target); } catch (RuntimeException e) { throw translateExceptionIfPossible(e); } @@ -455,7 +348,7 @@ public class Neo4jTemplate implements Neo4jOperations { public Node getNode(long id) { if (id < 0) throw new InvalidDataAccessApiUsageException("id is negative"); try { - return graphDatabase.getNodeById(id); + return infrastructure.getGraphDatabase().getNodeById(id); } catch (RuntimeException e) { throw translateExceptionIfPossible(e); } @@ -465,7 +358,7 @@ public class Neo4jTemplate implements Neo4jOperations { public Relationship getRelationship(long id) { if (id < 0) throw new InvalidDataAccessApiUsageException("id is negative"); try { - return graphDatabase.getRelationshipById(id); + return infrastructure.getGraphDatabase().getRelationshipById(id); } catch (RuntimeException e) { throw translateExceptionIfPossible(e); } @@ -478,10 +371,10 @@ public class Neo4jTemplate implements Neo4jOperations { @Override public void doWithGraphWithoutResult(GraphDatabase graph) throws Exception { if (element instanceof Relationship) { - Index relationshipIndex = graphDatabase.createIndex(Relationship.class, indexName, false); + Index relationshipIndex = infrastructure.getGraphDatabase().createIndex(Relationship.class, indexName, false); relationshipIndex.add((Relationship) element, field, value); } else if (element instanceof Node) { - graphDatabase.createIndex(Node.class, indexName, false).add((Node) element, field, value); + infrastructure.getGraphDatabase().createIndex(Node.class, indexName, false).add((Node) element, field, value); } else { throw new IllegalArgumentException("Provided element is neither node nor relationship " + element); } @@ -493,18 +386,18 @@ public class Neo4jTemplate implements Neo4jOperations { @Override @SuppressWarnings("unchecked") public Result convert(Iterable iterable) { - return new QueryResultBuilder(iterable, (ResultConverter) resultConverter); + return new QueryResultBuilder(iterable, (ResultConverter) infrastructure.getResultConverter()); } @Override @SuppressWarnings("unchecked") public T convert(Object value, Class type) { - return (T) resultConverter.convert(value, type); + return (T) infrastructure.getResultConverter().convert(value, type); } @Override public QueryEngine queryEngineFor(QueryType type) { - return graphDatabase.queryEngineFor(type, resultConverter); + return infrastructure.getGraphDatabase().queryEngineFor(type, infrastructure.getResultConverter()); } @Override @@ -527,7 +420,6 @@ public class Neo4jTemplate implements Neo4jOperations { } - // TODO result handling !! @SuppressWarnings("unchecked") public Iterable findAllByTraversal(Object entity, Class targetType, TraversalDescription traversalDescription) { return traverse(entity, traversalDescription).to((Class) targetType); @@ -576,82 +468,27 @@ public class Neo4jTemplate implements Neo4jOperations { } } - - public void setTransactionManager(PlatformTransactionManager transactionManager) { - this.transactionManager = transactionManager; - } - - public void setRelationshipEntityInstantiator(EntityInstantiator relationshipEntityInstantiator) { - this.relationshipEntityInstantiator = relationshipEntityInstantiator; - } - - public void setNodeEntityInstantiator(EntityInstantiator nodeEntityInstantiator) { - this.nodeEntityInstantiator = nodeEntityInstantiator; - } - - - public void setEntityStateHandler(EntityStateHandler entityStateHandler) { - this.entityStateHandler = entityStateHandler; - } - - public void setNodeEntityStateFactory(EntityStateFactory nodeEntityStateFactory) { - this.nodeEntityStateFactory = nodeEntityStateFactory; - } - - public void setRelationshipEntityStateFactory(EntityStateFactory relationshipEntityStateFactory) { - this.relationshipEntityStateFactory = relationshipEntityStateFactory; - } - public EntityStateHandler getEntityStateHandler() { - return entityStateHandler; - } - - public TypeRepresentationStrategy getNodeTypeRepresentationStrategy() { - return nodeTypeRepresentationStrategy; - } - - public void setNodeTypeRepresentationStrategy(TypeRepresentationStrategy nodeTypeRepresentationStrategy) { - this.nodeTypeRepresentationStrategy = nodeTypeRepresentationStrategy; - } - - public TypeRepresentationStrategy getRelationshipTypeRepresentationStrategy() { - return relationshipTypeRepresentationStrategy; - } - - public void setRelationshipTypeRepresentationStrategy(TypeRepresentationStrategy relationshipTypeRepresentationStrategy) { - this.relationshipTypeRepresentationStrategy = relationshipTypeRepresentationStrategy; + return infrastructure.getEntityStateHandler(); } public ConversionService getConversionService() { - return conversionService; - } - - public void setConversionService(ConversionService conversionService) { - this.conversionService = conversionService; + return infrastructure.getConversionService(); } public Validator getValidator() { - return validator; + return infrastructure.getValidator(); } - public void setValidator(Validator validatorFactory) { - this.validator = validatorFactory; - } - - public void setMappingContext(Neo4jMappingContext mappingContext) { - this.mappingContext = mappingContext; - } - - public GraphDatabaseService getGraphDatabaseService() { - return graphDatabaseService; + return infrastructure.getGraphDatabaseService(); } - public void setGraphDatabaseService(GraphDatabaseService graphDatabaseService) { - this.graphDatabaseService = graphDatabaseService; + public void setInfrastructure(MappingInfrastructure infrastructure) { + this.infrastructure = infrastructure; } - public void setGraphDatabase(GraphDatabase graphDatabase) { - this.graphDatabase = graphDatabase; + public MappingInfrastructure getInfrastructure() { + return infrastructure; } } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/ParameterCheck.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/ParameterCheck.java new file mode 100644 index 000000000..3f70f3f76 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/ParameterCheck.java @@ -0,0 +1,33 @@ +/** + * 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.support; + +import org.springframework.dao.InvalidDataAccessApiUsageException; + +/** + * @author mh + * @since 17.10.11 + */ +public class ParameterCheck { + public static void notNull(Object... pairs) { + assert pairs.length % 2 == 0 : "wrong number of pairs to check"; + for (int i = 0; i < pairs.length; i += 2) { + if (pairs[i] == null) { + throw new InvalidDataAccessApiUsageException("[Assertion failed] - " + pairs[i + 1] + " is required; it must not be null"); + } + } + } +} diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/EntityResultConverter.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/EntityResultConverter.java index dc1a1c34d..6c118272c 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/EntityResultConverter.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/EntityResultConverter.java @@ -19,7 +19,7 @@ package org.springframework.data.neo4j.support.conversion; import org.springframework.core.convert.ConversionService; import org.springframework.data.neo4j.conversion.DefaultConverter; import org.springframework.data.neo4j.core.EntityPath; -import org.springframework.data.neo4j.support.Neo4jTemplate; +import org.springframework.data.neo4j.mapping.EntityPersister; import org.springframework.data.neo4j.support.path.ConvertingEntityPath; /** @@ -27,25 +27,25 @@ import org.springframework.data.neo4j.support.path.ConvertingEntityPath; * @since 28.06.11 */ public class EntityResultConverter extends DefaultConverter { - private final Neo4jTemplate template; private final ConversionService conversionService; + private final EntityPersister entityPersister; - public EntityResultConverter(Neo4jTemplate template) { - this.template = template; - conversionService = this.template.getConversionService(); + public EntityResultConverter(ConversionService conversionService, EntityPersister entityPersister) { + this.conversionService = conversionService; + this.entityPersister = entityPersister; } @SuppressWarnings("unchecked") @Override protected Object doConvert(Object value, Class sourceType, Class targetType) { - if (template.isNodeEntity(targetType)) { - return template.projectTo(toNode(value, sourceType), targetType); - } - if (template.isRelationshipEntity(targetType)) { - return template.projectTo(toRelationship(value, sourceType), targetType); - } if (EntityPath.class.isAssignableFrom(targetType)) { - return new ConvertingEntityPath(template,toPath(value,sourceType)); + return new ConvertingEntityPath(entityPersister,toPath(value,sourceType)); + } + if (entityPersister.isNodeEntity(targetType)) { + return entityPersister.projectTo(toNode(value, sourceType), targetType); + } + if (entityPersister.isRelationshipEntity(targetType)) { + return entityPersister.projectTo(toRelationship(value, sourceType), targetType); } final Object result = super.doConvert(value, sourceType, targetType); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/path/ConvertingEntityPath.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/path/ConvertingEntityPath.java index 781812c16..11f79450f 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/path/ConvertingEntityPath.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/path/ConvertingEntityPath.java @@ -22,10 +22,7 @@ import org.neo4j.graphdb.PropertyContainer; import org.neo4j.graphdb.Relationship; 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.mapping.EntityPersister; import java.util.Iterator; @@ -43,8 +40,8 @@ public class ConvertingEntityPath implements EntityPath { private T projectEntityToFirstParameterOrCreateFromStoredType(Node node, Class... types) { if (node==null) return null; - if (types==null || types.length==0) return template.createEntityFromStoredType(node); - return template.projectTo(node, types[0]); + if (types==null || types.length==0) return persister.createEntityFromStoredType(node); + return persister.projectTo(node, types[0]); } @Override @@ -55,7 +52,7 @@ public class ConvertingEntityPath implements EntityPath { public T lastRelationshipEntity(Class... types) { Relationship relationship = lastRelationship(); if (relationship==null) return null; - return template.projectTo(relationship, getFirstOrDefault((Class) DefaultRelationshipBacked.class, types)); + return persister.projectTo(relationship, getFirstOrDefault((Class) DefaultRelationshipBacked.class, types)); } private static T getFirstOrDefault(final T defaultValue, T... values) { @@ -68,7 +65,7 @@ public class ConvertingEntityPath implements EntityPath { return new IterableWrapper(nodes()) { @Override protected T underlyingObjectToObject(Node node) { - return template.createEntityFromStoredType(node); + return persister.createEntityFromStoredType(node); } }; } @@ -78,7 +75,7 @@ public class ConvertingEntityPath implements EntityPath { return new IterableWrapper(relationships()) { @Override protected T underlyingObjectToObject(Relationship relationship) { - return template.projectTo(relationship, getFirstOrDefault((Class) DefaultRelationshipBacked.class, relationships)); + return persister.projectTo(relationship, getFirstOrDefault((Class) DefaultRelationshipBacked.class, relationships)); } }; } @@ -88,18 +85,18 @@ public class ConvertingEntityPath implements EntityPath { return new IterableWrapper(delegate) { @Override protected T underlyingObjectToObject(PropertyContainer element) { - return template.projectTo(element, getFirstOrDefault((Class) DefaultRelationshipBacked.class, relationships)); + return persister.projectTo(element, getFirstOrDefault((Class) DefaultRelationshipBacked.class, relationships)); } }; } - public ConvertingEntityPath(Neo4jTemplate template, Path delegate) { - this.template = template; + public ConvertingEntityPath(EntityPersister persister, Path delegate) { + this.persister = persister; this.delegate = delegate; } - private final Neo4jTemplate template; + private final EntityPersister persister; private final Path delegate; @Override diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/path/EntityEvaluator.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/path/EntityEvaluator.java index d96f3b9d2..b067c4f4b 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/path/EntityEvaluator.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/path/EntityEvaluator.java @@ -20,19 +20,22 @@ import org.neo4j.graphdb.Path; import org.neo4j.graphdb.traversal.Evaluation; import org.neo4j.graphdb.traversal.Evaluator; import org.springframework.data.neo4j.core.EntityPath; - -import org.springframework.data.neo4j.support.Neo4jTemplate; +import org.springframework.data.neo4j.mapping.EntityPersister; /** * @author mh * @since 26.02.11 */ public abstract class EntityEvaluator implements Evaluator { - private Neo4jTemplate template; + private EntityPersister persister; + + protected EntityEvaluator(EntityPersister persister) { + this.persister = persister; + } @Override public Evaluation evaluate(Path path) { - return evaluate(new ConvertingEntityPath(template, path)); + return evaluate(new ConvertingEntityPath(persister, path)); } public abstract Evaluation evaluate(EntityPath path); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryExecutor.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryExecutor.java index 673d1d930..ec24b59a6 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryExecutor.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/query/CypherQueryExecutor.java @@ -16,9 +16,7 @@ package org.springframework.data.neo4j.support.query; -import org.springframework.data.neo4j.annotation.QueryType; import org.springframework.data.neo4j.conversion.Result; -import org.springframework.data.neo4j.support.Neo4jTemplate; import org.springframework.util.ClassUtils; import java.util.Map; @@ -31,11 +29,12 @@ import java.util.Map; public class CypherQueryExecutor implements QueryOperations> { private final QueryEngine> queryEngine; - public CypherQueryExecutor(Neo4jTemplate ctx) { + @SuppressWarnings("unchecked") + public CypherQueryExecutor(final QueryEngine queryEngine) { if (ClassUtils.isPresent("org.neo4j.cypher.javacompat.ExecutionEngine",getClass().getClassLoader())) { - queryEngine = ctx.queryEngineFor(QueryType.Cypher); + this.queryEngine = queryEngine; } else { - queryEngine = new QueryEngine>() { + this.queryEngine = new QueryEngine>() { @Override public Result> query(String statement, Map params) { throw new IllegalStateException("Cypher is not available, please add it to your dependencies to execute: "+statement); diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/config/ConfigurationConfirmationTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/config/ConfigurationConfirmationTest.java index 4a7958335..a5cbacc0d 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/config/ConfigurationConfirmationTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/config/ConfigurationConfirmationTest.java @@ -27,6 +27,14 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; public class ConfigurationConfirmationTest { @Test(expected = BeanCreationException.class) public void testInvalidTransactionManagerFails() { - ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext("classpath:org/springframework/data/neo4j/config/ConfigurationCofirmationTest-context.xml"); + ClassPathXmlApplicationContext ctx = null; + try { + ctx = new ClassPathXmlApplicationContext("classpath:org/springframework/data/neo4j/config/ConfigurationConfirmationTest-context.xml"); + ctx.start(); + } finally { + if (ctx != null) { + ctx.close(); + } + } } } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/config/DataGraphNamespaceHandlerTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/config/DataGraphNamespaceHandlerTest.java index 2ac1860cf..f88bd9189 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/config/DataGraphNamespaceHandlerTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/config/DataGraphNamespaceHandlerTest.java @@ -61,6 +61,7 @@ public class DataGraphNamespaceHandlerTest { private Config assertInjected(String testCase) { ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:org/springframework/data/neo4j/config/DataGraphNamespaceHandlerTest" + testCase + "-context.xml"); + try { Config config = ctx.getBean("config", Config.class); Neo4jTemplate template = config.neo4jTemplate; Assert.assertNotNull("template", template); @@ -70,6 +71,9 @@ public class DataGraphNamespaceHandlerTest { Assert.assertNotNull("transactionManager",config.transactionManager); config.graphDatabaseService.shutdown(); return config; + } finally { + ctx.close(); + } } } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jEntityConverterTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jEntityConverterTest.java index e78823cdf..3e8f40b88 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jEntityConverterTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jEntityConverterTest.java @@ -75,7 +75,7 @@ public class Neo4jEntityConverterTest extends Neo4jPersistentTestBase { public void testFindNewlyWrittenNodeInIndex() { storeInGraph(michael); final Node createdNode = michaelNode(); - final Index index = gdc.getIndex(Person.class, Person.NAME_INDEX); + final Index index = template.getIndex(Person.class, Person.NAME_INDEX); final Node found = index.get("name", "Michael").getSingle(); assertEquals("node found in index", createdNode, found); } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersisterTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersisterTest.java index bb3678f5a..5da4d3146 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersisterTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jEntityPersisterTest.java @@ -15,12 +15,9 @@ */ package org.springframework.data.neo4j.mapping; -import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.neo4j.graphdb.Node; -import org.springframework.data.neo4j.annotation.GraphId; -import org.springframework.data.neo4j.annotation.NodeEntity; import org.springframework.data.neo4j.model.Friendship; import org.springframework.data.neo4j.model.Person; import org.springframework.data.neo4j.support.ManagedEntity; @@ -35,7 +32,7 @@ public class Neo4jEntityPersisterTest extends Neo4jPersistentTestBase { @Test public void testCreateEntityFromStoredType() throws Exception { - final Node personNode = gdc.createNode(); + final Node personNode = template.createNode(); personNode.setProperty("name","Michael"); final Person person = entityPersister.createEntityFromState(personNode, Person.class); assertEquals("Michael",person.getName()); diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jPersistentTestBase.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jPersistentTestBase.java index 8cbbd7d84..0450f3a6d 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jPersistentTestBase.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/mapping/Neo4jPersistentTestBase.java @@ -30,10 +30,7 @@ import org.springframework.data.neo4j.fieldaccess.NodeDelegatingFieldAccessorFac import org.springframework.data.neo4j.fieldaccess.RelationshipDelegatingFieldAccessorFactory; import org.springframework.data.neo4j.model.Group; import org.springframework.data.neo4j.model.Person; -import org.springframework.data.neo4j.support.DelegatingGraphDatabase; -import org.springframework.data.neo4j.support.EntityStateHandler; -import org.springframework.data.neo4j.support.EntityTools; -import org.springframework.data.neo4j.support.Neo4jTemplate; +import org.springframework.data.neo4j.support.*; import org.springframework.data.neo4j.support.node.NodeEntityInstantiator; import org.springframework.data.neo4j.support.node.NodeEntityStateFactory; import org.springframework.data.neo4j.support.relationship.RelationshipEntityInstantiator; @@ -54,7 +51,7 @@ import static java.util.Arrays.asList; */ public class Neo4jPersistentTestBase { private Transaction tx; - protected Neo4jTemplate gdc; + protected Neo4jTemplate template; protected NodeEntityStateFactory nodeEntityStateFactory; protected RelationshipEntityStateFactory relationshipEntityStateFactory; protected EntityStateHandler entityStateHandler; @@ -85,32 +82,34 @@ public class Neo4jPersistentTestBase { @Before public void setUp() throws Exception { + // todo cleanup !! mappingContext = new Neo4jMappingContext(); - gdc = createContext(mappingContext); - tx = gdc.beginTx(); + MappingInfrastructure infrastructure = createInfrastructure(mappingContext); + + template = new Neo4jTemplate(infrastructure); nodeEntityStateFactory = createNodeEntityStateFactory(mappingContext); relationshipEntityStateFactory = createRelationshipEntityStateFactory(mappingContext); - gdc.setNodeEntityStateFactory(nodeEntityStateFactory); - gdc.setRelationshipEntityStateFactory(relationshipEntityStateFactory); + infrastructure.setNodeEntityStateFactory(nodeEntityStateFactory); + infrastructure.setRelationshipEntityStateFactory(relationshipEntityStateFactory); + template.postConstruct(); - gdc.postConstruct(); - - entityStateHandler = gdc.getEntityStateHandler(); + entityStateHandler = infrastructure.getEntityStateHandler(); nodeEntityInstantiator = new NodeEntityInstantiator(entityStateHandler); relationshipEntityInstantiator = new RelationshipEntityInstantiator(entityStateHandler); - nodeTypeMapper = new DefaultTypeMapper(new TRSTypeAliasAccessor(gdc.getNodeTypeRepresentationStrategy()),asList(new ClassValueTypeInformationMapper())); + nodeTypeMapper = new DefaultTypeMapper(new TRSTypeAliasAccessor(infrastructure.getNodeTypeRepresentationStrategy()),asList(new ClassValueTypeInformationMapper())); nodeStateTransmitter = new SourceStateTransmitter(nodeEntityStateFactory); relationshipStateTransmitter = new SourceStateTransmitter(relationshipEntityStateFactory); - conversionService = gdc.getConversionService(); + conversionService = template.getConversionService(); fetchHandler = new Neo4jEntityFetchHandler(entityStateHandler, conversionService, nodeStateTransmitter, relationshipStateTransmitter); - final EntityTools nodeEntityTools = new EntityTools(gdc.getNodeTypeRepresentationStrategy(), nodeEntityStateFactory, nodeEntityInstantiator); - final EntityTools relationshipEntityTools = new EntityTools(gdc.getRelationshipTypeRepresentationStrategy(), relationshipEntityStateFactory, relationshipEntityInstantiator); + final EntityTools nodeEntityTools = new EntityTools(infrastructure.getNodeTypeRepresentationStrategy(), nodeEntityStateFactory, nodeEntityInstantiator); + final EntityTools relationshipEntityTools = new EntityTools(infrastructure.getRelationshipTypeRepresentationStrategy(), relationshipEntityStateFactory, relationshipEntityInstantiator); entityPersister = new Neo4jEntityPersister(conversionService, nodeEntityTools, relationshipEntityTools, mappingContext, entityStateHandler); + tx = template.beginTx(); group = new Group(); michael = new Person("Michael", 37); emil = new Person("Emil", 30); @@ -120,33 +119,32 @@ public class Neo4jPersistentTestBase { private NodeEntityStateFactory createNodeEntityStateFactory(Neo4jMappingContext mappingContext) { final NodeEntityStateFactory nodeEntityStateFactory = new NodeEntityStateFactory(); nodeEntityStateFactory.setMappingContext(mappingContext); - nodeEntityStateFactory.setTemplate(gdc); - nodeEntityStateFactory.setNodeDelegatingFieldAccessorFactory(new NodeDelegatingFieldAccessorFactory(gdc)); + nodeEntityStateFactory.setTemplate(template); + nodeEntityStateFactory.setNodeDelegatingFieldAccessorFactory(new NodeDelegatingFieldAccessorFactory(template)); return nodeEntityStateFactory; } private RelationshipEntityStateFactory createRelationshipEntityStateFactory(Neo4jMappingContext mappingContext) { final RelationshipEntityStateFactory relationshipEntityStateFactory = new RelationshipEntityStateFactory(); relationshipEntityStateFactory.setMappingContext(mappingContext); - relationshipEntityStateFactory.setTemplate(gdc); - relationshipEntityStateFactory.setRelationshipDelegatingFieldAccessorFactory(new RelationshipDelegatingFieldAccessorFactory(gdc)); + relationshipEntityStateFactory.setTemplate(template); + relationshipEntityStateFactory.setRelationshipDelegatingFieldAccessorFactory(new RelationshipDelegatingFieldAccessorFactory(template)); return relationshipEntityStateFactory; } - private Neo4jTemplate createContext(Neo4jMappingContext mappingContext) throws Exception { - Neo4jTemplate gdc = new Neo4jTemplate(); + private MappingInfrastructure createInfrastructure(Neo4jMappingContext mappingContext) throws Exception { + MappingInfrastructure infrastructure=new MappingInfrastructure(); final ImpermanentGraphDatabase gdb = new ImpermanentGraphDatabase(); - gdc.setGraphDatabaseService(gdb); + infrastructure.setGraphDatabaseService(gdb); final DelegatingGraphDatabase graphDatabase = new DelegatingGraphDatabase(gdb); - gdc.setGraphDatabase(graphDatabase); - - gdc.setMappingContext(mappingContext); + infrastructure.setGraphDatabase(graphDatabase); + infrastructure.setMappingContext(mappingContext); final EntityStateHandler entityStateHandler = new EntityStateHandler(mappingContext, graphDatabase); - gdc.setNodeTypeRepresentationStrategy(new NoopNodeTypeRepresentationStrategy(new NodeEntityInstantiator(entityStateHandler))); - gdc.setRelationshipTypeRepresentationStrategy(new NoopRelationshipTypeRepresentationStrategy(new RelationshipEntityInstantiator(entityStateHandler))); - gdc.setConversionService(new Neo4jConversionServiceFactoryBean().getObject()); - gdc.setEntityStateHandler(entityStateHandler); - return gdc; + infrastructure.setNodeTypeRepresentationStrategy(new NoopNodeTypeRepresentationStrategy(new NodeEntityInstantiator(entityStateHandler))); + infrastructure.setRelationshipTypeRepresentationStrategy(new NoopRelationshipTypeRepresentationStrategy(new RelationshipEntityInstantiator(entityStateHandler))); + infrastructure.setConversionService(new Neo4jConversionServiceFactoryBean().getObject()); + infrastructure.setEntityStateHandler(entityStateHandler); + return infrastructure; } protected List groupMemberNodes() { @@ -161,21 +159,21 @@ public class Neo4jPersistentTestBase { public void tearDown() throws Exception { tx.failure(); tx.finish(); - gdc.getGraphDatabaseService().shutdown(); + template.getGraphDatabaseService().shutdown(); } protected Node michaelNode() { - return gdc.getNode(michael.getId()); + return template.getNode(michael.getId()); } protected Node createNewNode() { - return gdc.createNode(); + return template.createNode(); } protected Group storeInGraph(Group g) { final Long id = g.getId(); if (id != null) { - write(g, gdc.getNode(id)); + write(g, template.getNode(id)); } else { write(g, null); } @@ -185,7 +183,7 @@ public class Neo4jPersistentTestBase { protected Person storeInGraph(Person p) { final Long id = p.getId(); if (id != null) { - write(p, gdc.getNode(id)); + write(p, template.getNode(id)); } else { write(p,null); } @@ -203,7 +201,7 @@ public class Neo4jPersistentTestBase { } protected Node groupNode() { - return gdc.getNode(group.getId()); + return template.getNode(group.getId()); } protected Set set(T... objs) { @@ -215,11 +213,11 @@ public class Neo4jPersistentTestBase { } protected Node andresNode() { - return gdc.getNode(andres.getId()); + return template.getNode(andres.getId()); } protected Node emilNode() { - return gdc.getNode(emil.getId()); + return template.getNode(emil.getId()); } public Person readPerson(Node node) { diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/GraphDatabaseContextTemplateTest.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/GraphDatabaseContextTemplateTest.java index 03c97e82b..c09a53411 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/GraphDatabaseContextTemplateTest.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/template/GraphDatabaseContextTemplateTest.java @@ -56,6 +56,7 @@ public class GraphDatabaseContextTemplateTest { private static final DynamicRelationshipType HAS = DynamicRelationshipType.withName("has"); @Autowired Neo4jTemplate neo4jTemplate; + @Autowired protected GraphDatabase graphDatabase; protected Node referenceNode; protected Relationship relationship1; @@ -72,7 +73,7 @@ public class GraphDatabaseContextTemplateTest { @Before public void setUp() throws Exception { Neo4jHelper.cleanDb(neo4jTemplate); - graphDatabase = neo4jTemplate.getGraphDatabase(); + // graphDatabase = neo4jTemplate.getGraphDatabase(); referenceNode = graphDatabase.getReferenceNode(); createData(); } diff --git a/spring-data-neo4j/src/test/resources/org/springframework/data/neo4j/config/ConfigurationCofirmationTest-context.xml b/spring-data-neo4j/src/test/resources/org/springframework/data/neo4j/config/ConfigurationConfirmationTest-context.xml similarity index 100% rename from spring-data-neo4j/src/test/resources/org/springframework/data/neo4j/config/ConfigurationCofirmationTest-context.xml rename to spring-data-neo4j/src/test/resources/org/springframework/data/neo4j/config/ConfigurationConfirmationTest-context.xml