diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResulConverter.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResultConverter.java similarity index 90% rename from spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResulConverter.java rename to spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResultConverter.java index 1d65f7dd8..98eb56388 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResulConverter.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/conversion/QueryMapResultConverter.java @@ -22,10 +22,10 @@ import org.springframework.data.neo4j.template.Neo4jOperations; import java.lang.reflect.Proxy; import java.util.Map; -public class QueryMapResulConverter implements ResultConverter, T> { +public class QueryMapResultConverter implements ResultConverter, T> { private final Neo4jOperations template; - public QueryMapResulConverter(Neo4jOperations template) { + public QueryMapResultConverter(Neo4jOperations template) { this.template = template; } diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/QueryResultProxy.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/QueryResultProxy.java index 852b684e9..5f52caffd 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/QueryResultProxy.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/support/conversion/QueryResultProxy.java @@ -25,6 +25,7 @@ import org.springframework.data.util.TypeInformation; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.util.Map; /** @@ -44,7 +45,15 @@ public class QueryResultProxy implements InvocationHandler { @SuppressWarnings("unchecked") @Override - public Object invoke(Object o, Method method, Object[] objects) throws Throwable { + public Object invoke(Object proxy, Method method, Object[] params) throws Throwable { + if (OBJECT_EQUALS.equals(method)) { + return equalsInternal(proxy, params[0]); + } + + if (OBJECT_HASHCODE.equals(method)) { + return map.hashCode(); + } + ResultColumn column = method.getAnnotation(ResultColumn.class); TypeInformation returnType = ClassTypeInformation.fromReturnTypeOf(method); @@ -93,4 +102,28 @@ public class QueryResultProxy implements InvocationHandler { return null; } + + private static final Method OBJECT_EQUALS = getObjectMethod("equals", Object.class); + + private static final Method OBJECT_HASHCODE = getObjectMethod("hashCode"); + + private boolean equalsInternal(Object me, Object other) { + if (other == null) { + return false; + } + if (other.getClass() != me.getClass()) { + return false; + } + InvocationHandler handler = Proxy.getInvocationHandler(other); + if (!(handler instanceof QueryResultProxy)) return false; + return ((QueryResultProxy) handler).map.equals(map); + } + + private static Method getObjectMethod(String name, Class... types) { + try { + return Object.class.getMethod(name, types); + } catch (NoSuchMethodException e) { + throw new IllegalArgumentException(e); + } + } } diff --git a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/conversion/QueryMapResultConverterTests.java b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/conversion/QueryMapResultConverterTests.java index 2680ba1df..39e181204 100644 --- a/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/conversion/QueryMapResultConverterTests.java +++ b/spring-data-neo4j/src/test/java/org/springframework/data/neo4j/conversion/QueryMapResultConverterTests.java @@ -23,11 +23,15 @@ import org.springframework.data.neo4j.model.Friendship; import org.springframework.data.neo4j.model.Person; import org.springframework.data.neo4j.support.conversion.NoSuchColumnFoundException; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import static java.util.Arrays.asList; import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.matchers.JUnitMatchers.hasItems; import static org.neo4j.helpers.collection.IteratorUtil.asCollection; @@ -77,7 +81,7 @@ public class QueryMapResultConverterTests extends Neo4jPersistentTestBase { @Test public void shouldBeAbleToGetAStringFromAResultMap() throws Exception { - QueryMapResulConverter converter = getConverter(); + QueryMapResultConverter converter = getConverter(); SimplestQuery query = converter.convert( simpleMap, SimplestQuery.class ); assertThat( query.getName(), equalTo( "Andres" ) ); @@ -86,7 +90,7 @@ public class QueryMapResultConverterTests extends Neo4jPersistentTestBase { @Test public void shouldBeAbleToHandleAnIterableOfString() throws Exception { - QueryMapResulConverter converter = getConverter(); + QueryMapResultConverter converter = getConverter(); SimplestQuery query = converter.convert( simpleMap, SimplestQuery.class ); assertThat( query.getFriendNames(), hasItems( "Michael", "Emil", "Anders" ) ); @@ -94,7 +98,7 @@ public class QueryMapResultConverterTests extends Neo4jPersistentTestBase { @Test public void shouldHandleANodeBackedEntity() throws Exception { - QueryMapResulConverter converter = new QueryMapResulConverter( + QueryMapResultConverter converter = new QueryMapResultConverter( template ); PersonAndFriendsData result = converter.convert( advancedMap, PersonAndFriendsData.class ); @@ -104,13 +108,47 @@ public class QueryMapResultConverterTests extends Neo4jPersistentTestBase { @Test( expected = NoSuchColumnFoundException.class ) public void shouldThrowNiceException() throws Exception { - QueryMapResulConverter converter = new QueryMapResulConverter( + QueryMapResultConverter converter = new QueryMapResultConverter( template ); PersonAndFriendsData convert = converter.convert( map(), PersonAndFriendsData.class ); convert.getFriends(); } - private QueryMapResulConverter getConverter() { - return new QueryMapResulConverter( template ); + @Test + public void testShouldBeAbleToCompareTwoResults() throws Exception { + QueryMapResultConverter converter = getConverter(); + + final SimplestQuery query1 = converter.convert(simpleMap, SimplestQuery.class); + final SimplestQuery query2 = converter.convert(simpleMap, SimplestQuery.class); + final SimplestQuery query1Clone = converter.convert(new HashMap(simpleMap), SimplestQuery.class); + + final HashMap copy = new HashMap(simpleMap); + copy.put("name", "Michael"); + final SimplestQuery otherQuery = converter.convert(copy, SimplestQuery.class); + + assertEquals(query1.hashCode(),query2.hashCode()); + assertEquals(query1,query2); + assertEquals(query1, query1Clone); + assertEquals(query1.hashCode(), query1Clone.hashCode()); + assertEquals(false, query1.equals(otherQuery)); + assertEquals(false, query1.hashCode() == otherQuery.hashCode()); + } + + @Test + public void testPutQueryResultsInSet() throws Exception { + QueryMapResultConverter converter = getConverter(); + + final SimplestQuery query1 = converter.convert(simpleMap, SimplestQuery.class); + final SimplestQuery query2 = converter.convert(simpleMap, SimplestQuery.class); + Set set=new HashSet(); + set.add(query1); + + assertEquals(true,set.contains(query1)); + assertEquals(true,set.contains(query2)); + + } + + private QueryMapResultConverter getConverter() { + return new QueryMapResultConverter( template ); } } \ No newline at end of file