Skip to content

Commit

Permalink
DATAGRAPH-325 Cannot return a set from a query with Neo4j (hashcode R…
Browse files Browse the repository at this point in the history
…esultColumn problem)
  • Loading branch information
jexp committed May 28, 2013
1 parent dbea0e8 commit 65422a5
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@
import java.lang.reflect.Proxy;
import java.util.Map;

public class QueryMapResulConverter<T> implements ResultConverter<Map<String, Object>, T> {
public class QueryMapResultConverter<T> implements ResultConverter<Map<String, Object>, T> {
private final Neo4jOperations template;

public QueryMapResulConverter(Neo4jOperations template) {
public QueryMapResultConverter(Neo4jOperations template) {
this.template = template;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

/**
Expand All @@ -44,7 +45,15 @@ public QueryResultProxy(Map<String, Object> map, MappingPolicy mappingPolicy, Re

@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);

Expand Down Expand Up @@ -93,4 +102,28 @@ private Class implementsInterface(String interfaceName, Class clazz) {

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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,15 @@
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;
Expand Down Expand Up @@ -77,7 +81,7 @@ public void init() throws Exception {

@Test
public void shouldBeAbleToGetAStringFromAResultMap() throws Exception {
QueryMapResulConverter<SimplestQuery> converter = getConverter();
QueryMapResultConverter<SimplestQuery> converter = getConverter();
SimplestQuery query = converter.convert( simpleMap, SimplestQuery.class );

assertThat( query.getName(), equalTo( "Andres" ) );
Expand All @@ -86,15 +90,15 @@ public void shouldBeAbleToGetAStringFromAResultMap() throws Exception {

@Test
public void shouldBeAbleToHandleAnIterableOfString() throws Exception {
QueryMapResulConverter<SimplestQuery> converter = getConverter();
QueryMapResultConverter<SimplestQuery> converter = getConverter();
SimplestQuery query = converter.convert( simpleMap, SimplestQuery.class );

assertThat( query.getFriendNames(), hasItems( "Michael", "Emil", "Anders" ) );
}

@Test
public void shouldHandleANodeBackedEntity() throws Exception {
QueryMapResulConverter<PersonAndFriendsData> converter = new QueryMapResulConverter<PersonAndFriendsData>(
QueryMapResultConverter<PersonAndFriendsData> converter = new QueryMapResultConverter<PersonAndFriendsData>(
template );
PersonAndFriendsData result = converter.convert( advancedMap, PersonAndFriendsData.class );

Expand All @@ -104,13 +108,47 @@ public void shouldHandleANodeBackedEntity() throws Exception {

@Test( expected = NoSuchColumnFoundException.class )
public void shouldThrowNiceException() throws Exception {
QueryMapResulConverter<PersonAndFriendsData> converter = new QueryMapResulConverter<PersonAndFriendsData>(
QueryMapResultConverter<PersonAndFriendsData> converter = new QueryMapResultConverter<PersonAndFriendsData>(
template );
PersonAndFriendsData convert = converter.convert( map(), PersonAndFriendsData.class );
convert.getFriends();
}

private QueryMapResulConverter<SimplestQuery> getConverter() {
return new QueryMapResulConverter<SimplestQuery>( template );
@Test
public void testShouldBeAbleToCompareTwoResults() throws Exception {
QueryMapResultConverter<SimplestQuery> 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<String, Object>(simpleMap), SimplestQuery.class);

final HashMap<String, Object> copy = new HashMap<String, Object>(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<SimplestQuery> converter = getConverter();

final SimplestQuery query1 = converter.convert(simpleMap, SimplestQuery.class);
final SimplestQuery query2 = converter.convert(simpleMap, SimplestQuery.class);
Set<SimplestQuery> set=new HashSet<SimplestQuery>();
set.add(query1);

assertEquals(true,set.contains(query1));
assertEquals(true,set.contains(query2));

}

private QueryMapResultConverter<SimplestQuery> getConverter() {
return new QueryMapResultConverter<SimplestQuery>( template );
}
}

0 comments on commit 65422a5

Please sign in to comment.