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 f06c876399..c58a0fd9f1 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 @@ -16,6 +16,10 @@ package org.springframework.data.neo4j.config; +import static java.util.Arrays.*; + +import javax.validation.Validator; + import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; @@ -41,7 +45,13 @@ import org.springframework.data.neo4j.support.MappingInfrastructure; import org.springframework.data.neo4j.support.Neo4jExceptionTranslator; import org.springframework.data.neo4j.support.Neo4jTemplate; -import org.springframework.data.neo4j.support.mapping.*; +import org.springframework.data.neo4j.support.index.IndexProvider; +import org.springframework.data.neo4j.support.index.IndexProviderImpl; +import org.springframework.data.neo4j.support.mapping.EntityStateHandler; +import org.springframework.data.neo4j.support.mapping.Neo4jEntityFetchHandler; +import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext; +import org.springframework.data.neo4j.support.mapping.SourceStateTransmitter; +import org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor; import org.springframework.data.neo4j.support.node.NodeEntityInstantiator; import org.springframework.data.neo4j.support.node.NodeEntityStateFactory; import org.springframework.data.neo4j.support.relationship.RelationshipEntityInstantiator; @@ -52,10 +62,6 @@ import org.springframework.transaction.jta.JtaTransactionManager; import org.springframework.transaction.jta.UserTransactionAdapter; -import javax.validation.Validator; - -import static java.util.Arrays.asList; - /** * Abstract base class for code based configuration of Spring managed Neo4j infrastructure. *

Subclasses are required to provide an implementation of graphDbService .... @@ -105,6 +111,8 @@ public MappingInfrastructure mappingInfrastructure() throws Exception { infrastructure.setTransactionManager(neo4jTransactionManager()); infrastructure.setGraphDatabase(graphDatabase()); + + infrastructure.setIndexProvider(indexProvider()); if (validator!=null) { infrastructure.setValidator(validator); @@ -251,4 +259,9 @@ public ConfigurationCheck configurationCheck() throws Exception { public PersistenceExceptionTranslator persistenceExceptionTranslator() { return new Neo4jExceptionTranslator(); } + + @Bean + public IndexProvider indexProvider() throws Exception { + return new IndexProviderImpl(mappingContext(), graphDatabase()); + } } 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 index fc719381aa..8187e91ca9 100644 --- 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 @@ -15,6 +15,8 @@ */ package org.springframework.data.neo4j.support; +import javax.validation.Validator; + import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Relationship; @@ -26,7 +28,12 @@ import org.springframework.data.neo4j.mapping.EntityInstantiator; import org.springframework.data.neo4j.support.conversion.EntityResultConverter; import org.springframework.data.neo4j.support.index.IndexProvider; -import org.springframework.data.neo4j.support.mapping.*; +import org.springframework.data.neo4j.support.index.IndexProviderImpl; +import org.springframework.data.neo4j.support.mapping.EntityRemover; +import org.springframework.data.neo4j.support.mapping.EntityStateHandler; +import org.springframework.data.neo4j.support.mapping.EntityTools; +import org.springframework.data.neo4j.support.mapping.Neo4jEntityPersister; +import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext; import org.springframework.data.neo4j.support.node.EntityStateFactory; import org.springframework.data.neo4j.support.node.NodeEntityInstantiator; import org.springframework.data.neo4j.support.query.CypherQueryExecutor; @@ -35,8 +42,6 @@ import org.springframework.data.neo4j.support.typerepresentation.TypeRepresentationStrategyFactory; import org.springframework.transaction.PlatformTransactionManager; -import javax.validation.Validator; - /** * @author mh * @since 17.10.11 @@ -102,12 +107,14 @@ public void postConstruct() { 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)); + if (this.indexProvider == null) { + this.indexProvider = new IndexProviderImpl(this.mappingContext, graphDatabase); + } } @@ -229,4 +236,8 @@ public Neo4jMappingContext getMappingContext() { public void setTypeRepresentationStrategyFactory(TypeRepresentationStrategyFactory typeRepresentationStrategyFactory) { this.typeRepresentationStrategyFactory = typeRepresentationStrategyFactory; } + + public void setIndexProvider(IndexProvider indexProvider) { + this.indexProvider = indexProvider; + } } 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 5a65eeeea6..b24afbb9a1 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 @@ -16,9 +16,22 @@ package org.springframework.data.neo4j.support; +import static org.springframework.data.neo4j.support.ParameterCheck.*; + +import java.util.Map; + +import javax.annotation.PostConstruct; +import javax.validation.Validator; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.neo4j.graphdb.*; +import org.neo4j.graphdb.DynamicRelationshipType; +import org.neo4j.graphdb.GraphDatabaseService; +import org.neo4j.graphdb.Node; +import org.neo4j.graphdb.Path; +import org.neo4j.graphdb.PropertyContainer; +import org.neo4j.graphdb.Relationship; +import org.neo4j.graphdb.Transaction; import org.neo4j.graphdb.index.Index; import org.neo4j.graphdb.traversal.TraversalDescription; import org.neo4j.helpers.collection.ClosableIterable; @@ -57,12 +70,6 @@ import org.springframework.transaction.support.TransactionCallback; import org.springframework.transaction.support.TransactionTemplate; -import javax.annotation.PostConstruct; -import javax.validation.Validator; -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. @@ -546,10 +553,12 @@ public Result lookup(final Class indexedType } } + @Override public Index getIndex(String indexName, Class indexedType) { return getIndexProvider().getIndex(indexedType, indexName); } + @Override public Index getIndex(Class indexedType, String propertyName) { final Neo4jPersistentEntityImpl persistentEntity = getPersistentEntity(indexedType); final Neo4jPersistentProperty property = persistentEntity.getPersistentProperty(propertyName); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/index/IndexProvider.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/index/IndexProvider.java index fb8b2ed2e9..6011e0b233 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/index/IndexProvider.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/index/IndexProvider.java @@ -15,90 +15,31 @@ */ package org.springframework.data.neo4j.support.index; -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.support.mapping.Neo4jMappingContext; -import org.springframework.data.neo4j.support.mapping.Neo4jPersistentEntityImpl; import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty; -import static org.springframework.data.neo4j.support.ParameterCheck.notNull; +public interface IndexProvider { -/** - * @author mh - * @since 17.10.11 - */ -public class IndexProvider { - private Neo4jMappingContext mappingContext; - private final GraphDatabase graphDatabase; - - public IndexProvider(Neo4jMappingContext mappingContext, GraphDatabase graphDatabase) { - this.mappingContext = mappingContext; - this.graphDatabase = graphDatabase; - } - - public Index getIndex(Class type) { - return getIndex(type, null); - } + public abstract Index getIndex(Class type); - public Index getIndex(Class type, String indexName) { - return getIndex(type, indexName, null); - } + public abstract Index getIndex(Class type, String indexName); @SuppressWarnings("unchecked") - public Index getIndex(Class type, String indexName, IndexType indexType) { - 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 = indexType == 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, indexType); - if (persistentEntity.isRelationshipEntity()) - return (Index) createIndex(Relationship.class, indexName, indexType); - throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity"); - } + public abstract Index getIndex(Class type, String indexName, + IndexType indexType); @SuppressWarnings("unchecked") - public Index getIndex(String indexName) { - return graphDatabase.getIndex(indexName); - } + public abstract Index getIndex(String 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); - } + public abstract boolean isNode(Class type); // TODO handle existing indexes @SuppressWarnings("unchecked") - public Index createIndex(Class type, String indexName, IndexType fullText) { - return graphDatabase.createIndex(type, indexName, fullText); - } + public abstract Index createIndex(Class type, String indexName, + IndexType fullText); + + public abstract Index getIndex(Neo4jPersistentProperty property, + final Class instanceType); - public Index getIndex(Neo4jPersistentProperty property, final Class instanceType) { - final Indexed indexedAnnotation = property.getAnnotation(Indexed.class); - final Class declaringType = property.getOwner().getType(); - final String providedIndexName = indexedAnnotation==null || indexedAnnotation.indexName().isEmpty() ? null : indexedAnnotation.indexName(); - final Indexed.Level level = indexedAnnotation == null ? Indexed.Level.CLASS : indexedAnnotation.level(); - String indexName = Indexed.Name.get(level, declaringType, providedIndexName, instanceType); - if (!property.isIndexed() || property.getIndexInfo().getIndexType() == IndexType.SIMPLE) { - return getIndex(declaringType, indexName, IndexType.SIMPLE); - } - String defaultIndexName = Indexed.Name.get(level, declaringType, null, instanceType.getClass()); - if (providedIndexName==null || providedIndexName.equals(defaultIndexName)) throw new IllegalStateException("Index name for "+property+" must differ from the default name: "+defaultIndexName); - return getIndex(declaringType, indexName, property.getIndexInfo().getIndexType()); - } -} +} \ No newline at end of file diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/index/IndexProviderImpl.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/index/IndexProviderImpl.java new file mode 100644 index 0000000000..0aff8c38a4 --- /dev/null +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/index/IndexProviderImpl.java @@ -0,0 +1,110 @@ +/** + * 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.index; + +import static org.springframework.data.neo4j.support.ParameterCheck.*; + +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.Neo4jPersistentProperty; +import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext; +import org.springframework.data.neo4j.support.mapping.Neo4jPersistentEntityImpl; + +/** + * @author mh + * @since 17.10.11 + */ +public class IndexProviderImpl implements IndexProvider { + private final Neo4jMappingContext mappingContext; + private final GraphDatabase graphDatabase; + + public IndexProviderImpl(Neo4jMappingContext mappingContext, GraphDatabase graphDatabase) { + this.mappingContext = mappingContext; + this.graphDatabase = graphDatabase; + } + + @Override + public Index getIndex(Class type) { + return getIndex(type, null); + } + + @Override + public Index getIndex(Class type, String indexName) { + return getIndex(type, indexName, null); + } + @Override + @SuppressWarnings("unchecked") + public Index getIndex(Class type, String indexName, IndexType indexType) { + 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 = indexType == 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, indexType); + if (persistentEntity.isRelationshipEntity()) + return (Index) createIndex(Relationship.class, indexName, indexType); + throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity"); + } + + @Override + @SuppressWarnings("unchecked") + public Index getIndex(String indexName) { + return graphDatabase.getIndex(indexName); + } + + @Override + 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 + @Override + @SuppressWarnings("unchecked") + public Index createIndex(Class type, String indexName, IndexType fullText) { + return graphDatabase.createIndex(type, indexName, fullText); + } + + @Override + public Index getIndex(Neo4jPersistentProperty property, final Class instanceType) { + final Indexed indexedAnnotation = property.getAnnotation(Indexed.class); + final Class declaringType = property.getOwner().getType(); + final String providedIndexName = indexedAnnotation==null || indexedAnnotation.indexName().isEmpty() ? null : indexedAnnotation.indexName(); + final Indexed.Level level = indexedAnnotation == null ? Indexed.Level.CLASS : indexedAnnotation.level(); + String indexName = Indexed.Name.get(level, declaringType, providedIndexName, instanceType); + if (!property.isIndexed() || property.getIndexInfo().getIndexType() == IndexType.SIMPLE) { + return getIndex(declaringType, indexName, IndexType.SIMPLE); + } + String defaultIndexName = Indexed.Name.get(level, declaringType, null, instanceType.getClass()); + if (providedIndexName==null || providedIndexName.equals(defaultIndexName)) throw new IllegalStateException("Index name for "+property+" must differ from the default name: "+defaultIndexName); + return getIndex(declaringType, indexName, property.getIndexInfo().getIndexType()); + } +}