started merging GraphDatabaseContext and Neo4jTemplate, unifying methods and conversion approach.
Renamed QueryResult to Result, ConvertedResult to EndResult More advanced index-check handling in GDC.IndexProvider Removed DirectGraphDatabaseRepositoryFactory in favor of gdc.repositoryFor()
This commit is contained in:
@@ -16,13 +16,9 @@
|
||||
|
||||
package org.springframework.data.neo4j.aspects.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.aspects.Developer;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@@ -35,11 +31,6 @@ import static org.junit.Assert.assertNull;
|
||||
|
||||
public class AttachEntityTest extends EntityTestBase {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@Autowired
|
||||
private DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void entityShouldHaveNoNode() {
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.neo4j.aspects.FriendshipRepository;
|
||||
import org.springframework.data.neo4j.aspects.GroupRepository;
|
||||
import org.springframework.data.neo4j.aspects.PersonRepository;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
@@ -45,8 +44,6 @@ public class EntityTestBase {
|
||||
|
||||
@Autowired protected GraphDatabaseService graphDatabaseService;
|
||||
|
||||
@Autowired protected DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
|
||||
@Autowired protected PersonRepository personRepository;
|
||||
@Autowired protected GroupRepository groupRepository;
|
||||
@Autowired protected FriendshipRepository friendshipRepository;
|
||||
|
||||
@@ -39,7 +39,6 @@ import static org.neo4j.helpers.collection.IteratorUtil.asCollection;
|
||||
import static org.springframework.data.neo4j.aspects.Person.persistedPerson;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
//@ContextConfiguration(locations = {"classpath:repository-namespace-config-context.xml"})
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTest-context.xml"})
|
||||
public class FinderTest extends EntityTestBase {
|
||||
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
|
||||
package org.springframework.data.neo4j.aspects.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.DynamicRelationshipType;
|
||||
@@ -28,17 +25,15 @@ import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.aspects.*;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.aspects.Friendship;
|
||||
import org.springframework.data.neo4j.aspects.Group;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.aspects.SubGroup;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -57,28 +52,6 @@ public class IndexTest extends EntityTestBase {
|
||||
private static final String NAME_VALUE = "aName";
|
||||
private static final String NAME_VALUE2 = "aSecondName";
|
||||
private static final String NAME_VALUE3 = "aThirdName";
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
@Autowired
|
||||
private DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
protected GraphRepository<Group> groupFinder;
|
||||
protected GraphRepository<Person> personFinder;
|
||||
@Autowired protected PersonRepository personRepository;
|
||||
@Autowired protected GroupRepository groupRepository;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
groupFinder = graphRepositoryFactory.createGraphRepository(Group.class);
|
||||
personFinder = graphRepositoryFactory.createGraphRepository(Person.class);
|
||||
}
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@@ -87,7 +60,7 @@ public class IndexTest extends EntityTestBase {
|
||||
Person p2 = persistedPerson(NAME_VALUE2, 25);
|
||||
Friendship friendship = p.knows(p2);
|
||||
friendship.setYears(1);
|
||||
GraphRepository<Friendship> friendshipFinder = graphRepositoryFactory.createGraphRepository(Friendship.class);
|
||||
GraphRepository<Friendship> friendshipFinder = graphDatabaseContext.repositoryFor(Friendship.class);
|
||||
assertEquals(friendship, friendshipFinder.findByPropertyValue("Friendship.years", 1));
|
||||
}
|
||||
|
||||
@@ -114,7 +87,7 @@ public class IndexTest extends EntityTestBase {
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
final Group found = groupFinder.findByPropertyValue( NAME, NAME_VALUE);
|
||||
final Group found = this.groupRepository.findByPropertyValue(NAME, NAME_VALUE);
|
||||
assertNull("Group.name removed from index", found);
|
||||
}
|
||||
|
||||
@@ -131,7 +104,7 @@ public class IndexTest extends EntityTestBase {
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
final Group found = groupFinder.findByPropertyValue( NAME, NAME_VALUE);
|
||||
final Group found = this.groupRepository.findByPropertyValue(NAME, NAME_VALUE);
|
||||
assertNull("Group.name removed from index", found);
|
||||
}
|
||||
|
||||
@@ -144,7 +117,7 @@ public class IndexTest extends EntityTestBase {
|
||||
public void testFindGroupByIndex() {
|
||||
Group group = persist(new Group());
|
||||
group.setName(NAME_VALUE);
|
||||
final Group found = groupFinder.findByPropertyValue(NAME, NAME_VALUE);
|
||||
final Group found = this.groupRepository.findByPropertyValue(NAME, NAME_VALUE);
|
||||
assertEquals(group, found);
|
||||
}
|
||||
|
||||
@@ -164,7 +137,7 @@ public class IndexTest extends EntityTestBase {
|
||||
public void testFindGroupByAlternativeFieldNameIndex() {
|
||||
Group group = persist(new Group());
|
||||
group.setOtherName(NAME_VALUE);
|
||||
final Group found = groupFinder.findByPropertyValue(Group.OTHER_NAME_INDEX, NAME_VALUE);
|
||||
final Group found = this.groupRepository.findByPropertyValue(Group.OTHER_NAME_INDEX, NAME_VALUE);
|
||||
assertEquals(group, found);
|
||||
}
|
||||
|
||||
@@ -177,18 +150,10 @@ public class IndexTest extends EntityTestBase {
|
||||
@Indexed(fulltext = true, indexName = "InvalidIndexed")
|
||||
String fullTextDefaultIndexName;
|
||||
|
||||
public String getFulltextNoIndexName() {
|
||||
return fulltextNoIndexName;
|
||||
}
|
||||
|
||||
public void setFulltextNoIndexName(String fulltextNoIndexName) {
|
||||
this.fulltextNoIndexName = fulltextNoIndexName;
|
||||
}
|
||||
|
||||
public String getFullTextDefaultIndexName() {
|
||||
return fullTextDefaultIndexName;
|
||||
}
|
||||
|
||||
public void setFullTextDefaultIndexName(String fullTextDefaultIndexName) {
|
||||
this.fullTextDefaultIndexName = fullTextDefaultIndexName;
|
||||
}
|
||||
@@ -215,7 +180,7 @@ public class IndexTest extends EntityTestBase {
|
||||
public void testDontFindGroupByNonIndexedFieldWithAnnotation() {
|
||||
Group group = persist(new Group());
|
||||
group.setUnindexedName("value-unindexedName");
|
||||
final Group found = groupFinder.findByPropertyValue("unindexedName", "value-unindexedName");
|
||||
final Group found = this.groupRepository.findByPropertyValue("unindexedName", "value-unindexedName");
|
||||
assertNull(found);
|
||||
}
|
||||
|
||||
@@ -224,7 +189,7 @@ public class IndexTest extends EntityTestBase {
|
||||
public void testDontFindGroupByNonIndexedField() {
|
||||
Group group = persist(new Group());
|
||||
group.setUnindexedName2("value-unindexedName2");
|
||||
final Group found = groupFinder.findByPropertyValue( "unindexedName2", "value-unindexedName2");
|
||||
final Group found = this.groupRepository.findByPropertyValue("unindexedName2", "value-unindexedName2");
|
||||
assertNull(found);
|
||||
}
|
||||
|
||||
@@ -235,7 +200,7 @@ public class IndexTest extends EntityTestBase {
|
||||
group.setName(NAME_VALUE);
|
||||
Group group2 = persist(new Group());
|
||||
group2.setName(NAME_VALUE);
|
||||
final Iterable<Group> found = groupFinder.findAllByPropertyValue(NAME, NAME_VALUE);
|
||||
final Iterable<Group> found = this.groupRepository.findAllByPropertyValue(NAME, NAME_VALUE);
|
||||
final Collection<Group> result = IteratorUtil.addToCollection(found.iterator(), new HashSet<Group>());
|
||||
assertEquals(new HashSet<Group>(Arrays.asList(group, group2)), result);
|
||||
}
|
||||
@@ -261,7 +226,7 @@ public class IndexTest extends EntityTestBase {
|
||||
@Test
|
||||
public void findsPersonByIndexOnAnnotatedIntFieldInSeparateTransactions() {
|
||||
Person person = persistedPerson(NAME_VALUE, 35);
|
||||
final Person found = personFinder.findByPropertyValue("age", 35);
|
||||
final Person found = this.personRepository.findByPropertyValue("age", 35);
|
||||
assertEquals("person found inside range", person, found);
|
||||
}
|
||||
|
||||
@@ -269,15 +234,15 @@ public class IndexTest extends EntityTestBase {
|
||||
@Transactional
|
||||
public void testRangeQueryPersonByIndexOnAnnotatedField() {
|
||||
Person person = persistedPerson(NAME_VALUE, 35);
|
||||
final Person found = personFinder.findAllByRange("age", 10, 40).iterator().next();
|
||||
final Person found = this.personRepository.findAllByRange("age", 10, 40).iterator().next();
|
||||
assertEquals("person found inside range", person, found);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testOutsideRangeQueryPersonByIndexOnAnnotatedField() {
|
||||
Person person = persistedPerson(NAME_VALUE, 35);
|
||||
Iterable<Person> emptyResult = personFinder.findAllByRange("age", 0, 34);
|
||||
persistedPerson(NAME_VALUE, 35);
|
||||
Iterable<Person> emptyResult = this.personRepository.findAllByRange("age", 0, 34);
|
||||
assertFalse("nothing found outside range", emptyResult.iterator().hasNext());
|
||||
}
|
||||
|
||||
@@ -287,7 +252,7 @@ public class IndexTest extends EntityTestBase {
|
||||
public void testFindAllPersonByIndexOnAnnotatedFieldWithAtIndexed() {
|
||||
Person person = persistedPerson(NAME_VALUE, 35);
|
||||
person.setNickname("Mike");
|
||||
final Person found = personFinder.findByPropertyValue( "nickname", "Mike");
|
||||
final Person found = this.personRepository.findByPropertyValue("nickname", "Mike");
|
||||
assertEquals(person, found);
|
||||
}
|
||||
|
||||
@@ -320,7 +285,7 @@ public class IndexTest extends EntityTestBase {
|
||||
p = persistedPerson(NAME_VALUE2, 30);
|
||||
tx.success();
|
||||
} finally {
|
||||
tx.finish();
|
||||
if (tx != null) tx.finish();
|
||||
}
|
||||
Assert.assertEquals(p, personRepository.findByPropertyValue(NAME_INDEX, "name", NAME_VALUE2));
|
||||
try {
|
||||
|
||||
@@ -16,22 +16,16 @@
|
||||
|
||||
package org.springframework.data.neo4j.aspects.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.NotInTransactionException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.aspects.Friendship;
|
||||
import org.springframework.data.neo4j.aspects.Group;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@@ -48,17 +42,9 @@ import static org.springframework.data.neo4j.aspects.support.HasRelationshipMatc
|
||||
@ContextConfiguration( locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTest-context.xml"} )
|
||||
public class ModificationOutsideOfTransactionTest extends EntityTestBase {
|
||||
|
||||
protected final Log log = LogFactory.getLog( getClass() );
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
@Autowired
|
||||
private DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
|
||||
@Before
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseContext);
|
||||
public void cleanUp() {
|
||||
manualCleanDb();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -248,7 +234,7 @@ public class ModificationOutsideOfTransactionTest extends EntityTestBase {
|
||||
@Test
|
||||
public void testFindOutsideTransaction()
|
||||
{
|
||||
final GraphRepository<Person> finder = graphRepositoryFactory.createGraphRepository(Person.class);
|
||||
final GraphRepository<Person> finder = graphDatabaseContext.repositoryFor(Person.class);
|
||||
assertEquals( false, finder.findAll().iterator().hasNext() );
|
||||
}
|
||||
|
||||
|
||||
@@ -16,23 +16,16 @@
|
||||
|
||||
package org.springframework.data.neo4j.aspects.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -45,20 +38,7 @@ import static org.springframework.data.neo4j.aspects.Person.persistedPerson;
|
||||
"classpath:org/springframework/data/neo4j/aspects/support/PersonDirectCreator-context.xml" })
|
||||
@TestExecutionListeners({CleanContextCacheTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, TransactionalTestExecutionListener.class})
|
||||
|
||||
public class NodeEntityInstantiationTest extends EntityTestBase {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
@Autowired
|
||||
private DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseContext);
|
||||
}
|
||||
public class NodeEntityInstantiationTest extends EntityTestBase {
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@@ -72,7 +52,7 @@ import static org.springframework.data.neo4j.aspects.Person.persistedPerson;
|
||||
Person person2 = graphDatabaseContext.createEntityFromState(node,Person.class);
|
||||
assertEquals("Rod", person2.getName());
|
||||
|
||||
GraphRepository<Person> finder = graphRepositoryFactory.createGraphRepository(Person.class);
|
||||
GraphRepository<Person> finder = graphDatabaseContext.repositoryFor(Person.class);
|
||||
Person found = finder.findOne(nodeId);
|
||||
assertEquals("Rod", found.getName());
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.aspects.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -26,17 +24,12 @@ import org.neo4j.graphdb.DynamicRelationshipType;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.neo4j.aspects.Friendship;
|
||||
import org.springframework.data.neo4j.aspects.Group;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
@@ -50,19 +43,6 @@ import static org.springframework.data.neo4j.aspects.Person.persistedPerson;
|
||||
|
||||
public class NodeEntityRelationshipTest extends EntityTestBase {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
@Autowired
|
||||
private DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateRelationshipWithoutAnnotationOnSet() {
|
||||
|
||||
@@ -16,22 +16,15 @@
|
||||
|
||||
package org.springframework.data.neo4j.aspects.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.NotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.aspects.Friendship;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.aspects.Personality;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.annotation.Rollback;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Date;
|
||||
@@ -44,18 +37,6 @@ import static org.springframework.data.neo4j.aspects.Person.persistedPerson;
|
||||
|
||||
public class PropertyTest extends EntityTestBase {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
@Autowired
|
||||
private DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseContext);
|
||||
}
|
||||
@Test
|
||||
@Transactional
|
||||
public void testSetPropertyEnum() {
|
||||
|
||||
@@ -16,22 +16,17 @@
|
||||
|
||||
package org.springframework.data.neo4j.aspects.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.DynamicRelationshipType;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.aspects.Friendship;
|
||||
import org.springframework.data.neo4j.aspects.FriendshipRepository;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -43,23 +38,6 @@ import static org.springframework.data.neo4j.aspects.Person.persistedPerson;
|
||||
|
||||
public class RelationshipEntityTest extends EntityTestBase {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
@Autowired
|
||||
private GraphDatabaseContext graphDatabaseContext;
|
||||
@Autowired
|
||||
private GraphDatabaseService graphDatabaseService;
|
||||
@Autowired
|
||||
private FriendshipRepository friendshipRepository;
|
||||
|
||||
@Autowired
|
||||
private DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testRelationshipCreate() {
|
||||
|
||||
@@ -69,7 +69,7 @@ public class TraversalTest extends EntityTestBase {
|
||||
group.setName("dev");
|
||||
group.addPerson(p);
|
||||
final TraversalDescription traversalDescription = Traversal.description().relationships(DynamicRelationshipType.withName("persons"), Direction.OUTGOING).evaluator(Evaluators.excludeStartPosition());
|
||||
Iterable<EntityPath<Group,Person>> paths = graphDatabaseContext.<EntityPath<Group,Person>>findAllByTraversal(group, EntityPath.class, traversalDescription);
|
||||
Iterable<EntityPath<Group,Person>> paths = (Iterable<EntityPath<Group, Person>>) graphDatabaseContext.<EntityPath<Group,Person>>findAllByTraversal(group, EntityPath.class, traversalDescription);
|
||||
for (EntityPath<Group, Person> path : paths) {
|
||||
assertEquals(group, path.startEntity());
|
||||
assertEquals(p, path.endEntity());
|
||||
@@ -107,7 +107,7 @@ public class TraversalTest extends EntityTestBase {
|
||||
@Test
|
||||
@Transactional
|
||||
public void testTraverseFromGroupToPeopleWithFinder() {
|
||||
final GraphRepository<Person> finder = graphRepositoryFactory.createGraphRepository(Person.class);
|
||||
final GraphRepository<Person> finder = graphDatabaseContext.repositoryFor(Person.class);
|
||||
Person p = persistedPerson("Michael", 35);
|
||||
Group group = persist(new Group());
|
||||
group.setName("dev");
|
||||
|
||||
@@ -28,7 +28,7 @@ import org.springframework.data.neo4j.annotation.QueryType;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.aspects.Personality;
|
||||
import org.springframework.data.neo4j.aspects.support.EntityTestBase;
|
||||
import org.springframework.data.neo4j.conversion.QueryResult;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
import org.springframework.data.neo4j.conversion.ResultConverter;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.support.DelegatingGraphDatabase;
|
||||
@@ -87,7 +87,7 @@ public class QueryEngineTest extends EntityTestBase {
|
||||
@Test
|
||||
public void testQueryListOfTypeNode() throws Exception {
|
||||
final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss";
|
||||
final QueryResult<Map<String,Object>> queryResult = queryEngine.query(queryString, michaelsName());
|
||||
final Result<Map<String,Object>> queryResult = queryEngine.query(queryString, michaelsName());
|
||||
final Collection<Node> result = IteratorUtil.asCollection(queryResult.to(Node.class));
|
||||
|
||||
assertEquals(asList(getNodeState(testTeam.emil)),result);
|
||||
|
||||
@@ -172,7 +172,7 @@ public class SubReferenceNodeTypeRepresentationStrategyTest extends EntityTestBa
|
||||
public void testInstantiateConcreteClassWithFinder() {
|
||||
log.debug("testInstantiateConcreteClassWithFinder");
|
||||
Volvo v = persist(new Volvo());
|
||||
GraphRepository<Car> finder = graphRepositoryFactory.createGraphRepository(Car.class);
|
||||
GraphRepository<Car> finder = graphDatabaseContext.repositoryFor(Car.class);
|
||||
assertEquals("Wrong concrete class.", Volvo.class, finder.findAll().iterator().next().getClass());
|
||||
}
|
||||
|
||||
@@ -184,16 +184,16 @@ public class SubReferenceNodeTypeRepresentationStrategyTest extends EntityTestBa
|
||||
log.warn("Created volvo");
|
||||
persist(new Toyota());
|
||||
log.warn("Created volvo");
|
||||
assertEquals("Wrong count for Volvo.", 1L, graphRepositoryFactory.createGraphRepository(Volvo.class).count());
|
||||
assertEquals("Wrong count for Toyota.", 1L, graphRepositoryFactory.createGraphRepository(Toyota.class).count());
|
||||
assertEquals("Wrong count for Car.", 2L, graphRepositoryFactory.createGraphRepository(Car.class).count());
|
||||
assertEquals("Wrong count for Volvo.", 1L, graphDatabaseContext.repositoryFor(Volvo.class).count());
|
||||
assertEquals("Wrong count for Toyota.", 1L, graphDatabaseContext.repositoryFor(Toyota.class).count());
|
||||
assertEquals("Wrong count for Car.", 2L, graphDatabaseContext.repositoryFor(Car.class).count());
|
||||
}
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCountClasses() {
|
||||
persistedPerson("Michael", 36);
|
||||
persistedPerson("David", 25);
|
||||
assertEquals("Wrong Person instance count.", 2L, graphRepositoryFactory.createGraphRepository(Person.class).count());
|
||||
assertEquals("Wrong Person instance count.", 2L, graphDatabaseContext.repositoryFor(Person.class).count());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -93,10 +93,6 @@
|
||||
<property name="mappingContext" ref="mappingContext"/>
|
||||
</bean>
|
||||
|
||||
<bean id="graphRepositoryFactory" class="org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory">
|
||||
<constructor-arg ref="graphDatabaseContext" />
|
||||
</bean>
|
||||
|
||||
<!--bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
|
||||
<property name="transactionManager">
|
||||
<bean class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.kernel.EmbeddedGraphDatabase;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
@@ -37,8 +36,6 @@ public class DataGraphNamespaceHandlerCrossStoreTest {
|
||||
@Autowired
|
||||
GraphDatabaseService graphDatabaseService;
|
||||
@Autowired
|
||||
DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
@Autowired
|
||||
GraphDatabaseContext graphDatabaseContext;
|
||||
@Autowired
|
||||
PlatformTransactionManager transactionManager;
|
||||
@@ -56,7 +53,6 @@ public class DataGraphNamespaceHandlerCrossStoreTest {
|
||||
Assert.assertNotNull("graphDatabaseContext", graphDatabaseContext);
|
||||
EmbeddedGraphDatabase graphDatabaseService = (EmbeddedGraphDatabase) graphDatabaseContext.getGraphDatabaseService();
|
||||
Assert.assertEquals("store-dir", "target/config-test", graphDatabaseService.getStoreDir());
|
||||
Assert.assertNotNull("graphRepositoryFactory", config.graphRepositoryFactory);
|
||||
Assert.assertNotNull("graphDatabaseService", config.graphDatabaseService);
|
||||
Assert.assertNotNull("transactionManager", config.transactionManager);
|
||||
config.graphDatabaseService.shutdown();
|
||||
|
||||
@@ -146,10 +146,6 @@
|
||||
</bean>
|
||||
|
||||
|
||||
<bean id="graphRepositoryFactory" class="org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory">
|
||||
<constructor-arg ref="graphDatabaseContext" />
|
||||
</bean>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.data.neo4j.transaction.ChainedTransactionManager" >
|
||||
<constructor-arg>
|
||||
<list>
|
||||
|
||||
@@ -16,13 +16,14 @@
|
||||
package org.springframework.data.neo4j.rest;
|
||||
|
||||
import org.neo4j.rest.graphdb.util.ConvertedResult;
|
||||
import org.springframework.data.neo4j.conversion.EndResult;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
class SpringConvertedResult<R> implements org.springframework.data.neo4j.conversion.ConvertedResult<R> {
|
||||
class SpringEndResult<R> implements EndResult<R> {
|
||||
private final ConvertedResult<R> result;
|
||||
|
||||
public SpringConvertedResult(ConvertedResult<R> result) {
|
||||
public SpringEndResult(ConvertedResult<R> result) {
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ public class SpringRestCypherQueryEngine implements QueryEngine<Map<String,Objec
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpringRestQueryResult<Map<String,Object>> query(String statement, Map<String, Object> params) {
|
||||
return new SpringRestQueryResult<Map<String, Object>>(restCypherQueryEngine.query(statement, params));
|
||||
public SpringRestResult<Map<String,Object>> query(String statement, Map<String, Object> params) {
|
||||
return new SpringRestResult<Map<String, Object>>(restCypherQueryEngine.query(statement, params));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.neo4j.rest.graphdb.query.RestCypherQueryEngine;
|
||||
import org.neo4j.rest.graphdb.query.RestGremlinQueryEngine;
|
||||
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.ResultConverter;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.support.query.ConversionServiceQueryResultConverter;
|
||||
@@ -77,13 +78,19 @@ public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDat
|
||||
return super.getRestAPI().createTraversalDescription();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> QueryEngine<T> queryEngineFor(QueryType type, final ResultConverter resultConverter) {
|
||||
switch (type) {
|
||||
case Cypher: return (QueryEngine<T>)new SpringRestCypherQueryEngine(new RestCypherQueryEngine(getRestAPI(), new SpringResultConverter(resultConverter)));
|
||||
case Gremlin: return (QueryEngine<T>)new SpringRestGremlinQueryEngine(new RestGremlinQueryEngine(getRestAPI(),new SpringResultConverter(resultConverter)));
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown Query Engine Type "+type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> QueryEngine<T> queryEngineFor(QueryType type) {
|
||||
switch (type) {
|
||||
case Cypher: return (QueryEngine<T>)new SpringRestCypherQueryEngine(new RestCypherQueryEngine(super.getRestAPI()));
|
||||
case Gremlin: return (QueryEngine<T>)new SpringRestGremlinQueryEngine(new RestGremlinQueryEngine(super.getRestAPI()));
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown Query Engine Type "+type);
|
||||
return queryEngineFor(type,createResultConverter());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -92,8 +99,20 @@ public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDat
|
||||
}
|
||||
|
||||
private ResultConverter createResultConverter() {
|
||||
if (conversionService==null) return null;
|
||||
if (conversionService==null) return new DefaultConverter();
|
||||
return new ConversionServiceQueryResultConverter(conversionService);
|
||||
}
|
||||
|
||||
private static class SpringResultConverter implements org.neo4j.rest.graphdb.util.ResultConverter {
|
||||
private final ResultConverter resultConverter;
|
||||
|
||||
public SpringResultConverter(ResultConverter resultConverter) {
|
||||
this.resultConverter = resultConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object convert(Object value, Class target) {
|
||||
return resultConverter.convert(value,target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ public class SpringRestGremlinQueryEngine implements QueryEngine<Object> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpringRestQueryResult<Object> query(String statement, Map<String, Object> params) {
|
||||
return new SpringRestQueryResult<Object>(restGremlinQueryEngine.query(statement, params));
|
||||
public SpringRestResult<Object> query(String statement, Map<String, Object> params) {
|
||||
return new SpringRestResult<Object>(restGremlinQueryEngine.query(statement, params));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,30 +17,36 @@ package org.springframework.data.neo4j.rest;
|
||||
|
||||
import org.neo4j.rest.graphdb.util.ConvertedResult;
|
||||
import org.neo4j.rest.graphdb.util.ResultConverter;
|
||||
import org.springframework.data.neo4j.conversion.EndResult;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
||||
class SpringRestQueryResult<T> implements org.springframework.data.neo4j.conversion.QueryResult<T> {
|
||||
class SpringRestResult<T> implements Result<T> {
|
||||
org.neo4j.rest.graphdb.util.QueryResult<T> queryResult;
|
||||
|
||||
@Override
|
||||
public <R> org.springframework.data.neo4j.conversion.ConvertedResult<R> to(final Class<R> type) {
|
||||
return new SpringConvertedResult<R>(queryResult.to(type));
|
||||
SpringRestResult(org.neo4j.rest.graphdb.util.QueryResult<T> queryResult) {
|
||||
this.queryResult = queryResult;
|
||||
}
|
||||
|
||||
public <R> org.springframework.data.neo4j.conversion.ConvertedResult<R> to(Class<R> type, final org.springframework.data.neo4j.conversion.ResultConverter<T, R> trResultConverter) {
|
||||
@Override
|
||||
public <R> EndResult<R> to(final Class<R> type) {
|
||||
return new SpringEndResult<R>(queryResult.to(type));
|
||||
}
|
||||
|
||||
public <R> EndResult<R> to(Class<R> type, final org.springframework.data.neo4j.conversion.ResultConverter<T, R> converter) {
|
||||
ConvertedResult<R> result = queryResult.to(type, new ResultConverter<T, R>() {
|
||||
@Override
|
||||
public R convert(T value, Class<R> type) {
|
||||
return trResultConverter.convert(value,type);
|
||||
return converter.convert(value,type);
|
||||
}
|
||||
});
|
||||
return new SpringConvertedResult<R>(result);
|
||||
return new SpringEndResult<R>(result);
|
||||
}
|
||||
|
||||
public void handle(org.springframework.data.neo4j.conversion.Handler<T> tHandler) {
|
||||
queryResult.handle(new SpringHandler<T>(tHandler));
|
||||
public void handle(org.springframework.data.neo4j.conversion.Handler<T> handler) {
|
||||
queryResult.handle(new SpringHandler<T>(handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,11 +54,11 @@ class SpringRestQueryResult<T> implements org.springframework.data.neo4j.convers
|
||||
return queryResult.iterator();
|
||||
}
|
||||
|
||||
SpringRestQueryResult(org.neo4j.rest.graphdb.util.QueryResult<T> queryResult) {
|
||||
this.queryResult = queryResult;
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T single() {
|
||||
return (T) to(Object.class).single();
|
||||
}
|
||||
|
||||
org.neo4j.rest.graphdb.util.QueryResult<T> queryResult;
|
||||
|
||||
|
||||
}
|
||||
@@ -52,7 +52,6 @@ public class RestFinderTest extends FinderTest {
|
||||
@AfterClass
|
||||
public static void shutdownDb() {
|
||||
RestTestBase.shutdownDb();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,7 +37,6 @@ 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.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.support.DelegatingGraphDatabase;
|
||||
import org.springframework.data.neo4j.support.EntityInstantiator;
|
||||
import org.springframework.data.neo4j.support.EntityStateHandler;
|
||||
@@ -97,6 +96,9 @@ public abstract class Neo4jConfiguration {
|
||||
gdc.setRelationshipTypeRepresentationStrategy(relationshipTypeRepresentationStrategy());
|
||||
gdc.setRelationshipEntityInstantiator(graphRelationshipInstantiator());
|
||||
|
||||
gdc.setTransactionManager(neo4jTransactionManager());
|
||||
gdc.setGraphDatabase(graphDatabase());
|
||||
|
||||
if (validator!=null) {
|
||||
gdc.setValidator(validator);
|
||||
}
|
||||
@@ -161,12 +163,6 @@ public abstract class Neo4jConfiguration {
|
||||
return new NodeEntityInstantiator(entityStateHandler());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DirectGraphRepositoryFactory directGraphRepositoryFactory() throws Exception {
|
||||
return new DirectGraphRepositoryFactory(graphDatabaseContext());
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Neo4jMappingContext mappingContext() {
|
||||
return new Neo4jMappingContext();
|
||||
|
||||
@@ -20,7 +20,7 @@ package org.springframework.data.neo4j.conversion;
|
||||
* @author mh
|
||||
* @since 28.06.11
|
||||
*/
|
||||
public interface ConvertedResult<R> extends Iterable<R> {
|
||||
public interface EndResult<R> extends Iterable<R> {
|
||||
R single();
|
||||
void handle(Handler<R> handler);
|
||||
}
|
||||
@@ -26,7 +26,7 @@ import java.util.Iterator;
|
||||
* @author mh
|
||||
* @since 28.06.11
|
||||
*/
|
||||
public class QueryResultBuilder<T> implements QueryResult<T> {
|
||||
public class QueryResultBuilder<T> implements Result<T> {
|
||||
private Iterable<T> result;
|
||||
private final ResultConverter defaultConverter;
|
||||
private final boolean isClosableIterable;
|
||||
@@ -45,13 +45,27 @@ public class QueryResultBuilder<T> implements QueryResult<T> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> ConvertedResult<R> to(Class<R> type) {
|
||||
public <R> EndResult<R> to(Class<R> type) {
|
||||
return this.to(type, defaultConverter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> ConvertedResult<R> to(final Class<R> type, final ResultConverter<T, R> resultConverter) {
|
||||
return new ConvertedResult<R>() {
|
||||
public T single() {
|
||||
try {
|
||||
final Iterator<T> it = result.iterator();
|
||||
if (!it.hasNext()) throw new IllegalStateException("Expected at least one result, got none.");
|
||||
final T value = it.next();
|
||||
if (it.hasNext())
|
||||
throw new IllegalStateException("Expected at least one result, got more than one.");
|
||||
return value;
|
||||
} finally {
|
||||
closeIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> EndResult<R> to(final Class<R> type, final ResultConverter<T, R> resultConverter) {
|
||||
return new EndResult<R>() {
|
||||
@Override
|
||||
public R single() {
|
||||
try {
|
||||
|
||||
@@ -20,8 +20,7 @@ package org.springframework.data.neo4j.conversion;
|
||||
* @author mh
|
||||
* @since 28.06.11
|
||||
*/
|
||||
public interface QueryResult<T> extends Iterable<T> {
|
||||
<R> ConvertedResult<R> to(Class<R> type);
|
||||
<R> ConvertedResult<R> to(Class<R> type, ResultConverter<T, R> resultConverter);
|
||||
void handle(Handler<T> handler);
|
||||
public interface Result<T> extends Iterable<T>, EndResult<T> {
|
||||
<R> EndResult<R> to(Class<R> type);
|
||||
<R> EndResult<R> to(Class<R> type, ResultConverter<T, R> resultConverter);
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Copyright 2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.conversion;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Path;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.traversal.Traverser;
|
||||
import org.neo4j.helpers.collection.IterableWrapper;
|
||||
import org.springframework.data.neo4j.core.EntityPath;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.path.EntityPathPathIterableWrapper;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 16.10.11
|
||||
*/ // todo integrate in result conversion handling
|
||||
public class TraverserConverter<T> {
|
||||
|
||||
private final GraphDatabaseContext ctx;
|
||||
|
||||
public TraverserConverter(GraphDatabaseContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterable<T> convert(Traverser traverser, Class<T> targetType) {
|
||||
if (Node.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.nodes();
|
||||
if (Relationship.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.relationships();
|
||||
if (EntityPath.class.isAssignableFrom(targetType)) return new EntityPathPathIterableWrapper(traverser, ctx);
|
||||
if (Path.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser;
|
||||
return (Iterable<T>) convertToGraphEntity(traverser, targetType);
|
||||
}
|
||||
|
||||
private Iterable<?> convertToGraphEntity(Traverser traverser, final Class<?> targetType) {
|
||||
if (ctx.isNodeEntity(targetType)) {
|
||||
return new IterableWrapper<Object, Node>(traverser.nodes()) {
|
||||
@Override
|
||||
protected Object underlyingObjectToObject(Node node) {
|
||||
return ctx.createEntityFromState(node, targetType);
|
||||
}
|
||||
};
|
||||
}
|
||||
if (ctx.isRelationshipEntity(targetType)) {
|
||||
return new IterableWrapper<Object, Relationship>(traverser.relationships()) {
|
||||
@Override
|
||||
protected Object underlyingObjectToObject(Relationship relationship) {
|
||||
return ctx.createEntityFromState(relationship, targetType);
|
||||
}
|
||||
};
|
||||
}
|
||||
throw new IllegalStateException("Can't determine valid type for traversal target " + targetType);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
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.support.query.QueryEngine;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -102,4 +103,6 @@ public interface GraphDatabase {
|
||||
<T> QueryEngine<T> queryEngineFor(QueryType type);
|
||||
|
||||
void setConversionService(ConversionService conversionService);
|
||||
|
||||
<T> QueryEngine<T> queryEngineFor(QueryType type, ResultConverter resultConverter);
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ public class QueryFieldAccessorFactory implements FieldAccessorFactory {
|
||||
}
|
||||
|
||||
private Object executeQuery(Object entity, String queryString, Map<String, Object> params) {
|
||||
return graphDatabaseContext.executeQuery(queryString,params,property);
|
||||
return graphDatabaseContext.query(queryString, params, property.getTypeInformation());
|
||||
}
|
||||
|
||||
private Map<String, Object> createPlaceholderParams(Object entity) {
|
||||
|
||||
@@ -53,7 +53,8 @@ public class Neo4jEntityPersister implements Neo4jEntityConverter<Object,Node> {
|
||||
public <S extends PropertyContainer, T> T createEntityFromStoredType(S state) {
|
||||
return createEntityFromState(state,null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static class StackedEntityCache {
|
||||
private long depth;
|
||||
private final Map<PropertyContainer,Object> objects =new HashMap<PropertyContainer, Object>();
|
||||
|
||||
@@ -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.repository;
|
||||
|
||||
|
||||
|
||||
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
|
||||
/**
|
||||
* Simple Factory for {@link NodeGraphRepository} instances.
|
||||
*/
|
||||
public class DirectGraphRepositoryFactory {
|
||||
|
||||
private final GraphDatabaseContext graphDatabaseContext;
|
||||
|
||||
public DirectGraphRepositoryFactory(final GraphDatabaseContext graphDatabaseContext) {
|
||||
this.graphDatabaseContext = graphDatabaseContext;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <T> GraphRepository<T> createGraphRepository(Class<T> clazz) {
|
||||
if (graphDatabaseContext.isNodeEntity(clazz)) return new NodeGraphRepository(clazz, graphDatabaseContext);
|
||||
if (graphDatabaseContext.isRelationshipEntity(clazz)) return new RelationshipGraphRepository(clazz, graphDatabaseContext);
|
||||
throw new IllegalArgumentException("Can't create graph repository for non graph entity of type "+clazz);
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,6 @@
|
||||
|
||||
package org.springframework.data.neo4j.repository;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.PropertyContainer;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
@@ -44,13 +37,16 @@ import org.springframework.data.repository.core.EntityInformation;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.*;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 28.03.11
|
||||
|
||||
@@ -24,11 +24,14 @@ import org.neo4j.index.impl.lucene.LuceneIndexImplementation;
|
||||
import org.neo4j.kernel.Traversal;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.neo4j.annotation.QueryType;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
import org.springframework.data.neo4j.conversion.ResultConverter;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.support.query.ConversionServiceQueryResultConverter;
|
||||
import org.springframework.data.neo4j.support.query.CypherQueryEngine;
|
||||
import org.springframework.data.neo4j.support.query.GremlinQueryEngine;
|
||||
import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -40,10 +43,15 @@ public class DelegatingGraphDatabase implements GraphDatabase {
|
||||
|
||||
protected GraphDatabaseService delegate;
|
||||
private ConversionService conversionService;
|
||||
private ResultConverter resultConverter;
|
||||
|
||||
public DelegatingGraphDatabase(final GraphDatabaseService delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
public DelegatingGraphDatabase(final GraphDatabaseService delegate, ResultConverter resultConverter) {
|
||||
this.delegate = delegate;
|
||||
this.resultConverter = resultConverter;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
@@ -117,7 +125,7 @@ public class DelegatingGraphDatabase implements GraphDatabase {
|
||||
Map<String, String> existingConfig = delegate.index().getConfiguration(index);
|
||||
Map<String, String> config = indexConfigFor(fullText);
|
||||
if (config.equals(existingConfig)) return index;
|
||||
throw new IllegalArgumentException("Setup for index "+indexName+" does not match "+(fullText ? "fulltext":"exact"));
|
||||
throw new IllegalArgumentException("Setup for index name '"+indexName+"' does not match "+(fullText ? "fulltext":"exact"));
|
||||
}
|
||||
|
||||
private Map<String, String> indexConfigFor(boolean fullText) {
|
||||
@@ -129,18 +137,36 @@ public class DelegatingGraphDatabase implements GraphDatabase {
|
||||
return Traversal.description();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
// todo create query engines only once
|
||||
public <T> QueryEngine<T> queryEngineFor(QueryType type) {
|
||||
return queryEngineFor(type,createResultConverter());
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> QueryEngine<T> queryEngineFor(QueryType type,ResultConverter resultConverter) {
|
||||
switch (type) {
|
||||
case Cypher: return (QueryEngine<T>)new CypherQueryEngine(delegate, createResultConverter());
|
||||
case Gremlin: return (QueryEngine<T>) new GremlinQueryEngine(delegate);
|
||||
case Cypher: {
|
||||
if (!ClassUtils.isPresent("org.neo4j.cypher.javacompat.ExecutionEngine", getClass().getClassLoader())) {
|
||||
return new FailingQueryEngine<T>("Cypher");
|
||||
}
|
||||
return (QueryEngine<T>)new CypherQueryEngine(delegate, resultConverter);
|
||||
}
|
||||
case Gremlin: {
|
||||
if (!ClassUtils.isPresent("com.tinkerpop.blueprints.pgm.impls.neo4j.Neo4jGraph", getClass().getClassLoader())) {
|
||||
return new FailingQueryEngine<T>("Gremlin");
|
||||
}
|
||||
return (QueryEngine<T>) new GremlinQueryEngine(delegate,resultConverter);
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown Query Engine Type "+type);
|
||||
}
|
||||
|
||||
private ConversionServiceQueryResultConverter createResultConverter() {
|
||||
if (conversionService == null) return null;
|
||||
return new ConversionServiceQueryResultConverter(conversionService);
|
||||
private ResultConverter createResultConverter() {
|
||||
if (resultConverter!=null) return resultConverter;
|
||||
if (conversionService != null) {
|
||||
this.resultConverter = new ConversionServiceQueryResultConverter(conversionService);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
@@ -151,4 +177,17 @@ public class DelegatingGraphDatabase implements GraphDatabase {
|
||||
public Node getReferenceNode() {
|
||||
return delegate.getReferenceNode();
|
||||
}
|
||||
|
||||
private static class FailingQueryEngine<T> implements QueryEngine<T> {
|
||||
private String dependency;
|
||||
|
||||
private FailingQueryEngine(final String dependency) {
|
||||
this.dependency = dependency;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<T> query(String statement, Map<String, Object> params) {
|
||||
throw new IllegalStateException(dependency + " is not available, please add it to your dependencies to execute: " +statement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,4 +206,9 @@ public class EntityStateHandler {
|
||||
}
|
||||
|
||||
|
||||
public Node getNodeState(Object entity) {
|
||||
final PropertyContainer result = getPersistentState(entity);
|
||||
if (result==null || result instanceof Node) return (Node) result;
|
||||
throw new IllegalArgumentException("State of "+entity+" is no Node but "+result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,31 +24,54 @@ import org.neo4j.graphdb.index.IndexManager;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.graphdb.traversal.Traverser;
|
||||
import org.neo4j.helpers.collection.ClosableIterable;
|
||||
import org.neo4j.helpers.collection.IterableWrapper;
|
||||
import org.neo4j.index.impl.lucene.LuceneIndexImplementation;
|
||||
import org.neo4j.kernel.AbstractGraphDatabase;
|
||||
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;
|
||||
import org.springframework.data.neo4j.conversion.QueryResultBuilder;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
import org.springframework.data.neo4j.conversion.ResultConverter;
|
||||
import org.springframework.data.neo4j.conversion.TraverserConverter;
|
||||
import org.springframework.data.neo4j.core.EntityPath;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.core.TypeRepresentationStrategy;
|
||||
import org.springframework.data.neo4j.core.UncategorizedGraphStoreException;
|
||||
import org.springframework.data.neo4j.fieldaccess.GraphBackedEntityIterableWrapper;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jEntityPersister;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntityImpl;
|
||||
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.path.EntityPathPathIterableWrapper;
|
||||
import org.springframework.data.neo4j.support.query.CypherQueryExecutor;
|
||||
import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
import org.springframework.data.neo4j.support.relationship.RelationshipEntityInstantiator;
|
||||
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;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallback;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.transaction.Status;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.TransactionManager;
|
||||
import javax.validation.Validator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@@ -60,7 +83,7 @@ import java.util.Map;
|
||||
* @author Michael Hunger
|
||||
* @since 13.09.2010
|
||||
*/
|
||||
public class GraphDatabaseContext {
|
||||
public class GraphDatabaseContext implements Neo4jOperations {
|
||||
|
||||
private static final Log log = LogFactory.getLog(GraphDatabaseContext.class);
|
||||
|
||||
@@ -81,13 +104,44 @@ public class GraphDatabaseContext {
|
||||
private TypeRepresentationStrategies typeRepresentationStrategies;
|
||||
private EntityInstantiator<Relationship> relationshipEntityInstantiator;
|
||||
private EntityInstantiator<Node> nodeEntityInstantiator;
|
||||
private PlatformTransactionManager transactionManager;
|
||||
private GraphDatabase graphDatabase;
|
||||
private ResultConverter resultConverter;
|
||||
private IndexProvider indexProvider;
|
||||
|
||||
public void setRelationshipEntityInstantiator(EntityInstantiator<Relationship> relationshipEntityInstantiator) {
|
||||
this.relationshipEntityInstantiator = relationshipEntityInstantiator;
|
||||
|
||||
/**
|
||||
* default constructor for dependency injection, TODO provide dependencies at creation time
|
||||
*/
|
||||
public GraphDatabaseContext() {
|
||||
}
|
||||
|
||||
public void setNodeEntityInstantiator(EntityInstantiator<Node> nodeEntityInstantiator) {
|
||||
this.nodeEntityInstantiator = nodeEntityInstantiator;
|
||||
/**
|
||||
* @param graphDatabase the neo4j graph database
|
||||
* @param transactionManager if passed in, will be used to create implicit transactions whenever needed
|
||||
*/
|
||||
public GraphDatabaseContext(final GraphDatabase graphDatabase, PlatformTransactionManager transactionManager) {
|
||||
notNull(graphDatabase, "graphDatabase");
|
||||
this.transactionManager = transactionManager;
|
||||
this.graphDatabase = graphDatabase;
|
||||
}
|
||||
|
||||
public GraphDatabaseContext(final GraphDatabase graphDatabase) {
|
||||
notNull(graphDatabase, "graphDatabase");
|
||||
transactionManager = null;
|
||||
this.graphDatabase = graphDatabase;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <T> GraphRepository<T> repositoryFor(Class<T> clazz) {
|
||||
if (isNodeEntity(clazz)) return new NodeGraphRepository(clazz, this);
|
||||
if (isRelationshipEntity(clazz)) return new RelationshipGraphRepository(clazz, this);
|
||||
throw new IllegalArgumentException("Can't create graph repository for non graph entity of type "+clazz);
|
||||
}
|
||||
|
||||
public GraphDatabase getGraphDatabase() {
|
||||
return graphDatabase;
|
||||
}
|
||||
|
||||
static class IndexProvider {
|
||||
@@ -109,30 +163,80 @@ public class GraphDatabaseContext {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <S extends PropertyContainer, T> Index<S> getIndex(Class<T> type, String indexName, Boolean fullText) {
|
||||
if (indexName == null) indexName = Indexed.Name.get(type);
|
||||
if (fullText == null) {
|
||||
if (mappingContext.isNodeEntity(type)) return (Index<S>) getIndexManager().forNodes(indexName);
|
||||
if (mappingContext.isRelationshipEntity(type))
|
||||
return (Index<S>) getIndexManager().forRelationships(indexName);
|
||||
throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity");
|
||||
|
||||
if (type==null) {
|
||||
notNull(indexName,"indexName");
|
||||
return getIndex(indexName);
|
||||
}
|
||||
Map<String, String> config = fullText ? LuceneIndexImplementation.FULLTEXT_CONFIG : LuceneIndexImplementation.EXACT_CONFIG;
|
||||
|
||||
if (mappingContext.isNodeEntity(type)) return (Index<S>) getIndexManager().forNodes(indexName, config);
|
||||
if (mappingContext.isRelationshipEntity(type))
|
||||
return (Index<S>) getIndexManager().forRelationships(indexName, config);
|
||||
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<S>) getIndexManager().forNodes(indexName);
|
||||
if (persistentEntity.isRelationshipEntity()) return (Index<S>) getIndexManager().forRelationships(indexName);
|
||||
throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity");
|
||||
}
|
||||
|
||||
if (persistentEntity.isNodeEntity()) return (Index<S>) createIndex(Node.class, indexName, fullText);
|
||||
if (persistentEntity.isRelationshipEntity()) return (Index<S>) createIndex(Relationship.class, indexName, fullText);
|
||||
throw new IllegalArgumentException("Wrong index type supplied: " + type + " expected Node- or Relationship-Entity");
|
||||
}
|
||||
|
||||
public IndexManager getIndexManager() {
|
||||
return indexManager;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends PropertyContainer> Index<T> getIndex(String indexName) {
|
||||
if (indexManager.existsForNodes(indexName)) return (Index<T>) indexManager.forNodes(indexName);
|
||||
if (indexManager.existsForRelationships(indexName)) return (Index<T>) indexManager.forRelationships(indexName);
|
||||
throw new IllegalArgumentException("Index "+indexName+" does not exist.");
|
||||
}
|
||||
|
||||
public boolean isNode(Class<? extends PropertyContainer> type) {
|
||||
if (type.equals(Node.class)) return true;
|
||||
if (type.equals(Relationship.class)) return false;
|
||||
throw new IllegalArgumentException("Unknown Graph Primitive, neither Node nor Relationship"+type);
|
||||
}
|
||||
|
||||
// TODO handle existing indexes
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends PropertyContainer> Index<T> createIndex(Class<T> type, String indexName, boolean fullText) {
|
||||
if (isNode(type)) {
|
||||
if (indexManager.existsForNodes(indexName))
|
||||
return (Index<T>) checkAndGetExistingIndex(indexName, fullText, indexManager.forNodes(indexName));
|
||||
return (Index<T>) indexManager.forNodes(indexName, indexConfigFor(fullText));
|
||||
} else {
|
||||
if (indexManager.existsForRelationships(indexName))
|
||||
return (Index<T>) checkAndGetExistingIndex(indexName, fullText, indexManager.forRelationships(indexName));
|
||||
return (Index<T>) indexManager.forRelationships(indexName, indexConfigFor(fullText));
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends PropertyContainer> Index<T> checkAndGetExistingIndex(final String indexName, boolean fullText, final Index<T> index) {
|
||||
Map<String, String> existingConfig = indexManager.getConfiguration(index);
|
||||
Map<String, String> config = indexConfigFor(fullText);
|
||||
if (configCheck(config, existingConfig, "provider") && configCheck(config, existingConfig, "type")) return index;
|
||||
throw new IllegalArgumentException("Setup for index "+indexName+" does not match. Existing: "+existingConfig+" required "+config);
|
||||
}
|
||||
|
||||
private boolean configCheck(Map<String, String> config, Map<String, String> existingConfig, String setting) {
|
||||
return ObjectUtils.nullSafeEquals(config.get(setting), existingConfig.get(setting));
|
||||
}
|
||||
|
||||
private Map<String, String> indexConfigFor(boolean fullText) {
|
||||
return fullText ? LuceneIndexImplementation.FULLTEXT_CONFIG : LuceneIndexImplementation.EXACT_CONFIG;
|
||||
}
|
||||
|
||||
}
|
||||
IndexProvider indexProvider;
|
||||
|
||||
public <S extends PropertyContainer, T> Index<S> getIndex(Class<T> type) {
|
||||
return indexProvider.getIndex(type, null);
|
||||
}
|
||||
public <S extends PropertyContainer> Index<S> getIndex(String name) {
|
||||
return indexProvider.getIndex(null, name);
|
||||
}
|
||||
|
||||
public <S extends PropertyContainer, T> Index<S> getIndex(Class<T> type, String indexName) {
|
||||
return indexProvider.getIndex(type, indexName, null);
|
||||
@@ -160,39 +264,6 @@ public class GraphDatabaseContext {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Iterable<T> findAllByTraversal(Object entity, Class<?> targetType, TraversalDescription traversalDescription) {
|
||||
final PropertyContainer state = entityPersister.getPersistentState(entity);
|
||||
if (state == null) throw new IllegalStateException("No node attached to " + this);
|
||||
final Traverser traverser = traversalDescription.traverse((Node) state);
|
||||
if (Node.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.nodes();
|
||||
if (Relationship.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.relationships();
|
||||
if (EntityPath.class.isAssignableFrom(targetType)) return new EntityPathPathIterableWrapper(traverser,this);
|
||||
if (Path.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser;
|
||||
return (Iterable<T>) convertToGraphEntity(traverser, targetType);
|
||||
}
|
||||
|
||||
private Iterable<?> convertToGraphEntity(Traverser traverser, final Class<?> targetType) {
|
||||
if (isNodeEntity(targetType)) {
|
||||
return new IterableWrapper<Object, Node>(traverser.nodes()) {
|
||||
@Override
|
||||
protected Object underlyingObjectToObject(Node node) {
|
||||
return createEntityFromState(node, targetType);
|
||||
}
|
||||
};
|
||||
}
|
||||
if (isRelationshipEntity(targetType)) {
|
||||
return new IterableWrapper<Object, Relationship>(traverser.relationships()) {
|
||||
@Override
|
||||
protected Object underlyingObjectToObject(Relationship relationship) {
|
||||
return createEntityFromState(relationship, targetType);
|
||||
}
|
||||
};
|
||||
}
|
||||
throw new IllegalStateException("Can't determine valid type for traversal target " + targetType);
|
||||
|
||||
}
|
||||
|
||||
public <T> ClosableIterable<T> findAll(final Class<T> entityClass) {
|
||||
return typeRepresentationStrategies.findAll(entityClass);
|
||||
}
|
||||
@@ -231,6 +302,14 @@ public class GraphDatabaseContext {
|
||||
}
|
||||
|
||||
public void remove(Object entity) {
|
||||
if (entity instanceof Node) {
|
||||
((Node)entity).delete();
|
||||
return;
|
||||
}
|
||||
if (entity instanceof Relationship) {
|
||||
((Relationship)entity).delete();
|
||||
return;
|
||||
}
|
||||
final Class<?> type = entity.getClass();
|
||||
if (isNodeEntity(type)) {
|
||||
entityRemover.removeNodeEntity(entity);
|
||||
@@ -253,10 +332,45 @@ public class GraphDatabaseContext {
|
||||
/**
|
||||
* Delegates to {@link GraphDatabaseService}
|
||||
*/
|
||||
@Override
|
||||
public Node createNode() {
|
||||
return graphDatabaseService.createNode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node createNode(final Map<String,Object> properties) {
|
||||
return graphDatabase.createNode(properties);
|
||||
}
|
||||
|
||||
public <T> T createNode(Class<T> target, Map<String,Object> properties) {
|
||||
final Node node = createNode(properties);
|
||||
if (isNodeEntity(target)) {
|
||||
typeRepresentationStrategies.postEntityCreation(node,target);
|
||||
}
|
||||
return convert(node, target);
|
||||
}
|
||||
|
||||
public Result<Node> createNodes(Map<String,Object>...allNodes) {
|
||||
Collection<Node> result=new ArrayList<Node>(allNodes.length);
|
||||
for (Map<String, Object> properties : allNodes) {
|
||||
result.add(createNode(properties));
|
||||
}
|
||||
return convert(result);
|
||||
}
|
||||
|
||||
public <T> Iterable<T> createNodes(Class<T> target, Map<String,Object>...allNodes) {
|
||||
final TypeRepresentationStrategy<Node> nodeTypeRepresentationStrategy = isNodeEntity(target) ? typeRepresentationStrategies.getNodeTypeRepresentationStrategy() : null;
|
||||
Collection<Node> result=new ArrayList<Node>(allNodes.length);
|
||||
for (Map<String, Object> properties : allNodes) {
|
||||
final Node node = createNode(properties);
|
||||
if (nodeTypeRepresentationStrategy!=null) {
|
||||
nodeTypeRepresentationStrategy.postEntityCreation(node,target);
|
||||
}
|
||||
result.add(node);
|
||||
}
|
||||
return convert(result).to(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link GraphDatabaseService}
|
||||
*/
|
||||
@@ -267,15 +381,8 @@ public class GraphDatabaseContext {
|
||||
/**
|
||||
* Delegates to {@link GraphDatabaseService}
|
||||
*/
|
||||
public Node getReferenceNode() {
|
||||
return graphDatabaseService.getReferenceNode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to {@link GraphDatabaseService}
|
||||
*/
|
||||
public Iterable<? extends Node> getAllNodes() {
|
||||
return graphDatabaseService.getAllNodes();
|
||||
public Result<Node> getAllNodes() {
|
||||
return convert(graphDatabaseService.getAllNodes());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -294,6 +401,10 @@ public class GraphDatabaseContext {
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
this.resultConverter = new EntityResultConverter<Object, Object>(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, graphDatabaseService);
|
||||
@@ -328,19 +439,19 @@ public class GraphDatabaseContext {
|
||||
return entityStateHandler.isManaged(entity);
|
||||
}
|
||||
|
||||
public Object executeQuery(String queryString, Map<String, Object> params, Neo4jPersistentProperty property) {
|
||||
final TypeInformation<?> typeInformation = property.getTypeInformation();
|
||||
public Object query(String statement, Map<String, Object> params, final TypeInformation<?> typeInformation) {
|
||||
final TypeInformation<?> actualType = typeInformation.getActualType();
|
||||
final Class<?> targetType = actualType.getType();
|
||||
if (actualType.isMap()) {
|
||||
return cypherQueryExecutor.queryForList(queryString, params);
|
||||
return cypherQueryExecutor.queryForList(statement, params);
|
||||
}
|
||||
if (typeInformation.isCollectionLike()) {
|
||||
return cypherQueryExecutor.query(queryString, targetType, params);
|
||||
return cypherQueryExecutor.query(statement, targetType, params);
|
||||
}
|
||||
return cypherQueryExecutor.queryForObject(queryString, targetType, params);
|
||||
return cypherQueryExecutor.queryForObject(statement, targetType, params);
|
||||
}
|
||||
|
||||
// todo have an result converter that is able to handle iterable input and output types
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Iterable<T> convertResultsTo(Traverser traverser, Class<T> targetType) {
|
||||
if (Node.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.nodes();
|
||||
@@ -376,6 +487,211 @@ public class GraphDatabaseContext {
|
||||
return createEntityFromState(result.relationship, relationshipClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Relationship createRelationship(final Node startNode, final Node endNode, final RelationshipType relationshipType, final Map<String,Object> properties) {
|
||||
notNull(startNode, "startNode", endNode, "endNode", relationshipType, "relationshipType", properties, "properties");
|
||||
return exec(new GraphCallback<Relationship>() {
|
||||
@Override
|
||||
public Relationship doWithGraph(GraphDatabase graph) throws Exception {
|
||||
return graph.createRelationship(startNode, endNode, relationshipType, properties);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
return new UncategorizedGraphStoreException("Error executing callback",ex);
|
||||
}
|
||||
|
||||
|
||||
private <T> T doExecute(final GraphCallback<T> callback) {
|
||||
notNull(callback, "callback");
|
||||
try {
|
||||
return callback.doWithGraph(graphDatabase);
|
||||
} catch (Exception e) {
|
||||
throw translateExceptionIfPossible(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T exec(final GraphCallback<T> callback) {
|
||||
if (transactionManager == null) return doExecute(callback);
|
||||
|
||||
TransactionTemplate template = new TransactionTemplate(transactionManager);
|
||||
return template.execute(new TransactionCallback<T>() {
|
||||
public T doInTransaction(TransactionStatus status) {
|
||||
return doExecute(callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node getReferenceNode() {
|
||||
try {
|
||||
return graphDatabase.getReferenceNode();
|
||||
} catch (RuntimeException e) {
|
||||
throw translateExceptionIfPossible(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node getNode(long id) {
|
||||
if (id < 0) throw new InvalidDataAccessApiUsageException("id is negative");
|
||||
try {
|
||||
return graphDatabase.getNodeById(id);
|
||||
} catch (RuntimeException e) {
|
||||
throw translateExceptionIfPossible(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Relationship getRelationship(long id) {
|
||||
if (id < 0) throw new InvalidDataAccessApiUsageException("id is negative");
|
||||
try {
|
||||
return graphDatabase.getRelationshipById(id);
|
||||
} catch (RuntimeException e) {
|
||||
throw translateExceptionIfPossible(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends PropertyContainer> T index(final String indexName, final T element, final String field, final Object value) {
|
||||
notNull(element, "element", field, "field", value, "value",indexName,"indexName");
|
||||
exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabase graph) throws Exception {
|
||||
if (element instanceof Relationship) {
|
||||
Index<Relationship> relationshipIndex = graphDatabase.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);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Provided element is neither node nor relationship " + element);
|
||||
}
|
||||
}
|
||||
});
|
||||
return element;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Result<T> convert(Iterable<T> iterable) {
|
||||
return new QueryResultBuilder<T>(iterable, (ResultConverter<T,?>) resultConverter);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T convert(Object value, Class<T> type) {
|
||||
return (T) resultConverter.convert(value,type);
|
||||
}
|
||||
|
||||
public QueryEngine queryEngineFor(QueryType type) {
|
||||
return graphDatabase.queryEngineFor(type,resultConverter);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Result<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
notNull(statement, "statement");
|
||||
return queryEngineFor(QueryType.Cypher).query(statement, params);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Result<Object> execute(String statement, Map<String, Object> params) {
|
||||
notNull(statement, "statement");
|
||||
return queryEngineFor(QueryType.Gremlin).query(statement, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Path> traverse(Object start, TraversalDescription traversal) {
|
||||
return traverse((Node)getPersistentState(start),traversal);
|
||||
}
|
||||
|
||||
|
||||
// TODO result handling !!
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> Iterable<T> findAllByTraversal(Object entity, Class<?> targetType, TraversalDescription traversalDescription) {
|
||||
final PropertyContainer state = entityPersister.getPersistentState(entity);
|
||||
if (state instanceof Node) {
|
||||
final Traverser traverser = traversalDescription.traverse((Node) state);
|
||||
return new TraverserConverter<T>(this).convert(traverser, (Class<T>) targetType);
|
||||
}
|
||||
throw new IllegalStateException("No node attached to " + entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Path> traverse(Node startNode, TraversalDescription traversal) {
|
||||
notNull(startNode, "startNode", traversal, "traversal");
|
||||
try {
|
||||
return this.convert(traversal.traverse(startNode));
|
||||
} catch (RuntimeException e) {
|
||||
throw translateExceptionIfPossible(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends PropertyContainer> Result<T> lookup(String indexName, String field, Object value) {
|
||||
notNull(field, "field", value, "value", indexName, "indexName");
|
||||
try {
|
||||
Index<T> index = getIndex(null, indexName);
|
||||
return convert(index.get(field, value));
|
||||
} catch (RuntimeException e) {
|
||||
throw translateExceptionIfPossible(e);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public <T extends PropertyContainer> Result<T> lookup(final Class<?> indexedType, final Object query) {
|
||||
notNull(query, "valueOrQueryObject", indexedType, "indexedType");
|
||||
try {
|
||||
Index<T> index = getIndex(indexedType);
|
||||
return convert(index.query(query));
|
||||
} catch (RuntimeException e) {
|
||||
throw translateExceptionIfPossible(e);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public <T extends PropertyContainer> Result<T> lookup(String indexName, Object query) {
|
||||
notNull(query, "valueOrQueryObject", indexName, "indexName");
|
||||
try {
|
||||
Index<T> index = getIndex(null, indexName);
|
||||
return convert(index.query(query));
|
||||
} catch (RuntimeException e) {
|
||||
throw translateExceptionIfPossible(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void setTransactionManager(PlatformTransactionManager transactionManager) {
|
||||
this.transactionManager = transactionManager;
|
||||
}
|
||||
|
||||
public void setRelationshipEntityInstantiator(EntityInstantiator<Relationship> relationshipEntityInstantiator) {
|
||||
this.relationshipEntityInstantiator = relationshipEntityInstantiator;
|
||||
}
|
||||
|
||||
public void setNodeEntityInstantiator(EntityInstantiator<Node> nodeEntityInstantiator) {
|
||||
this.nodeEntityInstantiator = nodeEntityInstantiator;
|
||||
}
|
||||
|
||||
|
||||
public void setEntityStateHandler(EntityStateHandler entityStateHandler) {
|
||||
this.entityStateHandler = entityStateHandler;
|
||||
@@ -437,5 +753,9 @@ public class GraphDatabaseContext {
|
||||
public void setGraphDatabaseService(GraphDatabaseService graphDatabaseService) {
|
||||
this.graphDatabaseService = graphDatabaseService;
|
||||
}
|
||||
|
||||
public void setGraphDatabase(GraphDatabase graphDatabase) {
|
||||
this.graphDatabase = graphDatabase;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,4 +108,12 @@ public class TypeRepresentationStrategies implements TypeRepresentationStrategy<
|
||||
public <U> U projectEntity(PropertyContainer state, Class<U> type) {
|
||||
return getTypeRepresentationStrategy(state).projectEntity(state, type);
|
||||
}
|
||||
|
||||
public TypeRepresentationStrategy<Node> getNodeTypeRepresentationStrategy() {
|
||||
return nodeTypeRepresentationStrategy;
|
||||
}
|
||||
|
||||
public TypeRepresentationStrategy<Relationship> getRelationshipTypeRepresentationStrategy() {
|
||||
return relationshipTypeRepresentationStrategy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,8 @@
|
||||
package org.springframework.data.neo4j.support.conversion;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.data.neo4j.core.EntityPath;
|
||||
|
||||
|
||||
import org.springframework.data.neo4j.conversion.DefaultConverter;
|
||||
import org.springframework.data.neo4j.core.EntityPath;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.path.ConvertingEntityPath;
|
||||
|
||||
@@ -41,10 +39,10 @@ public class EntityResultConverter<T,R> extends DefaultConverter<T,R> {
|
||||
@Override
|
||||
protected Object doConvert(Object value, Class<?> sourceType, Class targetType) {
|
||||
if (ctx.isNodeEntity(targetType)) {
|
||||
return ctx.createEntityFromState(toNode(value,sourceType),targetType);
|
||||
return ctx.projectTo(toNode(value,sourceType),targetType);
|
||||
}
|
||||
if (ctx.isRelationshipEntity(targetType)) {
|
||||
return ctx.createEntityFromState(toRelationship(value,sourceType),targetType);
|
||||
return ctx.projectTo(toRelationship(value,sourceType),targetType);
|
||||
}
|
||||
if (EntityPath.class.isAssignableFrom(targetType)) {
|
||||
return new ConvertingEntityPath(ctx,toPath(value,sourceType));
|
||||
|
||||
@@ -38,24 +38,24 @@ public class ConvertingEntityPath<S,E> implements EntityPath<S,E> {
|
||||
|
||||
@Override
|
||||
public <T> T startEntity(Class<T>... types) {
|
||||
return createNodeEntityFromFirstParameterOrStoredType(startNode(), types);
|
||||
return projectEntityToFirstParameterOrCreateFromStoredType(startNode(), types);
|
||||
}
|
||||
|
||||
private <T> T createNodeEntityFromFirstParameterOrStoredType(Node node, Class<T>...types) {
|
||||
private <T> T projectEntityToFirstParameterOrCreateFromStoredType(Node node, Class<T>... types) {
|
||||
if (node==null) return null;
|
||||
if (types==null || types.length==0) return graphDatabaseContext.createEntityFromStoredType(node);
|
||||
return graphDatabaseContext.createEntityFromState(node,types[0]);
|
||||
return graphDatabaseContext.projectTo(node, types[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T endEntity(Class<T>... types) {
|
||||
return createNodeEntityFromFirstParameterOrStoredType(endNode(),types);
|
||||
return projectEntityToFirstParameterOrCreateFromStoredType(endNode(), types);
|
||||
}
|
||||
@Override
|
||||
public <T> T lastRelationshipEntity(Class<T>... types) {
|
||||
Relationship relationship = lastRelationship();
|
||||
if (relationship==null) return null;
|
||||
return graphDatabaseContext.createEntityFromState(relationship, getFirstOrDefault((Class<T>) DefaultRelationshipBacked.class, types));
|
||||
return graphDatabaseContext.projectTo(relationship, getFirstOrDefault((Class<T>) DefaultRelationshipBacked.class, types));
|
||||
}
|
||||
|
||||
private static <T> T getFirstOrDefault(final T defaultValue, T... values) {
|
||||
@@ -78,7 +78,7 @@ public class ConvertingEntityPath<S,E> implements EntityPath<S,E> {
|
||||
return new IterableWrapper<T,Relationship>(relationships()) {
|
||||
@Override
|
||||
protected T underlyingObjectToObject(Relationship relationship) {
|
||||
return graphDatabaseContext.createEntityFromState(relationship, getFirstOrDefault((Class<T>)DefaultRelationshipBacked.class, relationships));
|
||||
return graphDatabaseContext.projectTo(relationship, getFirstOrDefault((Class<T>) DefaultRelationshipBacked.class, relationships));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -88,7 +88,7 @@ public class ConvertingEntityPath<S,E> implements EntityPath<S,E> {
|
||||
return new IterableWrapper<T,PropertyContainer>(delegate) {
|
||||
@Override
|
||||
protected T underlyingObjectToObject(PropertyContainer element) {
|
||||
return graphDatabaseContext.createEntityFromState(element, getFirstOrDefault((Class<T>)DefaultRelationshipBacked.class, relationships));
|
||||
return graphDatabaseContext.projectTo(element, getFirstOrDefault((Class<T>) DefaultRelationshipBacked.class, relationships));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.neo4j.cypher.javacompat.ExecutionResult;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.data.neo4j.conversion.DefaultConverter;
|
||||
import org.springframework.data.neo4j.conversion.QueryResult;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
import org.springframework.data.neo4j.conversion.QueryResultBuilder;
|
||||
import org.springframework.data.neo4j.conversion.ResultConverter;
|
||||
|
||||
@@ -47,7 +47,7 @@ public class CypherQueryEngine implements QueryEngine<Map<String,Object>> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public QueryResult<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
public Result<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
try {
|
||||
ExecutionResult result = parseAndExecuteQuery(statement,params);
|
||||
return new QueryResultBuilder<Map<String,Object>>(result,resultConverter);
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.springframework.data.neo4j.support.query;
|
||||
|
||||
import org.springframework.data.neo4j.conversion.QueryResult;
|
||||
import org.springframework.data.neo4j.annotation.QueryType;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.conversion.EntityResultConverter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -32,13 +32,12 @@ public class CypherQueryExecutor implements QueryOperations<Map<String,Object>>
|
||||
private final QueryEngine<Map<String,Object>> queryEngine;
|
||||
|
||||
public CypherQueryExecutor(GraphDatabaseContext ctx) {
|
||||
EntityResultConverter converter = new EntityResultConverter(ctx);
|
||||
if (ClassUtils.isPresent("org.neo4j.cypher.javacompat.ExecutionEngine",getClass().getClassLoader())) {
|
||||
queryEngine = new CypherQueryEngine(ctx.getGraphDatabaseService(), converter);
|
||||
queryEngine = ctx.queryEngineFor(QueryType.Cypher);
|
||||
} else {
|
||||
queryEngine = new QueryEngine<Map<String, Object>>() {
|
||||
@Override
|
||||
public QueryResult<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
public Result<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
throw new IllegalStateException("Cypher is not available, please add it to your dependencies to execute: "+statement);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ package org.springframework.data.neo4j.support.query;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.data.neo4j.conversion.DefaultConverter;
|
||||
import org.springframework.data.neo4j.conversion.QueryResult;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
import org.springframework.data.neo4j.conversion.QueryResultBuilder;
|
||||
import org.springframework.data.neo4j.conversion.ResultConverter;
|
||||
|
||||
@@ -42,7 +42,7 @@ public class GremlinQueryEngine implements QueryEngine<Object> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public QueryResult<Object> query(String statement, Map<String, Object> params) {
|
||||
public Result<Object> query(String statement, Map<String, Object> params) {
|
||||
try {
|
||||
Iterable<Object> result = gremlinExecutor.query(statement, params);
|
||||
return new QueryResultBuilder<Object>(result,resultConverter);
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.data.neo4j.support.query;
|
||||
|
||||
import org.springframework.data.neo4j.conversion.QueryResult;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -25,6 +25,6 @@ import java.util.Map;
|
||||
* @since 22.06.11
|
||||
*/
|
||||
public interface QueryEngine<T> {
|
||||
QueryResult<T> query(String statement, Map<String, Object> params);
|
||||
Result<T> query(String statement, Map<String, Object> params);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ package org.springframework.data.neo4j.template;
|
||||
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.springframework.data.neo4j.conversion.QueryResult;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
@@ -102,36 +102,45 @@ public interface Neo4jOperations {
|
||||
* Converts the Iterable into a QueryResult object for uniform handling. E.g.
|
||||
* template.convert(node.getRelationships());
|
||||
*/
|
||||
<T> QueryResult<T> convert(Iterable<T> iterable);
|
||||
<T> Result<T> convert(Iterable<T> iterable);
|
||||
|
||||
/**
|
||||
* Runs the given cypher statement and packages the result in a QueryResult, simple conversions via the
|
||||
* registered converter-factories are already executed via this method.
|
||||
*/
|
||||
QueryResult<Map<String, Object>> query(String statement,Map<String,Object> params);
|
||||
Result<Map<String, Object>> query(String statement,Map<String,Object> params);
|
||||
|
||||
/**
|
||||
* Executes the given Gremlin statement and returns the result packaged as QueryResult as Neo4j types, not
|
||||
* Gremlin types. Table rows are converted to Map<String,Object>.
|
||||
*/
|
||||
QueryResult<Object> execute(String statement, Map<String,Object> params);
|
||||
Result<Object> execute(String statement, Map<String,Object> params);
|
||||
|
||||
/**
|
||||
* Traverses the graph starting at the given node with the provided traversal description. The Path's of the
|
||||
* traversal will be packaged into a QueryResult which can be easily converted into Nodes, Relationships or
|
||||
* Graph-Entities.
|
||||
*/
|
||||
QueryResult<Path> traverse(Node startNode, TraversalDescription traversal);
|
||||
Result<Path> traverse(Node startNode, TraversalDescription traversal);
|
||||
|
||||
/**
|
||||
* The value is looked up in the Neo4j index returning the IndexHits wrapped in a QueryResult to be converted
|
||||
* into Paths or Entities.
|
||||
*/
|
||||
<T extends PropertyContainer> QueryResult<T> lookup(String indexName, String field, Object value);
|
||||
<T extends PropertyContainer> Result<T> lookup(String indexName, String field, Object value);
|
||||
|
||||
/**
|
||||
* The query is executed on the index returning the IndexHits wrapped in a QueryResult to be converted
|
||||
* into Paths or Entities.
|
||||
*/
|
||||
<T extends PropertyContainer> QueryResult<T> lookup(String indexName, Object query);
|
||||
<T extends PropertyContainer> Result<T> lookup(String indexName, Object query);
|
||||
|
||||
Result<Path> traverse(Object start, TraversalDescription traversal);
|
||||
|
||||
<T extends PropertyContainer> Result<T> lookup(Class<?> indexedType, Object query);
|
||||
|
||||
Node createNode();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> T convert(Object value, Class<T> type);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.neo4j.annotation.QueryType;
|
||||
import org.springframework.data.neo4j.conversion.QueryResult;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
import org.springframework.data.neo4j.conversion.QueryResultBuilder;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.support.query.QueryEngine;
|
||||
@@ -154,7 +154,7 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> QueryResult<T> convert(Iterable<T> iterable) {
|
||||
public <T> Result<T> convert(Iterable<T> iterable) {
|
||||
return new QueryResultBuilder<T>(iterable);
|
||||
}
|
||||
|
||||
@@ -174,20 +174,20 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public QueryResult<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
public Result<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
notNull(statement, "statement");
|
||||
return queryEngineFor(QueryType.Cypher).query(statement, params);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public QueryResult<Object> execute(String statement, Map<String, Object> params) {
|
||||
public Result<Object> execute(String statement, Map<String, Object> params) {
|
||||
notNull(statement, "statement");
|
||||
return queryEngineFor(QueryType.Gremlin).query(statement, params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResult<Path> traverse(Node startNode, TraversalDescription traversal) {
|
||||
public Result<Path> traverse(Node startNode, TraversalDescription traversal) {
|
||||
notNull(startNode, "startNode", traversal, "traversal");
|
||||
try {
|
||||
return new QueryResultBuilder<Path>(traversal.traverse(startNode));
|
||||
@@ -197,7 +197,7 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends PropertyContainer> QueryResult<T> lookup(String indexName, String field, Object value) {
|
||||
public <T extends PropertyContainer> Result<T> lookup(String indexName, String field, Object value) {
|
||||
notNull(field, "field", value, "value", indexName, "indexName");
|
||||
try {
|
||||
Index<T> index = graphDatabase.getIndex(indexName);
|
||||
@@ -207,7 +207,7 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public <T extends PropertyContainer> QueryResult<T> lookup(String indexName, Object query) {
|
||||
public <T extends PropertyContainer> Result<T> lookup(String indexName, Object query) {
|
||||
notNull(query, "valueOrQueryObject", indexName, "indexName");
|
||||
try {
|
||||
Index<T> index = graphDatabase.getIndex(indexName);
|
||||
@@ -216,6 +216,26 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
throw translateExceptionIfPossible(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result<Path> traverse(Object start, TraversalDescription traversal) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends PropertyContainer> Result<T> lookup(Class<?> indexedType, Object query) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Node createNode() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T convert(Object value, Class<T> type) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.neo4j.kernel.EmbeddedGraphDatabase;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.data.neo4j.model.PersonRepository;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
@@ -38,8 +37,6 @@ public class DataGraphNamespaceHandlerTest {
|
||||
@Autowired
|
||||
GraphDatabaseService graphDatabaseService;
|
||||
@Autowired
|
||||
DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
@Autowired
|
||||
GraphDatabaseContext graphDatabaseContext;
|
||||
@Autowired
|
||||
PlatformTransactionManager transactionManager;
|
||||
@@ -69,7 +66,6 @@ public class DataGraphNamespaceHandlerTest {
|
||||
Assert.assertNotNull("graphDatabaseContext", graphDatabaseContext);
|
||||
EmbeddedGraphDatabase graphDatabaseService = (EmbeddedGraphDatabase) graphDatabaseContext.getGraphDatabaseService();
|
||||
Assert.assertEquals("store-dir", "target/config-test", graphDatabaseService.getStoreDir());
|
||||
Assert.assertNotNull("graphRepositoryFactory",config.graphRepositoryFactory);
|
||||
Assert.assertNotNull("graphDatabaseService",config.graphDatabaseService);
|
||||
Assert.assertNotNull("transactionManager",config.transactionManager);
|
||||
config.graphDatabaseService.shutdown();
|
||||
|
||||
@@ -0,0 +1,353 @@
|
||||
/**
|
||||
* 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.template;
|
||||
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.kernel.Traversal;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.data.neo4j.conversion.ResultConverter;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.model.Person;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
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.Iterator;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.neo4j.helpers.collection.MapUtil.map;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:template-config-context.xml"})
|
||||
public class GraphDatabaseContextTemplateTest {
|
||||
private static final DynamicRelationshipType KNOWS = DynamicRelationshipType.withName("knows");
|
||||
private static final DynamicRelationshipType HAS = DynamicRelationshipType.withName("has");
|
||||
@Autowired
|
||||
GraphDatabaseContext template;
|
||||
protected GraphDatabase graphDatabase;
|
||||
protected Node referenceNode;
|
||||
protected Relationship relationship1;
|
||||
protected Node node1;
|
||||
@Autowired
|
||||
PlatformTransactionManager transactionManager;
|
||||
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(template);
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
Neo4jHelper.cleanDb(template);
|
||||
graphDatabase = template.getGraphDatabase();
|
||||
referenceNode = graphDatabase.getReferenceNode();
|
||||
createData();
|
||||
}
|
||||
|
||||
private void createData() {
|
||||
|
||||
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
referenceNode.setProperty("name", "node0");
|
||||
graphDatabase.createIndex(Node.class, "node", false).add(referenceNode, "name", "node0");
|
||||
node1 = graphDatabase.createNode(map("name", "node1"));
|
||||
relationship1 = referenceNode.createRelationshipTo(node1, KNOWS);
|
||||
relationship1.setProperty("name", "rel1");
|
||||
graphDatabase.createIndex(Relationship.class, "relationship", false).add(relationship1, "name", "rel1");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExecuteCallbackInTransaction() throws Exception {
|
||||
Node refNode = template.exec(new GraphCallback<Node>() {
|
||||
@Override
|
||||
public Node doWithGraph(GraphDatabase graph) throws Exception {
|
||||
Node referenceNode = graph.getReferenceNode();
|
||||
referenceNode.setProperty("test", "testDoInTransaction");
|
||||
return referenceNode;
|
||||
}
|
||||
});
|
||||
assertEquals("same reference node", referenceNode, refNode);
|
||||
assertTestPropertySet(referenceNode, "testDoInTransaction");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRollbackTransactionOnException() {
|
||||
try {
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabase graph) throws Exception {
|
||||
graph.getReferenceNode().setProperty("test", "shouldRollbackTransactionOnException");
|
||||
throw new RuntimeException("please rollback");
|
||||
}
|
||||
});
|
||||
} catch (RuntimeException re) {
|
||||
System.out.println(re.getMessage());
|
||||
}
|
||||
Assert.assertThat((String) graphDatabase.getReferenceNode().getProperty("test", "not set"), not("shouldRollbackTransactionOnException"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldRollbackViaStatus() throws Exception {
|
||||
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(final TransactionStatus status) {
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabase graph) throws Exception {
|
||||
graph.getReferenceNode().setProperty("test", "shouldRollbackTransactionOnException");
|
||||
status.setRollbackOnly();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
Assert.assertThat((String) graphDatabase.getReferenceNode().getProperty("test", "not set"), not("shouldRollbackTransactionOnException"));
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void shouldNotConvertUserRuntimeExceptionToDataAccessException() {
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabase graph) throws Exception {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void shouldConvertMissingTransactionExceptionToDataAccessException() {
|
||||
Neo4jTemplate template = new Neo4jTemplate(graphDatabase, null);
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabase graph) throws Exception {
|
||||
graph.createNode(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void shouldConvertNotFoundExceptionToDataAccessException() {
|
||||
Neo4jTemplate template = new Neo4jTemplate(graphDatabase, transactionManager);
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabase graph) throws Exception {
|
||||
graph.getNodeById(Long.MAX_VALUE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void shouldConvertTemplateNotFoundExceptionToDataAccessException() {
|
||||
template.getNode(Long.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExecuteCallback() throws Exception {
|
||||
Long refNodeId = template.exec(new GraphCallback<Long>() {
|
||||
@Override
|
||||
public Long doWithGraph(GraphDatabase graph) throws Exception {
|
||||
return graph.getReferenceNode().getId();
|
||||
}
|
||||
});
|
||||
assertEquals(referenceNode.getId(), (long) refNodeId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetReferenceNode() throws Exception {
|
||||
assertEquals(referenceNode, template.getReferenceNode());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateNode() throws Exception {
|
||||
Node node = template.createNode(null);
|
||||
assertNotNull("created node", node);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateEntityWithProperties() throws Exception {
|
||||
Person person = template.createNode(Person.class, map("name", "name"));
|
||||
assertNotNull("created node", person);
|
||||
assertEquals("property created", "name", person.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateNodeTypeWithProperties() throws Exception {
|
||||
Node person = template.createNode(Node.class, map("name", "name"));
|
||||
assertNotNull("created node", person);
|
||||
assertEquals("property created", "name", person.getProperty("name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testCreateNodeWithProperties() throws Exception {
|
||||
Node node = template.createNode(map("test", "testCreateNodeWithProperties"));
|
||||
assertTestPropertySet(node, "testCreateNodeWithProperties");
|
||||
}
|
||||
|
||||
private void assertTestPropertySet(Node node, String testName) {
|
||||
assertEquals(testName, node.getProperty("test", "not set"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetNode() throws Exception {
|
||||
Node lookedUpNode = template.getNode(referenceNode.getId());
|
||||
assertEquals(referenceNode, lookedUpNode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRelationship() throws Exception {
|
||||
Relationship lookedUpRelationship = template.getRelationship(relationship1.getId());
|
||||
assertThat(lookedUpRelationship, is(relationship1));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndexRelationship() throws Exception {
|
||||
Index<Relationship> index = graphDatabase.getIndex("relationship");
|
||||
Relationship lookedUpRelationship = index.get("name", "rel1").getSingle();
|
||||
assertThat("same relationship from index", lookedUpRelationship, is(relationship1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndexNode() throws Exception {
|
||||
template.index("node", node1, "name", "node1");
|
||||
Index<Node> index = graphDatabase.getIndex("node");
|
||||
Node lookedUpNode = index.get("name", "node1").getSingle();
|
||||
assertThat("same node from index", lookedUpNode, is(node1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryNodes() throws Exception {
|
||||
assertSingleResult("node0", template.lookup("node", new TermQuery(new Term("name", "node0"))).to(String.class, new PropertyContainerNameConverter()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveNodes() throws Exception {
|
||||
assertSingleResult("node0", template.lookup("node", "name", "node0").to(String.class, new PropertyContainerNameConverter()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryRelationships() throws Exception {
|
||||
assertSingleResult("rel1", template.lookup("relationship", new TermQuery(new Term("name", "rel1"))).to(String.class, new PropertyContainerNameConverter()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRetrieveRelationships() throws Exception {
|
||||
assertSingleResult("rel1", template.lookup("relationship", "name", "rel1").to(String.class, new PropertyContainerNameConverter()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testTraverse() throws Exception {
|
||||
final TraversalDescription description = Traversal.description().relationships(KNOWS).prune(Traversal.pruneAfterDepth(1)).filter(Traversal.returnAllButStartNode());
|
||||
assertSingleResult("node1", template.traverse(referenceNode, description).to(String.class, new PathNodeNameMapper()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFindNextNodeViaCypher() throws Exception {
|
||||
assertSingleResult(node1, template.query("start n=node(0) match n-->m return m", null).to(Node.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldFindNextNodeViaGremlin() throws Exception {
|
||||
assertSingleResult(node1, template.execute("g.v(0).out", null).to(Node.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetDirectRelationship() throws Exception {
|
||||
assertSingleResult("rel1", template.convert(referenceNode.getRelationships()).to(String.class, new RelationshipNameConverter()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetDirectRelationshipForType() throws Exception {
|
||||
assertSingleResult("rel1", template.convert(referenceNode.getRelationships(KNOWS)).to(String.class, new RelationshipNameConverter()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGetDirectRelationshipForTypeAndDirection() throws Exception {
|
||||
assertSingleResult("rel1", template.convert(referenceNode.getRelationships(KNOWS, Direction.OUTGOING)).to(String.class, new RelationshipNameConverter()));
|
||||
}
|
||||
|
||||
private <T> void assertSingleResult(T expected, Iterable<T> iterable) {
|
||||
Iterator<T> result = iterable.iterator();
|
||||
assertEquals(expected, result.next());
|
||||
assertEquals(false, result.hasNext());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldCreateRelationshipWithProperty() throws Exception {
|
||||
Relationship relationship = template.createRelationship(referenceNode, node1, HAS, map("name", "rel2"));
|
||||
assertNotNull(relationship);
|
||||
assertEquals(referenceNode, relationship.getStartNode());
|
||||
assertEquals(node1, relationship.getEndNode());
|
||||
assertEquals(HAS.name(), relationship.getType().name());
|
||||
assertEquals("rel2", relationship.getProperty("name", "not set"));
|
||||
}
|
||||
|
||||
private static class PathRelationshipNameMapper implements ResultConverter<Path, String> {
|
||||
@Override
|
||||
public String convert(Path path, Class<String> type) {
|
||||
return (String) path.lastRelationship().getProperty("name", "not set");
|
||||
}
|
||||
}
|
||||
|
||||
private static class PathNodeNameMapper implements ResultConverter<Path, String> {
|
||||
@Override
|
||||
public String convert(Path path, Class<String> type) {
|
||||
return (String) path.endNode().getProperty("name", "not set");
|
||||
}
|
||||
}
|
||||
|
||||
private static class RelationshipNameConverter implements ResultConverter<Relationship, String> {
|
||||
@Override
|
||||
public String convert(Relationship value, Class<String> type) {
|
||||
return (String) value.getProperty("name");
|
||||
}
|
||||
}
|
||||
|
||||
private static class PropertyContainerNameConverter implements ResultConverter<PropertyContainer, String> {
|
||||
@Override
|
||||
public String convert(PropertyContainer value, Class<String> type) {
|
||||
return (String) value.getProperty("name");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import org.neo4j.graphdb.RelationshipType;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.kernel.Traversal;
|
||||
import org.springframework.data.neo4j.conversion.Handler;
|
||||
import org.springframework.data.neo4j.conversion.QueryResult;
|
||||
import org.springframework.data.neo4j.conversion.Result;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
|
||||
import java.util.HashSet;
|
||||
@@ -52,7 +52,7 @@ public class NeoTraversalTest extends NeoApiTest {
|
||||
|
||||
final Set<String> resultSet = new HashSet<String>();
|
||||
@SuppressWarnings("deprecation") final TraversalDescription description = Traversal.description().relationships(HAS).filter(returnAllButStartNode()).prune(Traversal.pruneAfterDepth(2));
|
||||
final QueryResult<Path> queryResult = template.traverse(template.getReferenceNode(), description);
|
||||
final Result<Path> queryResult = template.traverse(template.getReferenceNode(), description);
|
||||
queryResult.handle(new Handler<Path>() {
|
||||
@Override
|
||||
public void handle(Path value) {
|
||||
|
||||
@@ -12,4 +12,5 @@
|
||||
<neo4j:config graphDatabaseService="graphDatabaseService"/>
|
||||
<neo4j:repositories base-package="org.springframework.data.neo4j.model"/>
|
||||
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase"/>
|
||||
<tx:annotation-driven/>
|
||||
</beans>
|
||||
@@ -49,7 +49,7 @@
|
||||
public HelloWorldInitializer() {
|
||||
super(new String[]{"spring/helloWorldServer-Context.xml"},
|
||||
Pair.of("worldRepository", WorldRepository.class),
|
||||
Pair.of("graphRepositoryFactory", GraphRepositoryFactory.class));
|
||||
Pair.of("template", Neo4jTemplate.class));
|
||||
}
|
||||
}
|
||||
]]></programlisting>
|
||||
|
||||
@@ -45,8 +45,7 @@ class Person {
|
||||
@Indexed int age;
|
||||
}
|
||||
|
||||
GraphRepository<Person> graphRepository = graphRepositoryFactory
|
||||
.createGraphRepository(Person.class);
|
||||
GraphRepository<Person> graphRepository = template.repositoryFor(Person.class);
|
||||
|
||||
// Exact match, in named index
|
||||
Person mark = graphRepository.findByPropertyValue("people", "name", "mark");
|
||||
@@ -84,8 +83,8 @@ class Person {
|
||||
@Indexed(indexName = "people-search", fulltext=true) String name;
|
||||
}
|
||||
|
||||
GraphRepository<Person> graphRepository = graphRepositoryFactory
|
||||
.createGraphRepository(Person.class);
|
||||
GraphRepository<Person> graphRepository =
|
||||
template.repositoryFor(Person.class);
|
||||
|
||||
Person mark = graphRepository.findAllByQuery("people-search", "name", "ma*");
|
||||
]]></programlisting>
|
||||
|
||||
@@ -201,8 +201,8 @@
|
||||
</para>
|
||||
<example>
|
||||
<title>Using GraphRepositories</title>
|
||||
<programlisting language="java"><![CDATA[GraphRepository<Person> graphRepository = graphRepositoryFactory
|
||||
.createGraphRepository(Person.class);
|
||||
<programlisting language="java"><![CDATA[GraphRepository<Person> graphRepository = template
|
||||
.repositoryFor(Person.class);
|
||||
|
||||
Person michael = graphRepository.save(new Person("Michael", 36));
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
int year;
|
||||
}
|
||||
|
||||
@Autowired DirectGraphRepositoryFactory graphRepositoryFactory;
|
||||
@Autowired Neo4jTemplate template;
|
||||
|
||||
@Test public void persistedMovieShouldBeRetrievableFromGraphDb() {
|
||||
int id = 1;
|
||||
Movie forrestGump = new Movie(id, "Forrest Gump", 1994).persist();
|
||||
GraphRepository<Movie> movieRepository =
|
||||
graphRepositoryFactory.createGraphRepository(Movie.class);
|
||||
template.repositoryFor(Movie.class);
|
||||
Movie retrievedMovie = movieRepository.findByPropertyValue("id", id);
|
||||
assertEqual("retrieved movie matches persisted one", forrestGump, retrievedMovie);
|
||||
assertEqual("retrieved movie title matches", "Forrest Gump", retrievedMovie.getTitle());
|
||||
|
||||
Reference in New Issue
Block a user