package reorganisation

added lookup method with instance-type and propertyName to determine the correct index
documentation
more tests for Neo4j-Template and Neo4jOperations
This commit is contained in:
Michael Hunger
2011-10-18 15:23:55 +02:00
parent 7148212928
commit bb7cc28e21
55 changed files with 367 additions and 309 deletions

View File

@@ -32,8 +32,8 @@ import org.springframework.data.neo4j.annotation.*;
import org.springframework.data.neo4j.aspects.core.NodeBacked;
import org.springframework.data.neo4j.aspects.core.RelationshipBacked;
import org.springframework.data.neo4j.support.EntityStateHandler;
import org.springframework.data.neo4j.support.RelationshipResult;
import org.springframework.data.neo4j.mapping.RelationshipResult;
import org.springframework.data.neo4j.support.mapping.EntityStateHandler;
import org.springframework.data.neo4j.support.node.NodeEntityStateFactory;
import org.springframework.data.neo4j.support.DoReturn;
import org.springframework.data.neo4j.core.EntityPath;

View File

@@ -16,7 +16,7 @@
package org.springframework.data.neo4j.aspects.core;
import org.springframework.data.neo4j.support.ManagedEntity;
import org.springframework.data.neo4j.mapping.ManagedEntity;
/**
* super interface denoting entities that are graph backed, the backing STATE can be a {@link org.neo4j.graphdb.Node}

View File

@@ -55,7 +55,7 @@
</bean>
<bean id="entityStateHandler" class="org.springframework.data.neo4j.support.EntityStateHandler">
<bean id="entityStateHandler" class="org.springframework.data.neo4j.support.mapping.EntityStateHandler">
<constructor-arg ref="mappingContext"/>
<constructor-arg ref="graphDatabase"/>
</bean>
@@ -89,7 +89,7 @@
<property name="mappingContext" ref="mappingContext"/>
</bean>
<bean id="mappingContext" class="org.springframework.data.neo4j.mapping.Neo4jMappingContext"/>
<bean id="mappingContext" class="org.springframework.data.neo4j.support.mapping.Neo4jMappingContext"/>
<bean id="relationshipEntityStateFactory" class="org.springframework.data.neo4j.support.relationship.RelationshipEntityStateFactory">
<property name="relationshipDelegatingFieldAccessorFactory">
@@ -145,5 +145,5 @@
<!-- Adds dependency checks for setters annotated with @Required -->
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
<bean class="org.springframework.data.neo4j.template.Neo4jExceptionTranslator"/>
<bean class="org.springframework.data.neo4j.support.Neo4jExceptionTranslator"/>
</beans>

View File

@@ -23,9 +23,8 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.data.neo4j.aspects.config.Neo4jAspectConfiguration;
import org.springframework.data.neo4j.cross_store.support.node.CrossStoreNodeEntityInstantiator;
import org.springframework.data.neo4j.cross_store.support.node.CrossStoreNodeEntityStateFactory;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
import org.springframework.data.neo4j.support.node.NodeEntityStateFactory;
import org.springframework.data.neo4j.transaction.ChainedTransactionManager;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

View File

@@ -18,7 +18,7 @@ package org.springframework.data.neo4j.cross_store.support.node;
import org.neo4j.graphdb.Node;
import org.springframework.data.neo4j.aspects.core.NodeBacked;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
@@ -45,7 +45,7 @@ public class CrossStoreNodeEntityInstantiator implements EntityInstantiator<Node
/**
* Takes the JPA id stored in the "FOREIGN_ID" property of the node for a {@link EntityManager#find(Class, Object)} operation.
* If the entity is found its instance is associated with the graph node and returned otherwise a new node entity instance for
* this node is created by the original {@link EntityInstantiator}.
* this node is created by the original {@link org.springframework.data.neo4j.mapping.EntityInstantiator}.
* @param n Node to instantiate an entity for
* @param entityClass type of the entity
* @param <T> generic type of the entity

View File

@@ -110,7 +110,7 @@
<constructor-arg ref="nodeEntityInstantiator"/>
<constructor-arg ref="entityManagerFactory"/>
</bean>
<bean id="entityStateHandler" class="org.springframework.data.neo4j.support.EntityStateHandler">
<bean id="entityStateHandler" class="org.springframework.data.neo4j.support.mapping.EntityStateHandler">
<constructor-arg ref="mappingContext"/>
<constructor-arg ref="graphDatabase"/>
</bean>
@@ -142,7 +142,7 @@
<property name="mappingContext" ref="mappingContext"/>
</bean>
<bean id="mappingContext" class="org.springframework.data.neo4j.mapping.Neo4jMappingContext"/>
<bean id="mappingContext" class="org.springframework.data.neo4j.support.mapping.Neo4jMappingContext"/>
<bean id="relationshipEntityStateFactory" class="org.springframework.data.neo4j.support.relationship.RelationshipEntityStateFactory">

View File

@@ -38,12 +38,14 @@ import org.springframework.data.neo4j.fieldaccess.NodeDelegatingFieldAccessorFac
import org.springframework.data.neo4j.fieldaccess.RelationshipDelegatingFieldAccessorFactory;
import org.springframework.data.neo4j.mapping.*;
import org.springframework.data.neo4j.support.*;
import org.springframework.data.neo4j.support.mapping.*;
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
import org.springframework.data.neo4j.support.node.NodeEntityStateFactory;
import org.springframework.data.neo4j.support.relationship.RelationshipEntityInstantiator;
import org.springframework.data.neo4j.support.relationship.RelationshipEntityStateFactory;
import org.springframework.data.neo4j.support.typerepresentation.ClassValueTypeInformationMapper;
import org.springframework.data.neo4j.support.typerepresentation.TypeRepresentationStrategyFactory;
import org.springframework.data.neo4j.template.Neo4jExceptionTranslator;
import org.springframework.data.neo4j.support.Neo4jExceptionTranslator;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.transaction.jta.UserTransactionAdapter;

View File

@@ -21,24 +21,18 @@ import org.apache.commons.logging.LogFactory;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.index.Index;
import org.neo4j.index.lucene.ValueContext;
import org.springframework.data.neo4j.annotation.Indexed;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import java.lang.reflect.AnnotatedElement;
public class IndexingPropertyFieldAccessorListenerFactory<S extends PropertyContainer, T> implements FieldAccessorListenerFactory {
private final PropertyFieldAccessorFactory propertyFieldAccessorFactory;
private final ConvertingNodePropertyFieldAccessorFactory convertingNodePropertyFieldAccessorFactory;
private final IndexProvider indexProvider;
private final Neo4jTemplate template;
public IndexingPropertyFieldAccessorListenerFactory(final Neo4jTemplate template, final PropertyFieldAccessorFactory propertyFieldAccessorFactory, final ConvertingNodePropertyFieldAccessorFactory convertingNodePropertyFieldAccessorFactory) {
this.template = template;
indexProvider = new IndexProvider<S,T>(template);
this.propertyFieldAccessorFactory = propertyFieldAccessorFactory;
this.convertingNodePropertyFieldAccessorFactory = convertingNodePropertyFieldAccessorFactory;
}
@@ -55,42 +49,10 @@ public class IndexingPropertyFieldAccessorListenerFactory<S extends PropertyCont
@Override
public FieldAccessListener forField(Neo4jPersistentProperty property) {
return new IndexingPropertyFieldAccessorListener(property, indexProvider, template);
return new IndexingPropertyFieldAccessorListener(property, template);
}
public static class IndexProvider<S extends PropertyContainer, T> {
private final Neo4jTemplate template;
public IndexProvider(Neo4jTemplate template) {
this.template = template;
}
private String getIndexKey(Neo4jPersistentProperty property) {
Indexed indexed = property.getAnnotation(Indexed.class);
if (indexed==null || indexed.fieldName().isEmpty()) return property.getNeo4jPropertyName();
return indexed.fieldName();
}
private Indexed getIndexedAnnotation(AnnotatedElement element) {
return element.getAnnotation(Indexed.class);
}
private Index<S> getIndex(Neo4jPersistentProperty property, Object instance) {
final Indexed indexedAnnotation = property.getAnnotation(Indexed.class);
@SuppressWarnings("unchecked") final Class<T> type = (Class<T>) property.getOwner().getType();
final String providedIndexName = indexedAnnotation.indexName().isEmpty() ? null : indexedAnnotation.indexName();
String indexName = Indexed.Name.get(indexedAnnotation.level(), type, providedIndexName, instance.getClass());
if (!property.getIndexInfo().isFulltext()) {
return template.getIndex(type, indexName, false);
}
if (providedIndexName == null) throw new IllegalStateException("@Indexed(fullext=true) on "+property+" requires an providedIndexName too ");
String defaultIndexName = Indexed.Name.get(indexedAnnotation.level(), type, null, instance.getClass());
if (providedIndexName.equals(defaultIndexName)) throw new IllegalStateException("Full-index name for "+property+" must differ from the default name: "+defaultIndexName);
return template.getIndex(type, indexName, true);
}
}
/**
* @author Michael Hunger
* @since 12.09.2010
@@ -101,19 +63,17 @@ public class IndexingPropertyFieldAccessorListenerFactory<S extends PropertyCont
protected final String indexKey;
private final Neo4jPersistentProperty property;
private final IndexProvider indexProvider;
private final Neo4jTemplate template;
public IndexingPropertyFieldAccessorListener(final Neo4jPersistentProperty property, IndexProvider indexProvider, Neo4jTemplate template) {
public IndexingPropertyFieldAccessorListener(final Neo4jPersistentProperty property, Neo4jTemplate template) {
this.property = property;
this.indexProvider = indexProvider;
this.template = template;
indexKey = indexProvider.getIndexKey(property);
indexKey = template.getIndexKey(property);
}
@Override
public void valueChanged(Object entity, Object oldVal, Object newVal) {
@SuppressWarnings("unchecked") Index<T> index = indexProvider.getIndex(property, entity);
@SuppressWarnings("unchecked") Index<T> index = template.getIndex(property, entity.getClass());
if (newVal instanceof Number) newVal = ValueContext.numeric((Number) newVal);
final T state = template.getPersistentState(entity);

View File

@@ -17,10 +17,10 @@
package org.springframework.data.neo4j.fieldaccess;
import org.springframework.data.neo4j.core.EntityState;
import org.springframework.data.neo4j.mapping.ManagedEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.DoReturn;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.ManagedEntity;
import java.util.AbstractSet;
import java.util.Collection;

View File

@@ -16,10 +16,10 @@
package org.springframework.data.neo4j.fieldaccess;
import org.springframework.data.neo4j.core.EntityState;
import org.springframework.data.neo4j.mapping.ManagedEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.DoReturn;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.ManagedEntity;
import java.util.Map;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
package org.springframework.data.neo4j.mapping;
/**
* Interface to be implemented by classes that can instantiate and configure entities. The framework must do this when

View File

@@ -0,0 +1,52 @@
/**
* 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.springframework.data.neo4j.annotation.Indexed;
/**
* @author mh
* @since 18.10.11
*/
public class IndexInfo {
private String indexName;
private boolean fulltext;
private final String fieldName;
private final Indexed.Level level;
public IndexInfo(Indexed annotation, Neo4jPersistentProperty property) {
this.indexName = determineIndexName(annotation,property);
this.fulltext = annotation.fulltext();
fieldName = annotation.fieldName();
level = annotation.level();
}
private String determineIndexName(Indexed annotation, Neo4jPersistentProperty property) {
final String providedIndexName = annotation.indexName().isEmpty() ? null : annotation.indexName();
final Class<?> declaringClass = property.getField().getDeclaringClass();
final Class<?> instanceType = property.getOwner().getType();
return Indexed.Name.get(annotation.level(), declaringClass, providedIndexName, instanceType);
}
public String getIndexName() {
return indexName;
}
public boolean isFulltext() {
return fulltext;
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
package org.springframework.data.neo4j.mapping;
import org.springframework.data.neo4j.core.EntityState;

View File

@@ -48,7 +48,7 @@ public interface Neo4jPersistentProperty extends PersistentProperty<Neo4jPersist
boolean isIndexed();
Neo4jPersistentPropertyImpl.IndexInfo getIndexInfo();
IndexInfo getIndexInfo();
String getNeo4jPropertyName();

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
package org.springframework.data.neo4j.mapping;
import org.neo4j.graphdb.Relationship;
@@ -25,7 +25,7 @@ public class RelationshipResult {
public final Relationship relationship;
public final Type type;
RelationshipResult(Relationship relationship, Type type) {
public RelationshipResult(Relationship relationship, Type type) {
this.relationship = relationship;
this.type = type;
}

View File

@@ -18,7 +18,7 @@ package org.springframework.data.neo4j.repository;
import org.neo4j.graphdb.PropertyContainer;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.Neo4jTemplate;

View File

@@ -19,7 +19,6 @@ import java.util.Iterator;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
@@ -38,7 +37,7 @@ class CypherQueryCreator extends AbstractQueryCreator<CypherQueryDefinition, Cyp
private final Class<?> domainClass;
/**
* Creates a new {@link CypherQueryCreator} using the given {@link PartTree}, {@link Neo4jMappingContext} and domain
* Creates a new {@link CypherQueryCreator} using the given {@link PartTree}, {@link org.springframework.data.neo4j.support.mapping.Neo4jMappingContext} and domain
* class.
*
* @param tree must not be {@literal null}.

View File

@@ -23,8 +23,9 @@ 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.mapping.EntityInstantiator;
import org.springframework.data.neo4j.support.index.IndexProvider;
import org.springframework.data.neo4j.support.mapping.*;
import org.springframework.data.neo4j.support.conversion.EntityResultConverter;
import org.springframework.data.neo4j.support.node.EntityStateFactory;
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
@@ -32,6 +33,7 @@ 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.data.neo4j.support.typerepresentation.TypeRepresentationStrategies;
import org.springframework.transaction.PlatformTransactionManager;
import javax.validation.Validator;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.data.neo4j.template;
package org.springframework.data.neo4j.support;
import org.neo4j.graphdb.NotFoundException;
import org.neo4j.graphdb.NotInTransactionException;

View File

@@ -32,12 +32,15 @@ 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.EntityPersister;
import org.springframework.data.neo4j.mapping.RelationshipResult;
import org.springframework.data.neo4j.support.mapping.EntityStateHandler;
import org.springframework.data.neo4j.support.mapping.Neo4jPersistentEntityImpl;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
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.query.QueryEngine;
import org.springframework.data.neo4j.template.GraphCallback;
import org.springframework.data.neo4j.template.Neo4jExceptionTranslator;
import org.springframework.data.neo4j.template.Neo4jOperations;
import org.springframework.data.util.TypeInformation;
import org.springframework.transaction.PlatformTransactionManager;
@@ -175,6 +178,12 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister {
return infrastructure.getEntityPersister().projectTo(entity, targetType);
}
/**
* just sets the persistent state (i.e. Node or id) to the entity, doesn't copy any values/properties.
* @param entity
* @param <S>
* @return
*/
@Override
public <S extends PropertyContainer> S getPersistentState(Object entity) {
notNull(entity,"entity");
@@ -193,12 +202,13 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister {
}
@Override
public void delete(Object entity) {
notNull(entity,"entity");
infrastructure.getEntityRemover().remove(entity);
public void delete(final Object entity) {
notNull(entity, "entity");
infrastructure.getEntityRemover().removeNodeEntity(entity);
}
public void removeNodeEntity(Object entity) {
public void removeNodeEntity(final Object entity) {
notNull(entity, "entity");
infrastructure.getEntityRemover().removeNodeEntity(entity);
}
@@ -418,7 +428,7 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister {
}
@Override
public QueryEngine queryEngineFor(QueryType type) {
public <T> QueryEngine<T> queryEngineFor(QueryType type) {
return infrastructure.getGraphDatabase().queryEngineFor(type, infrastructure.getResultConverter());
}
@@ -426,7 +436,8 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister {
@SuppressWarnings("unchecked")
public Result<Map<String, Object>> query(String statement, Map<String, Object> params) {
notNull(statement, "statement");
return queryEngineFor(QueryType.Cypher).query(statement, params);
final QueryEngine<Map<String,Object>> queryEngine = queryEngineFor(QueryType.Cypher);
return queryEngine.query(statement, params);
}
@Override
@@ -470,16 +481,23 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister {
}
@Override
public <T extends PropertyContainer> Result<T> lookup(final Class<?> indexedType, final Object query) {
notNull(query, "valueOrQueryObject", indexedType, "indexedType");
public <T extends PropertyContainer> Result<T> lookup(final Class<?> indexedType, String propertyName, final Object value) {
notNull(propertyName, "property name", indexedType, "indexedType",value,"query value");
try {
Index<T> index = getIndex(indexedType);
return convert(index.query(query));
final Neo4jPersistentEntityImpl<?> persistentEntity = getPersistentEntity(indexedType);
final Neo4jPersistentProperty property = persistentEntity.getPersistentProperty(propertyName);
final Index<T> index = infrastructure.getIndexProvider().getIndex(property, indexedType);
return convert(index.query(propertyName, value));
} catch (RuntimeException e) {
throw translateExceptionIfPossible(e);
}
}
private Neo4jPersistentEntityImpl<?> getPersistentEntity(Class<?> type) {
return infrastructure.getMappingContext().getPersistentEntity(type);
}
@Override
public <T extends PropertyContainer> Result<T> lookup(String indexName, Object query) {
notNull(query, "valueOrQueryObject", indexName, "indexName");
@@ -524,4 +542,11 @@ public class Neo4jTemplate implements Neo4jOperations, EntityPersister {
public GraphDatabase getGraphDatabase() {
return infrastructure.getGraphDatabase();
}
public String getIndexKey(Neo4jPersistentProperty property) {
return infrastructure.getIndexProvider().getIndexKey(property);
}
public <S extends PropertyContainer> Index<S> getIndex(Neo4jPersistentProperty property, final Class<?> instanceType) {
return infrastructure.getIndexProvider().getIndex(property, instanceType);
}
}

View File

@@ -1,41 +0,0 @@
/**
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
/**
* A simple class for holding a tuple of two typed elements. Useful for instance for map construction.
* Instantiated via the static factory method Tuple2._(v1,v2)
* @author Michael Hunger
* @since 11.09.2010
*/
public final class Tuple2<T1,T2> {
public final T1 _1;
public final T2 _2;
private Tuple2(T1 _1,T2 _2) {
this._1=_1;
this._2=_2;
}
public static <T1,T2> Tuple2<T1,T2> _(T1 _1, T2 _2) {
return new Tuple2<T1,T2>(_1,_2);
}
@Override
public String toString() {
return String.format("(%s,%s)",_1,_2);
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
package org.springframework.data.neo4j.support.index;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.PropertyContainer;
@@ -21,8 +21,9 @@ 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 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;
@@ -30,11 +31,11 @@ import static org.springframework.data.neo4j.support.ParameterCheck.notNull;
* @author mh
* @since 17.10.11
*/
class IndexProvider {
public class IndexProvider {
private Neo4jMappingContext mappingContext;
private final GraphDatabase graphDatabase;
IndexProvider(Neo4jMappingContext mappingContext, GraphDatabase graphDatabase) {
public IndexProvider(Neo4jMappingContext mappingContext, GraphDatabase graphDatabase) {
this.mappingContext = mappingContext;
this.graphDatabase = graphDatabase;
}
@@ -86,4 +87,24 @@ class IndexProvider {
public <T extends PropertyContainer> Index<T> createIndex(Class<T> type, String indexName, boolean fullText) {
return graphDatabase.createIndex(type, indexName, fullText);
}
public String getIndexKey(Neo4jPersistentProperty property) {
Indexed indexed = property.getAnnotation(Indexed.class);
if (indexed==null || indexed.fieldName().isEmpty()) return property.getNeo4jPropertyName();
return indexed.fieldName();
}
public <S extends PropertyContainer> Index<S> getIndex(Neo4jPersistentProperty property, final Class<?> instanceType) {
final Indexed indexedAnnotation = property.getAnnotation(Indexed.class);
final Class<?> declaringType = property.getOwner().getType();
final String providedIndexName = indexedAnnotation.indexName().isEmpty() ? null : indexedAnnotation.indexName();
String indexName = Indexed.Name.get(indexedAnnotation.level(), declaringType, providedIndexName, instanceType);
if (!property.getIndexInfo().isFulltext()) {
return getIndex(declaringType, indexName, false);
}
if (providedIndexName == null) throw new IllegalStateException("@Indexed(fullext=true) on "+property+" requires an providedIndexName too ");
String defaultIndexName = Indexed.Name.get(indexedAnnotation.level(), declaringType, null, instanceType.getClass());
if (providedIndexName.equals(defaultIndexName)) throw new IllegalStateException("Full-index name for "+property+" must differ from the default name: "+defaultIndexName);
return getIndex(declaringType, indexName, true);
}
}

View File

@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
package org.springframework.data.neo4j.support.mapping;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
import org.springframework.data.persistence.StateBackedCreator;
import org.springframework.data.persistence.StateProvider;
import org.springframework.util.ClassUtils;

View File

@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.springframework.data.neo4j.core.GraphDatabase;
import org.springframework.data.neo4j.core.TypeRepresentationStrategy;
import org.springframework.data.neo4j.mapping.RelationshipResult;
/**
* @author mh

View File

@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.*;
import org.springframework.data.neo4j.core.GraphDatabase;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntityImpl;
import org.springframework.data.neo4j.mapping.ManagedEntity;
import org.springframework.data.neo4j.mapping.RelationshipResult;
import org.springframework.data.neo4j.mapping.RelationshipProperties;
/**

View File

@@ -13,15 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.PropertyContainer;
import org.springframework.data.convert.DefaultTypeMapper;
import org.springframework.data.convert.TypeMapper;
import org.springframework.data.neo4j.core.TypeRepresentationStrategy;
import org.springframework.data.neo4j.mapping.ClassValueTypeInformationMapper;
import org.springframework.data.neo4j.mapping.SourceStateTransmitter;
import org.springframework.data.neo4j.mapping.TRSTypeAliasAccessor;
import org.springframework.data.neo4j.support.mapping.SourceStateTransmitter;
import org.springframework.data.neo4j.support.mapping.TRSTypeAliasAccessor;
import org.springframework.data.neo4j.support.typerepresentation.ClassValueTypeInformationMapper;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
import org.springframework.data.neo4j.support.node.EntityStateFactory;
import static java.util.Arrays.asList;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.data.neo4j.mapping;
package org.springframework.data.neo4j.support.mapping;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.mapping.Association;
@@ -25,6 +25,10 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.neo4j.annotation.*;
import org.springframework.data.neo4j.mapping.IndexInfo;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.mapping.RelationshipInfo;
import org.springframework.data.util.TypeInformation;
import java.beans.PropertyDescriptor;
@@ -35,7 +39,7 @@ import java.util.IdentityHashMap;
import java.util.Map;
/**
* Implementation of {@link Neo4jPersistentProperty}.
* Implementation of {@link org.springframework.data.neo4j.mapping.Neo4jPersistentProperty}.
*
* @author Oliver Gierke
*/
@@ -190,36 +194,6 @@ class Neo4jPersistentPropertyImpl extends AbstractPersistentProperty<Neo4jPersis
}
public static class IndexInfo {
private String indexName;
private boolean fulltext;
private final String fieldName;
private final Indexed.Level level;
public IndexInfo(Indexed annotation, Neo4jPersistentPropertyImpl property) {
this.indexName = determineIndexName(annotation,property);
this.fulltext = annotation.fulltext();
fieldName = annotation.fieldName();
level = annotation.level();
}
private String determineIndexName(Indexed annotation, Neo4jPersistentPropertyImpl property) {
final String providedIndexName = annotation.indexName().isEmpty() ? null : annotation.indexName();
final Class<?> declaringClass = property.getField().getDeclaringClass();
final Class<?> instanceType = property.getOwner().getType();
return Indexed.Name.get(annotation.level(), declaringClass, providedIndexName, instanceType);
}
public String getIndexName() {
return indexName;
}
public boolean isFulltext() {
return fulltext;
}
}
@Override
public String toString() {
return getType() +" "+ getName() + " rel: "+isRelationship()+ " idx: "+isIndexed();

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.mapping;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.PropertyContainer;
import org.springframework.core.convert.ConversionService;
@@ -23,10 +23,8 @@ import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.support.EntityStateHandler;
import org.springframework.data.neo4j.support.EntityTools;
import org.springframework.data.neo4j.support.ManagedEntity;
import org.springframework.data.neo4j.mapping.*;
import org.springframework.data.neo4j.mapping.ManagedEntity;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.mapping;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.PropertyContainer;
@@ -21,7 +21,8 @@ import org.neo4j.graphdb.Relationship;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.neo4j.annotation.Fetch;
import org.springframework.data.neo4j.support.EntityStateHandler;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import java.util.ArrayList;
import java.util.List;

View File

@@ -13,17 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.mapping;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.Relationship;
import org.springframework.core.convert.ConversionService;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.support.EntityStateHandler;
import org.springframework.data.neo4j.support.EntityTools;
import org.springframework.data.neo4j.support.ManagedEntity;
import org.springframework.data.neo4j.mapping.*;
import org.springframework.data.neo4j.mapping.ManagedEntity;
import java.util.HashMap;
import java.util.Map;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.data.neo4j.mapping;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.PropertyContainer;
import org.springframework.data.mapping.context.AbstractMappingContext;
@@ -23,6 +23,7 @@ import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.SimpleTypeHolder;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelationshipEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.util.TypeInformation;
import java.beans.PropertyDescriptor;
@@ -30,7 +31,7 @@ import java.lang.reflect.Field;
/**
* Neo4J specific {@link MappingContext} implementation. Simply creates {@link Neo4jPersistentEntityImpl} and
* {@link Neo4jPersistentProperty} instances.
* {@link org.springframework.data.neo4j.mapping.Neo4jPersistentProperty} instances.
*
* @author Oliver Gierke
*/

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.data.neo4j.mapping;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.PropertyContainer;
@@ -23,7 +23,10 @@ import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.neo4j.annotation.*;
import org.springframework.data.neo4j.support.ManagedEntity;
import org.springframework.data.neo4j.mapping.ManagedEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.mapping.RelationshipProperties;
import org.springframework.data.util.TypeInformation;
import java.lang.annotation.Annotation;
@@ -31,7 +34,7 @@ import java.util.IdentityHashMap;
import java.util.Map;
/**
* Implementation of {@link Neo4jPersistentEntity}.
* Implementation of {@link org.springframework.data.neo4j.mapping.Neo4jPersistentEntity}.
*
* @author Oliver Gierke
*/
@@ -165,6 +168,6 @@ public class Neo4jPersistentEntityImpl<T> extends BasicPersistentEntity<T, Neo4j
@Override
public String toString() {
return String.format("%s %smanaged @%sEntity Annotations: %s",getType(),isManaged() ? "" : "un", isNodeEntity() ? "Node":"Relationship",annotations.keySet());
return String.format("%s %smanaged @%sEntity Annotations: %s", getType(), isManaged() ? "" : "un", isNodeEntity() ? "Node" : "Relationship", annotations.keySet());
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.mapping;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.Transaction;
@@ -23,6 +23,8 @@ import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.neo4j.core.EntityState;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.DoReturn;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.node.EntityStateFactory;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.mapping;
package org.springframework.data.neo4j.support.mapping;
import org.neo4j.graphdb.PropertyContainer;
import org.springframework.data.convert.TypeAliasAccessor;

View File

@@ -17,8 +17,8 @@
package org.springframework.data.neo4j.support.node;
import org.neo4j.graphdb.Node;
import org.springframework.data.neo4j.support.AbstractConstructorEntityInstantiator;
import org.springframework.data.neo4j.support.EntityStateHandler;
import org.springframework.data.neo4j.support.mapping.AbstractConstructorEntityInstantiator;
import org.springframework.data.neo4j.support.mapping.EntityStateHandler;
/**

View File

@@ -22,9 +22,9 @@ import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.data.neo4j.fieldaccess.DefaultEntityState;
import org.springframework.data.neo4j.fieldaccess.DelegatingFieldAccessorFactory;
import org.springframework.data.neo4j.mapping.ManagedEntity;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.ManagedEntity;
/**
* @author Michael Hunger

View File

@@ -21,7 +21,7 @@ import org.springframework.data.neo4j.core.EntityState;
import org.springframework.data.neo4j.fieldaccess.DelegatingFieldAccessorFactory;
import org.springframework.data.neo4j.fieldaccess.DetachedEntityState;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.support.Neo4jTemplate;

View File

@@ -17,8 +17,8 @@
package org.springframework.data.neo4j.support.relationship;
import org.neo4j.graphdb.Relationship;
import org.springframework.data.neo4j.support.AbstractConstructorEntityInstantiator;
import org.springframework.data.neo4j.support.EntityStateHandler;
import org.springframework.data.neo4j.support.mapping.AbstractConstructorEntityInstantiator;
import org.springframework.data.neo4j.support.mapping.EntityStateHandler;
import sun.reflect.ReflectionFactory;
/**

View File

@@ -20,7 +20,7 @@ import org.neo4j.graphdb.Relationship;
import org.springframework.data.neo4j.core.EntityState;
import org.springframework.data.neo4j.fieldaccess.DelegatingFieldAccessorFactory;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.support.Neo4jTemplate;
import org.springframework.data.neo4j.support.node.EntityStateFactory;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.mapping;
package org.springframework.data.neo4j.support.typerepresentation;
import org.springframework.data.convert.TypeInformationMapper;
import org.springframework.data.util.ClassTypeInformation;

View File

@@ -27,7 +27,7 @@ import org.neo4j.helpers.collection.FilteringIterable;
import org.neo4j.helpers.collection.IterableWrapper;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.core.NodeTypeRepresentationStrategy;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
public class IndexingNodeTypeRepresentationStrategy implements NodeTypeRepresentationStrategy {

View File

@@ -28,7 +28,7 @@ import org.springframework.data.neo4j.annotation.RelationshipEntity;
import org.springframework.data.neo4j.core.RelationshipTypeRepresentationStrategy;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
public class IndexingRelationshipTypeRepresentationStrategy implements RelationshipTypeRepresentationStrategy {

View File

@@ -20,8 +20,7 @@ import org.neo4j.graphdb.Node;
import org.neo4j.helpers.collection.ClosableIterable;
import org.springframework.data.neo4j.core.NodeTypeRepresentationStrategy;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
public class NoopNodeTypeRepresentationStrategy implements NodeTypeRepresentationStrategy {

View File

@@ -20,7 +20,7 @@ import org.neo4j.graphdb.Relationship;
import org.neo4j.helpers.collection.ClosableIterable;
import org.springframework.data.neo4j.core.RelationshipTypeRepresentationStrategy;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
public class NoopRelationshipTypeRepresentationStrategy implements RelationshipTypeRepresentationStrategy {

View File

@@ -25,7 +25,7 @@ import org.neo4j.helpers.collection.CombiningIterable;
import org.neo4j.helpers.collection.IterableWrapper;
import org.neo4j.kernel.Traversal;
import org.springframework.data.neo4j.core.NodeTypeRepresentationStrategy;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
import java.util.Collections;
import java.util.LinkedList;

View File

@@ -13,14 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
package org.springframework.data.neo4j.support.typerepresentation;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.Relationship;
import org.neo4j.helpers.collection.ClosableIterable;
import org.springframework.data.neo4j.core.TypeRepresentationStrategy;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
/**
* @author mh
@@ -31,9 +31,9 @@ public class TypeRepresentationStrategies implements TypeRepresentationStrategy<
private final TypeRepresentationStrategy<Node> nodeTypeRepresentationStrategy;
private final TypeRepresentationStrategy<Relationship> relationshipTypeRepresentationStrategy;
TypeRepresentationStrategies(Neo4jMappingContext mappingContext,
TypeRepresentationStrategy<Node> nodeTypeRepresentationStrategy,
TypeRepresentationStrategy<Relationship> relationshipTypeRepresentationStrategy) {
public TypeRepresentationStrategies(Neo4jMappingContext mappingContext,
TypeRepresentationStrategy<Node> nodeTypeRepresentationStrategy,
TypeRepresentationStrategy<Relationship> relationshipTypeRepresentationStrategy) {
this.mappingContext = mappingContext;
this.nodeTypeRepresentationStrategy = nodeTypeRepresentationStrategy;
this.relationshipTypeRepresentationStrategy = relationshipTypeRepresentationStrategy;

View File

@@ -20,7 +20,7 @@ import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.springframework.data.neo4j.core.*;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.mapping.EntityInstantiator;
public class TypeRepresentationStrategyFactory {
private GraphDatabaseService graphDatabaseService;

View File

@@ -144,22 +144,23 @@ public interface Neo4jOperations {
*/
<T extends PropertyContainer> Result<T> lookup(String indexName, String field, Object value);
/**
* The value or query-object is looked up in the index indicated by the property of the indexed type, so all the customization
* via @Indexed annotations is taken into consideration. The resulting IndexHits are returned as a Result to be
* converted into Entities and other types.
*/
<T extends PropertyContainer> Result<T> lookup(Class<?> indexedType, String propertyName, Object value);
/**
* The query is executed on the index returning the IndexHits wrapped in a Result to be converted
* into Paths or Entities.
*/
<T extends PropertyContainer> Result<T> lookup(String indexName, Object query);
/**
* The query is executed on the index for this entity type returning the IndexHits wrapped in a Result to be converted
* into Paths or Entities.
*/
<T extends PropertyContainer> Result<T> lookup(Class<?> indexedType, Object query);
/**
* Provides a cypher or gremlin query engine set up with a default entity converter.
*/
QueryEngine queryEngineFor(QueryType type);
<T> QueryEngine<T> queryEngineFor(QueryType type);
/**
* Runs the given cypher statement and packages the result in a Result, simple conversions via the
@@ -239,7 +240,13 @@ public interface Neo4jOperations {
*/
<S extends PropertyContainer> S getPersistentState(Object entity);
/**
* @return a traversal description suited for the current mode of operation (aware of remote REST connections)
*/
TraversalDescription traversalDescription();
/**
* @return the graph database used by the template
*/
GraphDatabase getGraphDatabase();
}

View File

@@ -20,7 +20,6 @@ import org.mockito.Mockito;
import org.neo4j.graphdb.Node;
import org.springframework.data.neo4j.model.Friendship;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.support.ManagedEntity;
import static org.junit.Assert.assertEquals;

View File

@@ -18,6 +18,8 @@ package org.springframework.data.neo4j.mapping;
import org.junit.Before;
import org.junit.Test;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.mapping.Neo4jPersistentEntityImpl;
import static org.junit.Assert.assertEquals;

View File

@@ -31,10 +31,12 @@ import org.springframework.data.neo4j.fieldaccess.RelationshipDelegatingFieldAcc
import org.springframework.data.neo4j.model.Group;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.support.*;
import org.springframework.data.neo4j.support.mapping.*;
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
import org.springframework.data.neo4j.support.node.NodeEntityStateFactory;
import org.springframework.data.neo4j.support.relationship.RelationshipEntityInstantiator;
import org.springframework.data.neo4j.support.relationship.RelationshipEntityStateFactory;
import org.springframework.data.neo4j.support.typerepresentation.ClassValueTypeInformationMapper;
import org.springframework.data.neo4j.support.typerepresentation.NoopNodeTypeRepresentationStrategy;
import org.springframework.data.neo4j.support.typerepresentation.NoopRelationshipTypeRepresentationStrategy;

View File

@@ -23,7 +23,7 @@ import org.junit.Test;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
import org.springframework.data.repository.query.parser.Part;
/**

View File

@@ -25,7 +25,7 @@ import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
/**
* Unit tests for {@link MatchClause}.

View File

@@ -23,7 +23,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.data.mapping.PropertyPath;
import org.springframework.data.mapping.context.PersistentPropertyPath;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
/**

View File

@@ -16,30 +16,43 @@
package org.springframework.data.neo4j.support;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.neo4j.helpers.collection.MapUtil;
import org.neo4j.kernel.Traversal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.data.neo4j.annotation.QueryType;
import org.springframework.data.neo4j.conversion.EndResult;
import org.springframework.data.neo4j.conversion.Result;
import org.springframework.data.neo4j.mapping.ManagedEntity;
import org.springframework.data.neo4j.model.Friendship;
import org.springframework.data.neo4j.model.Group;
import org.springframework.data.neo4j.model.Named;
import org.springframework.data.neo4j.model.Person;
import org.springframework.data.neo4j.repository.GraphRepository;
import org.springframework.data.neo4j.support.query.QueryEngine;
import org.springframework.data.neo4j.template.Neo4jOperations;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import static org.junit.Assert.*;
import static org.neo4j.graphdb.Direction.OUTGOING;
import static org.neo4j.helpers.collection.IteratorUtil.asCollection;
import static org.neo4j.helpers.collection.MapUtil.map;
/**
* @author mh
@@ -47,89 +60,92 @@ import static org.neo4j.helpers.collection.IteratorUtil.asCollection;
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:template-config-context.xml"})
@Transactional
public class EntityNeo4jTemplateTest extends EntityTestBase {
public static final DynamicRelationshipType KNOWS = DynamicRelationshipType.withName("knows");
@Autowired
PlatformTransactionManager transactionManager;
private Neo4jOperations neo4jOperations;
@Before
public void setUp() throws Exception {
createTeam();
neo4jOperations = neo4jTemplate;
}
@Test
@Test @Transactional
public void testRepositoryFor() throws Exception {
final GraphRepository<Person> personRepository = neo4jTemplate.repositoryFor(Person.class);
final GraphRepository<Group> groupRepository = neo4jTemplate.repositoryFor(Group.class);
final GraphRepository<Friendship> friendshipRepository = neo4jTemplate.repositoryFor(Friendship.class);
final GraphRepository<Person> personRepository = neo4jOperations.repositoryFor(Person.class);
final GraphRepository<Group> groupRepository = neo4jOperations.repositoryFor(Group.class);
final GraphRepository<Friendship> friendshipRepository = neo4jOperations.repositoryFor(Friendship.class);
testTeam.createSDGTeam(personRepository,groupRepository,friendshipRepository);
final Person found = personRepository.findOne(testTeam.michael.getId());
assertEquals(found.getId(),testTeam.michael.getId());
}
@Test
@Test @Transactional
public void testRelationshipRepositoryFor() throws Exception {
final GraphRepository<Friendship> friendshipRepository = neo4jTemplate.repositoryFor(Friendship.class);
final GraphRepository<Friendship> friendshipRepository = neo4jOperations.repositoryFor(Friendship.class);
final Friendship found = friendshipRepository.findOne(testTeam.friendShip.getId());
assertEquals(found.getId(),testTeam.friendShip.getId());
}
@Test
@Test @Transactional
public void testGetIndexForType() throws Exception {
final Index<PropertyContainer> personIndex = neo4jTemplate.getIndex(Person.class);
assertEquals("Person",personIndex.getName());
}
@Test
@Test @Transactional
public void testGetIndexForName() throws Exception {
final Index<PropertyContainer> nameIndex = neo4jTemplate.getIndex(Person.NAME_INDEX);
assertEquals(Person.NAME_INDEX, nameIndex.getName());
}
@Test
@Test @Transactional
public void testGetIndexForNoTypeAndName() throws Exception {
final Index<PropertyContainer> nameIndex = neo4jTemplate.getIndex(null,Person.NAME_INDEX);
final Index<PropertyContainer> nameIndex = neo4jOperations.getIndex(null,Person.NAME_INDEX);
assertEquals(Person.NAME_INDEX,nameIndex.getName());
}
@Test
@Test @Transactional
public void testGetIndexForTypeAndNoName() throws Exception {
final Index<PropertyContainer> nameIndex = neo4jTemplate.getIndex(Person.class,null);
final Index<PropertyContainer> nameIndex = neo4jOperations.getIndex(Person.class,null);
assertEquals("Person",nameIndex.getName());
}
@Test
@Test @Transactional
public void testGetIndexForTypeAndName() throws Exception {
final Index<PropertyContainer> nameIndex = neo4jTemplate.getIndex(Person.class,Person.NAME_INDEX);
final Index<PropertyContainer> nameIndex = neo4jOperations.getIndex(Person.class,Person.NAME_INDEX);
assertEquals(Person.NAME_INDEX, nameIndex.getName());
}
@Test
@Test @Transactional
public void testFindOne() throws Exception {
final Person found = neo4jTemplate.findOne(testTeam.michael.getId(), Person.class);
final Person found = neo4jOperations.findOne(testTeam.michael.getId(), Person.class);
assertEquals(found.getId(),testTeam.michael.getId());
}
@Test
@Test @Transactional
public void testFindAll() throws Exception {
final Collection<Person> people = asCollection(neo4jTemplate.findAll(Person.class));
final Collection<Person> people = asCollection(neo4jOperations.findAll(Person.class));
assertEquals(3,people.size());
}
@Test
@Test @Transactional
public void testCount() throws Exception {
assertEquals(3,neo4jTemplate.count(Person.class));
assertEquals(3,neo4jOperations.count(Person.class));
}
@Test
@Test @Transactional
public void testCreateRelationshipEntityFromStoredType() throws Exception {
final Relationship friendshipRelationship = getRelationshipState(testTeam.friendShip);
@@ -137,7 +153,7 @@ public class EntityNeo4jTemplateTest extends EntityTestBase {
assertEquals(testTeam.friendShip.getId(),found.getId());
}
@Test
@Test @Transactional
public void testCreateNodeEntityFromStoredType() throws Exception {
final Node michaelNode = getNodeState(testTeam.michael);
@@ -145,7 +161,7 @@ public class EntityNeo4jTemplateTest extends EntityTestBase {
assertEquals(testTeam.michael.getId(),found.getId());
}
@Test
@Test @Transactional
public void testCreateEntityFromState() throws Exception {
final PropertyContainer michaelNode = getNodeState(testTeam.michael);
@@ -153,162 +169,196 @@ public class EntityNeo4jTemplateTest extends EntityTestBase {
assertEquals(testTeam.michael.getId(),found.getId());
}
@Test
@Test @Transactional
public void testProjectTo() throws Exception {
final Named named = neo4jTemplate.projectTo(testTeam.sdg, Named.class);
final Named named = neo4jOperations.projectTo(testTeam.sdg, Named.class);
assertEquals(testTeam.sdg.getName(),named.getName());
}
@Test
@Test @Transactional
public void testGetPersistentState() throws Exception {
assertEquals(testTeam.michael.getId(),(Long)((Node)neo4jTemplate.getPersistentState(testTeam.michael)).getId());
assertEquals(testTeam.michael.getId(),(Long)((Node)neo4jOperations.getPersistentState(testTeam.michael)).getId());
}
@Test
@Test @Transactional
public void testSetPersistentState() throws Exception {
final Person clone = new Person();
neo4jTemplate.setPersistentState(clone, neo4jOperations.getPersistentState(testTeam.david));
assertEquals(testTeam.david.getId(), clone.getId());
}
@Test
@Ignore("TODO execute non tx")
@Test(expected = DataRetrievalFailureException.class)
public void testDelete() throws Exception {
final Long id = testTeam.michael.getId();
neo4jTemplate.delete(testTeam.michael);
assertNull(neo4jTemplate.getGraphDatabase().getNodeById(id));
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
neo4jOperations.delete(testTeam.michael);
}
});
assertNull(neo4jOperations.getNode(id));
}
@Test
@Ignore("TODO execute non tx")
@Test(expected = DataRetrievalFailureException.class)
public void testRemoveNodeEntity() throws Exception {
final Long id = testTeam.michael.getId();
neo4jTemplate.removeNodeEntity(testTeam.michael);
assertNull(neo4jTemplate.getGraphDatabase().getNodeById(id));
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
neo4jTemplate.removeNodeEntity(testTeam.michael);
}
});
assertNull(neo4jOperations.getNode(id));
}
@Test
@Ignore("TODO execute non tx")
@Test(expected = DataRetrievalFailureException.class)
public void testRemoveRelationshipEntity() throws Exception {
final Long id = testTeam.friendShip.getId();
neo4jTemplate.removeRelationshipEntity(testTeam.friendShip);
assertNull(neo4jTemplate.getGraphDatabase().getRelationshipById(id));
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
neo4jTemplate.removeRelationshipEntity(testTeam.friendShip);
}
});
assertNull(neo4jOperations.getRelationship(id));
}
@Test
@Test @Transactional
public void testCreateNodeAs() throws Exception {
final Person thomas = neo4jOperations.createNodeAs(Person.class, map("name", "Thomas"));
assertEquals("Thomas",neo4jOperations.getNode(thomas.getId()).getProperty("name"));
final Person found = neo4jTemplate.createEntityFromStoredType(getNodeState(thomas));
assertEquals("Thomas",found.getName());
}
@Test
@Test @Transactional
public void testIsNodeEntity() throws Exception {
assertEquals(true,neo4jTemplate.isNodeEntity(Person.class));
assertEquals(false,neo4jTemplate.isNodeEntity(Friendship.class));
assertEquals(false,neo4jTemplate.isNodeEntity(Object.class));
}
@Test
@Test @Transactional
public void testIsRelationshipEntity() throws Exception {
assertEquals(true,neo4jTemplate.isRelationshipEntity(Friendship.class));
assertEquals(false,neo4jTemplate.isRelationshipEntity(Person.class));
assertEquals(false,neo4jTemplate.isRelationshipEntity(Object.class));
}
@Test
@Test @Transactional
public void testSave() throws Exception {
final Person thomas = new Person("Thomas", 30);
neo4jOperations.save(thomas);
final Node node = getNodeState(thomas);
assertNotNull("created node",node);
assertEquals("created node with id", (Long) node.getId(), thomas.getId());
assertEquals("created node with name", "Thomas", node.getProperty("name"));
}
@Test
static abstract class ManagedTestEntity implements ManagedEntity {}
@Test @Transactional
public void testIsManaged() throws Exception {
assertEquals(true,neo4jTemplate.isManaged(Mockito.mock(ManagedEntity.class)));
assertEquals(true,neo4jTemplate.isManaged(Mockito.mock(ManagedTestEntity.class)));
assertEquals(false,neo4jTemplate.isManaged(testTeam.michael));
assertEquals(false,neo4jTemplate.isManaged(testTeam.friendShip));
assertEquals(false,neo4jTemplate.isManaged(new Object()));
}
@Test
@Test @Transactional
public void testQuery() throws Exception {
final Person result = neo4jOperations.query("start n=node({self}) return n", map("self", testTeam.michael.getId())).to(Person.class).single();
assertEquals(testTeam.michael.getId(),result.getId());
}
@Test
@Test @Transactional
public void testGetRelationshipBetweenNodes() throws Exception {
final Relationship knows = neo4jTemplate.getRelationshipBetween(getNodeState(testTeam.michael), getNodeState(testTeam.david), "knows");
final Relationship knows = neo4jOperations.getRelationshipBetween(getNodeState(testTeam.michael), getNodeState(testTeam.david), "knows");
assertEquals(testTeam.friendShip.getId(),(Long)knows.getId());
}
@Test
@Test @Transactional
public void testGetAutoPersistedRelationshipBetweenNodes() throws Exception {
final Node emilNode = getNodeState(testTeam.emil);
final Node michaelNode = getNodeState(testTeam.michael);
final Relationship boss = neo4jTemplate.getRelationshipBetween(emilNode, michaelNode, "boss");
final Relationship boss = neo4jOperations.getRelationshipBetween(emilNode, michaelNode, "boss");
assertNotNull("found relationship",boss);
assertEquals(michaelNode,boss.getEndNode());
assertEquals(emilNode,boss.getStartNode());
}
@Test
@Test @Transactional
public void testGetRelationshipBetween() throws Exception {
final Friendship knows = neo4jTemplate.getRelationshipBetween(testTeam.michael, testTeam.david, Friendship.class, "knows");
final Friendship knows = neo4jOperations.getRelationshipBetween(testTeam.michael, testTeam.david, Friendship.class, "knows");
assertEquals(testTeam.friendShip.getId(),knows.getId());
}
@Test
@Test @Transactional
public void testDeleteRelationshipBetween() throws Exception {
neo4jTemplate.deleteRelationshipBetween(testTeam.michael,testTeam.david,"knows");
neo4jOperations.deleteRelationshipBetween(testTeam.michael,testTeam.david,"knows");
assertNull("relationship deleted", getNodeState(testTeam.michael).getSingleRelationship(KNOWS, OUTGOING));
}
@Test
@Test @Transactional
public void testCreateRelationshipBetweenNodes() throws Exception {
final Friendship friendship = neo4jTemplate.createRelationshipBetween(testTeam.david, testTeam.emil, Friendship.class, "knows", false);
final Friendship friendship = neo4jOperations.createRelationshipBetween(testTeam.david, testTeam.emil, Friendship.class, "knows", false);
assertEquals(friendship.getId(),(Long)getNodeState(testTeam.david).getSingleRelationship(KNOWS, OUTGOING).getId());
}
@Test
@Test @Transactional
public void testCreateDuplicateRelationshipBetweenNodes() throws Exception {
neo4jTemplate.createRelationshipBetween(testTeam.michael, testTeam.david, Friendship.class, "knows", true);
neo4jOperations.createRelationshipBetween(testTeam.michael, testTeam.david, Friendship.class, "knows", true);
assertEquals(2, asCollection(getNodeState(testTeam.michael).getRelationships(KNOWS, OUTGOING)).size());
}
@Test
@Test @Transactional
public void testCreateRelationshipBetween() throws Exception {
final Node davidNode = getNodeState(testTeam.david);
final Relationship friendship = neo4jTemplate.createRelationshipBetween(davidNode, getNodeState(testTeam.emil), "knows", MapUtil.map("years", 10));
final Relationship friendship = neo4jOperations.createRelationshipBetween(davidNode, getNodeState(testTeam.emil), "knows", MapUtil.map("years", 10));
assertEquals(friendship.getId(),davidNode.getSingleRelationship(KNOWS, OUTGOING).getId());
assertEquals(10,friendship.getProperty("years"));
}
@Test
@Test @Transactional
public void testConvertSingle() throws Exception {
final Person p = neo4jTemplate.convert(neo4jTemplate.getPersistentState(testTeam.michael), Person.class);
final Person p = neo4jOperations.convert(neo4jOperations.getPersistentState(testTeam.michael), Person.class);
assertEquals(testTeam.michael.getName(),p.getName());
}
@Test
@Test @Transactional
public void testConvert() throws Exception {
final EndResult<Group> groups = neo4jTemplate.convert(Arrays.asList(getNodeState(testTeam.sdg))).to(Group.class);
final EndResult<Group> groups = neo4jOperations.convert(Arrays.asList(getNodeState(testTeam.sdg))).to(Group.class);
assertEquals(testTeam.sdg.getName(),groups.iterator().next().getName());
}
@Test
public void testQueryEngineFor() throws Exception {
@Test @Transactional
public void testQueryEngineForCypher() throws Exception {
final QueryEngine<Result<Map<String,Object>>> engine = neo4jOperations.queryEngineFor(QueryType.Cypher);
final Person result = engine.query("start n=node({self}) return n", map("self", testTeam.michael.getId())).to(Person.class).single();
assertEquals(testTeam.michael.getId(), result.getId());
}
@Test @Transactional
public void testQueryEngineForGremlin() throws Exception {
final QueryEngine<Result<Object>> engine = neo4jOperations.queryEngineFor(QueryType.Gremlin);
final Person result = engine.query("g.v(self)", map("self", testTeam.michael.getId())).to(Person.class).single();
assertEquals(testTeam.michael.getId(), result.getId());
}
@Test
@Test @Transactional
public void testTraverse() throws Exception {
final TraversalDescription traversalDescription = neo4jTemplate.traversalDescription().relationships(DynamicRelationshipType.withName("knows"), Direction.OUTGOING).filter(Traversal.returnAllButStartNode());
final Person knows = neo4jTemplate.traverse(testTeam.michael, traversalDescription).to(Person.class).single();
final TraversalDescription traversalDescription = neo4jOperations.traversalDescription().relationships(DynamicRelationshipType.withName("knows"), Direction.OUTGOING).filter(Traversal.returnAllButStartNode());
final Person knows = neo4jOperations.traverse(testTeam.michael, traversalDescription).to(Person.class).single();
assertEquals(testTeam.david.getName(), knows.getName());
}
@Test
@Test @Transactional
public void testLookup() throws Exception {
final Person found = neo4jOperations.lookup(Person.class, "name","name:Michael").to(Person.class).single();
assertEquals(testTeam.michael.getId(),found.getId());
}
@Test @Transactional
public void testLookupExact() throws Exception {
final Person found = neo4jOperations.lookup(Person.class, "name","Michael").to(Person.class).single();
assertEquals(testTeam.michael.getId(),found.getId());
}
}