Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: PojoMetadata now prefers getter/setter with more concrete types #315

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions core/src/main/java/org/sql2o/reflection/PojoMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,10 @@ private PropertyAndFieldInfo initializePropertyInfo() {

// prepare methods. Methods will override fields, if both exists.
for (Method m : theClass.getDeclaredMethods()) {
if (m.isBridge()) {
// skip bridge methods: https://github.com/aaberg/sql2o/issues/314
continue;
}

if (m.getName().startsWith("get")) {
String propertyName = m.getName().substring(3);
Expand All @@ -123,7 +127,6 @@ private PropertyAndFieldInfo initializePropertyInfo() {
} else {
propertyName = propertyName.toLowerCase();
}

propertyGetters.put(propertyName, factoryFacade.newGetter(m));
}

Expand All @@ -137,7 +140,6 @@ private PropertyAndFieldInfo initializePropertyInfo() {
} else {
propertyName = propertyName.toLowerCase();
}

propertySetters.put(propertyName, factoryFacade.newSetter(m));
}
}
Expand Down
64 changes: 64 additions & 0 deletions core/src/test/java/org/sql2o/reflection/PojoMetadataTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package org.sql2o.reflection;

import javassist.*;
import org.junit.Test;

import java.util.HashMap;
import java.util.UUID;

import static org.junit.Assert.*;

/**
* Tests the {@link PojoMetadata} class.
* @author mavi
*/
public class PojoMetadataTest {
/**
* Tests that when there are two getters with different return types, the one with more concrete type is preferred.
* See https://github.com/aaberg/sql2o/issues/314 for more details.
*/
@Test
public void testPrefersGetterWithMoreConcreteType() throws Exception {
Class<?> clazz = createClassWithGetters();
final PojoMetadata metadata = new PojoMetadata(clazz, false, false, new HashMap<String, String>(), true);
assertEquals(String.class, metadata.getPropertyGetter("id").getType());
}

/**
* Tests that when there are two setters with different return types, the one with more concrete type is preferred.
* See https://github.com/aaberg/sql2o/issues/314 for more details.
*/
@Test
public void testPrefersSetterWithMoreConcreteType() throws Exception {
Class<?> clazz = createClassWithSetters();
final PojoMetadata metadata = new PojoMetadata(clazz, false, false, new HashMap<String, String>(), true);
assertEquals(String.class, metadata.getPropertySetter("id").getType());
}

private Class<?> createClassWithGetters() throws CannotCompileException, NotFoundException {
final ClassPool pool = ClassPool.getDefault();
final CtClass ctClass = pool.makeClass("my.test.Klass" + UUID.randomUUID().toString().replace("-", ""));
ctClass.addField(new CtField(pool.get("java.lang.String"), "id", ctClass));
ctClass.addMethod(withBridge(CtNewMethod.make("public Object getId() { return id; }", ctClass)));
ctClass.addMethod(CtNewMethod.make("public String getId() { return id; }", ctClass));
final Class<?> clazz = ctClass.toClass();
assertEquals(2, clazz.getDeclaredMethods().length);
return clazz;
}

private Class<?> createClassWithSetters() throws CannotCompileException, NotFoundException {
final ClassPool pool = ClassPool.getDefault();
final CtClass ctClass = pool.makeClass("my.test.Klass" + UUID.randomUUID().toString().replace("-", ""));
ctClass.addField(new CtField(pool.get("java.lang.Object"), "id", ctClass));
ctClass.addMethod(withBridge(CtNewMethod.make("public void setId(Object id) { this.id = id; }", ctClass)));
ctClass.addMethod(CtNewMethod.make("public void setId(String id) { this.id = id; }", ctClass));
final Class<?> clazz = ctClass.toClass();
assertEquals(2, clazz.getDeclaredMethods().length);
return clazz;
}

private static CtMethod withBridge(CtMethod method) {
method.setModifiers(method.getModifiers() | 0x00000040); // Modifier.BRIDGE field not public :(
return method;
}
}