Add element type handling

This commit is contained in:
Timo Westkämper 2014-10-11 11:53:45 +03:00
parent d75f157f90
commit 7d6de92d79
4 changed files with 62 additions and 15 deletions

View File

@ -13,10 +13,14 @@
*/
package com.mysema.query.types.path;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;
import com.google.common.primitives.Primitives;
import com.mysema.util.BeanUtils;
import com.mysema.util.ReflectionUtils;
/**
* PathBuilderValidator validates PathBuilder properties at creation time
@ -44,7 +48,14 @@ public interface PathBuilderValidator {
public <T> Class<? extends T> validate(Class<?> parent, String property, Class<T> propertyType) {
while (!parent.equals(Object.class)) {
try {
return (Class<? extends T>) parent.getDeclaredField(property).getType();
Field field = parent.getDeclaredField(property);
if (Map.class.isAssignableFrom(field.getType())) {
return (Class) ReflectionUtils.getTypeParameterAsClass(field.getGenericType(), 1);
} else if (Collection.class.isAssignableFrom(field.getType())) {
return (Class) ReflectionUtils.getTypeParameterAsClass(field.getGenericType(), 0);
} else {
return (Class) Primitives.wrap(field.getType());
}
} catch (NoSuchFieldException e) {
parent = parent.getSuperclass();
}
@ -60,7 +71,17 @@ public interface PathBuilderValidator {
if (getter == null && Primitives.wrap(propertyType).equals(Boolean.class)) {
getter = BeanUtils.getAccessor("is", property, parent);
}
return getter != null ? (Class<? extends T>) getter.getReturnType() : null;
if (getter != null) {
if (Map.class.isAssignableFrom(getter.getReturnType())) {
return (Class) ReflectionUtils.getTypeParameterAsClass(getter.getGenericReturnType(), 1);
} else if (Collection.class.isAssignableFrom(getter.getReturnType())) {
return (Class) ReflectionUtils.getTypeParameterAsClass(getter.getGenericReturnType(), 0);
} else {
return (Class) Primitives.wrap(getter.getReturnType());
}
} else {
return null;
}
}
};

View File

@ -1,18 +1,26 @@
package com.mysema.query.types.path;
import java.util.Collection;
import java.util.Map;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
public class PathBuilderValidatorTest {
public static class Customer {
String name;
Collection<Integer> collection;
Map<String, Integer> map;
}
public static class ExtendedCustomer extends Customer {}
public static class Project {
public String getName() { return ""; }
public Collection<Integer> getCollection() { return null; }
public Map<String, Integer> getMap() { return null; }
}
public static class ExtendedProject extends Project {
@ -21,16 +29,18 @@ public class PathBuilderValidatorTest {
@Test
public void Default() {
assertNotNull(PathBuilderValidator.DEFAULT.validate(Customer.class, "name", String.class));
assertNotNull(PathBuilderValidator.DEFAULT.validate(ExtendedCustomer.class, "name", String.class));
assertNotNull(PathBuilderValidator.DEFAULT.validate(Project.class, "name", String.class));
assertNotNull(PathBuilderValidator.DEFAULT.validate(ExtendedProject.class, "name", String.class));
assertEquals(String.class, PathBuilderValidator.DEFAULT.validate(Customer.class, "name", String.class));
assertEquals(String.class, PathBuilderValidator.DEFAULT.validate(ExtendedCustomer.class, "name", String.class));
assertEquals(String.class, PathBuilderValidator.DEFAULT.validate(Project.class, "name", String.class));
assertEquals(String.class, PathBuilderValidator.DEFAULT.validate(ExtendedProject.class, "name", String.class));
}
@Test
public void Fields() {
assertNotNull(PathBuilderValidator.FIELDS.validate(Customer.class, "name", String.class));
assertNotNull(PathBuilderValidator.FIELDS.validate(ExtendedCustomer.class, "name", String.class));
assertEquals(String.class, PathBuilderValidator.FIELDS.validate(Customer.class, "name", String.class));
assertEquals(String.class, PathBuilderValidator.FIELDS.validate(ExtendedCustomer.class, "name", String.class));
assertEquals(Integer.class, PathBuilderValidator.FIELDS.validate(Customer.class, "collection", Collection.class));
assertEquals(Integer.class, PathBuilderValidator.FIELDS.validate(Customer.class, "map", Map.class));
assertNull(PathBuilderValidator.FIELDS.validate(Project.class, "name", String.class));
assertNull(PathBuilderValidator.FIELDS.validate(ExtendedProject.class, "name", String.class));
}
@ -39,8 +49,10 @@ public class PathBuilderValidatorTest {
public void Properties() {
assertNull(PathBuilderValidator.PROPERTIES.validate(Customer.class, "name", String.class));
assertNull(PathBuilderValidator.PROPERTIES.validate(ExtendedCustomer.class, "name", String.class));
assertNotNull(PathBuilderValidator.PROPERTIES.validate(Project.class, "name", String.class));
assertNotNull(PathBuilderValidator.PROPERTIES.validate(ExtendedProject.class, "name", String.class));
assertNotNull(PathBuilderValidator.PROPERTIES.validate(ExtendedProject.class, "started", Boolean.class));
assertEquals(String.class, PathBuilderValidator.PROPERTIES.validate(Project.class, "name", String.class));
assertEquals(String.class, PathBuilderValidator.PROPERTIES.validate(ExtendedProject.class, "name", String.class));
assertEquals(Boolean.class, PathBuilderValidator.PROPERTIES.validate(ExtendedProject.class, "started", Boolean.class));
assertEquals(Integer.class, PathBuilderValidator.PROPERTIES.validate(Project.class, "collection", Collection.class));
assertEquals(Integer.class, PathBuilderValidator.PROPERTIES.validate(Project.class, "map", Map.class));
}
}

View File

@ -14,8 +14,12 @@
package com.mysema.query.jpa.support;
import javax.persistence.EntityManager;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.ManagedType;
import javax.persistence.metamodel.Metamodel;
import javax.persistence.metamodel.PluralAttribute;
import com.google.common.primitives.Primitives;
import com.mysema.query.types.path.PathBuilderValidator;
/**
@ -36,7 +40,13 @@ public class JPAPathBuilderValidator implements PathBuilderValidator {
@Override
public <T> Class<? extends T> validate(Class<?> parent, String property, Class<T> propertyType) {
try {
return (Class)metamodel.managedType(parent).getAttribute(property).getJavaType();
ManagedType managedType = metamodel.managedType(parent);
Attribute attribute = managedType.getAttribute(property);
if (attribute instanceof PluralAttribute) {
return ((PluralAttribute)attribute).getElementType().getJavaType();
} else {
return Primitives.wrap(attribute.getJavaType());
}
} catch (IllegalArgumentException e) {
return null;
}

View File

@ -2,12 +2,14 @@ package com.mysema.query.jpa.support;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import java.util.Collection;
import com.mysema.query.jpa.domain.Cat;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
public class JPAPathBuilderValidatorTest {
@ -26,7 +28,9 @@ public class JPAPathBuilderValidatorTest {
@Test
public void validate() {
JPAPathBuilderValidator validator = new JPAPathBuilderValidator(entityManagerFactory.getMetamodel());
assertNotNull(validator.validate(Cat.class, "name", String.class));
assertEquals(String.class, validator.validate(Cat.class, "name", String.class));
assertEquals(Cat.class, validator.validate(Cat.class, "kittens", Collection.class));
assertEquals(Cat.class, validator.validate(Cat.class, "mate", Cat.class));
assertNull(validator.validate(Cat.class, "xxx", String.class));
assertNull(validator.validate(Object.class, "name", String.class));
}