mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 15:07:14 +00:00
No effective change - reformat code
This commit is contained in:
@@ -11,118 +11,118 @@ import java.lang.reflect.Modifier;
|
||||
|
||||
public class CheckImmutable {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CheckImmutable.class);
|
||||
|
||||
private final KnownImmutable knownImmutable;
|
||||
private static final Logger logger = LoggerFactory.getLogger(CheckImmutable.class);
|
||||
|
||||
public CheckImmutable(KnownImmutable knownImmutable) {
|
||||
this.knownImmutable = knownImmutable;
|
||||
}
|
||||
|
||||
public CheckImmutableResponse checkImmutable(Class<?> cls) {
|
||||
private final KnownImmutable knownImmutable;
|
||||
|
||||
CheckImmutableResponse res = new CheckImmutableResponse();
|
||||
|
||||
isImmutable(cls, res);
|
||||
|
||||
if (res.isImmutable()){
|
||||
res.setCompoundType(isCompoundType(cls));
|
||||
}
|
||||
|
||||
return res;
|
||||
public CheckImmutable(KnownImmutable knownImmutable) {
|
||||
this.knownImmutable = knownImmutable;
|
||||
}
|
||||
|
||||
public CheckImmutableResponse checkImmutable(Class<?> cls) {
|
||||
|
||||
CheckImmutableResponse res = new CheckImmutableResponse();
|
||||
|
||||
isImmutable(cls, res);
|
||||
|
||||
if (res.isImmutable()) {
|
||||
res.setCompoundType(isCompoundType(cls));
|
||||
}
|
||||
|
||||
private boolean isCompoundType(Class<?> cls) {
|
||||
|
||||
int maxLength = 0;
|
||||
Constructor<?> chosen = null;
|
||||
|
||||
// find the constructor with the most number of parameters
|
||||
Constructor<?>[] constructors = cls.getConstructors();
|
||||
for (int i = 0; i < constructors.length; i++) {
|
||||
Class<?>[] parameterTypes = constructors[i].getParameterTypes();
|
||||
if (parameterTypes.length > maxLength){
|
||||
maxLength = parameterTypes.length;
|
||||
chosen = constructors[i];
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug("checkImmutable "+cls+" constructor "+chosen);
|
||||
|
||||
return maxLength > 1;
|
||||
}
|
||||
|
||||
private boolean isImmutable(Class<?> cls, CheckImmutableResponse res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
if (knownImmutable.isKnownImmutable(cls)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (cls.isArray()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (hasDefaultConstructor(cls)){
|
||||
// must not have a default constructor to be considered immutable
|
||||
res.setReasonNotImmutable(cls+" has a default constructor");
|
||||
return false;
|
||||
}
|
||||
private boolean isCompoundType(Class<?> cls) {
|
||||
|
||||
// check super class
|
||||
Class<?> superClass = cls.getSuperclass();
|
||||
int maxLength = 0;
|
||||
Constructor<?> chosen = null;
|
||||
|
||||
if (!isImmutable(superClass, res)) {
|
||||
res.setReasonNotImmutable("Super not Immutable " + superClass);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasAllFinalFields(cls, res)){
|
||||
return false;
|
||||
}
|
||||
|
||||
// Lets hope we didn't forget something
|
||||
return true;
|
||||
// find the constructor with the most number of parameters
|
||||
Constructor<?>[] constructors = cls.getConstructors();
|
||||
for (int i = 0; i < constructors.length; i++) {
|
||||
Class<?>[] parameterTypes = constructors[i].getParameterTypes();
|
||||
if (parameterTypes.length > maxLength) {
|
||||
maxLength = parameterTypes.length;
|
||||
chosen = constructors[i];
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasAllFinalFields(Class<?> cls, CheckImmutableResponse res){
|
||||
logger.debug("checkImmutable " + cls + " constructor " + chosen);
|
||||
|
||||
// Check all fields defined in the class for type and if they are final
|
||||
Field[] objFields = cls.getDeclaredFields();
|
||||
for (int i = 0; i < objFields.length; i++) {
|
||||
if (!Modifier.isStatic(objFields[i].getModifiers())) {
|
||||
if (!Modifier.isFinal(objFields[i].getModifiers())) {
|
||||
res.setReasonNotImmutable("Non final field " + cls + "." + objFields[i].getName());
|
||||
return false;
|
||||
}
|
||||
if (!isImmutable(objFields[i].getType(), res)) {
|
||||
res.setReasonNotImmutable("Non Immutable field type " + objFields[i].getType());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return maxLength > 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
private boolean isImmutable(Class<?> cls, CheckImmutableResponse res) {
|
||||
|
||||
|
||||
if (knownImmutable.isKnownImmutable(cls)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private boolean hasDefaultConstructor(Class<?> cls) {
|
||||
|
||||
Class<?>[] noParams = new Class<?>[0];
|
||||
try {
|
||||
cls.getDeclaredConstructor(noParams);
|
||||
return true;
|
||||
|
||||
} catch (SecurityException e) {
|
||||
// this is ok
|
||||
return false;
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
// this is expected for our IVO's
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cls.isArray()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (hasDefaultConstructor(cls)) {
|
||||
// must not have a default constructor to be considered immutable
|
||||
res.setReasonNotImmutable(cls + " has a default constructor");
|
||||
return false;
|
||||
}
|
||||
|
||||
// check super class
|
||||
Class<?> superClass = cls.getSuperclass();
|
||||
|
||||
if (!isImmutable(superClass, res)) {
|
||||
res.setReasonNotImmutable("Super not Immutable " + superClass);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hasAllFinalFields(cls, res)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Lets hope we didn't forget something
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean hasAllFinalFields(Class<?> cls, CheckImmutableResponse res) {
|
||||
|
||||
// Check all fields defined in the class for type and if they are final
|
||||
Field[] objFields = cls.getDeclaredFields();
|
||||
for (int i = 0; i < objFields.length; i++) {
|
||||
if (!Modifier.isStatic(objFields[i].getModifiers())) {
|
||||
if (!Modifier.isFinal(objFields[i].getModifiers())) {
|
||||
res.setReasonNotImmutable("Non final field " + cls + "." + objFields[i].getName());
|
||||
return false;
|
||||
}
|
||||
if (!isImmutable(objFields[i].getType(), res)) {
|
||||
res.setReasonNotImmutable("Non Immutable field type " + objFields[i].getType());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private boolean hasDefaultConstructor(Class<?> cls) {
|
||||
|
||||
Class<?>[] noParams = new Class<?>[0];
|
||||
try {
|
||||
cls.getDeclaredConstructor(noParams);
|
||||
return true;
|
||||
|
||||
} catch (SecurityException e) {
|
||||
// this is ok
|
||||
return false;
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
// this is expected for our IVO's
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+24
-25
@@ -1,37 +1,36 @@
|
||||
package com.avaje.ebeaninternal.server.type.reflect;
|
||||
|
||||
|
||||
|
||||
public class CheckImmutableResponse {
|
||||
|
||||
private boolean immutable = true;
|
||||
|
||||
private String reasonNotImmutable;
|
||||
private boolean immutable = true;
|
||||
|
||||
private boolean compoundType;
|
||||
|
||||
public String toString(){
|
||||
if(immutable){
|
||||
return "immutable";
|
||||
} else {
|
||||
return "not immutable due to:"+reasonNotImmutable;
|
||||
}
|
||||
}
|
||||
private String reasonNotImmutable;
|
||||
|
||||
public boolean isCompoundType() {
|
||||
return compoundType;
|
||||
}
|
||||
private boolean compoundType;
|
||||
|
||||
public void setCompoundType(boolean compoundType) {
|
||||
this.compoundType = compoundType;
|
||||
public String toString() {
|
||||
if (immutable) {
|
||||
return "immutable";
|
||||
} else {
|
||||
return "not immutable due to:" + reasonNotImmutable;
|
||||
}
|
||||
}
|
||||
|
||||
public void setReasonNotImmutable(String error) {
|
||||
this.immutable = false;
|
||||
this.reasonNotImmutable = error;
|
||||
}
|
||||
public boolean isCompoundType() {
|
||||
return compoundType;
|
||||
}
|
||||
|
||||
public boolean isImmutable() {
|
||||
return immutable;
|
||||
}
|
||||
public void setCompoundType(boolean compoundType) {
|
||||
this.compoundType = compoundType;
|
||||
}
|
||||
|
||||
public void setReasonNotImmutable(String error) {
|
||||
this.immutable = false;
|
||||
this.reasonNotImmutable = error;
|
||||
}
|
||||
|
||||
public boolean isImmutable() {
|
||||
return immutable;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,25 +6,25 @@ import java.lang.reflect.Method;
|
||||
|
||||
public class ImmutableMeta {
|
||||
|
||||
private final Constructor<?> constructor;
|
||||
|
||||
private final Method[] readers;
|
||||
|
||||
public ImmutableMeta(Constructor<?> constructor, Method[] readers) {
|
||||
this.constructor = constructor;
|
||||
this.readers = readers;
|
||||
}
|
||||
|
||||
|
||||
public Constructor<?> getConstructor() {
|
||||
return constructor;
|
||||
}
|
||||
private final Constructor<?> constructor;
|
||||
|
||||
public Method[] getReaders() {
|
||||
return readers;
|
||||
}
|
||||
|
||||
public boolean isCompoundType() {
|
||||
return readers.length > 1;
|
||||
}
|
||||
private final Method[] readers;
|
||||
|
||||
public ImmutableMeta(Constructor<?> constructor, Method[] readers) {
|
||||
this.constructor = constructor;
|
||||
this.readers = readers;
|
||||
}
|
||||
|
||||
|
||||
public Constructor<?> getConstructor() {
|
||||
return constructor;
|
||||
}
|
||||
|
||||
public Method[] getReaders() {
|
||||
return readers;
|
||||
}
|
||||
|
||||
public boolean isCompoundType() {
|
||||
return readers.length > 1;
|
||||
}
|
||||
}
|
||||
|
||||
+187
-188
@@ -14,213 +14,212 @@ import java.util.HashSet;
|
||||
|
||||
public class ImmutableMetaFactory {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(ImmutableMetaFactory.class);
|
||||
|
||||
public ImmutableMeta createImmutableMeta(Class<?> cls) {
|
||||
|
||||
ScoreConstructor[] scoreConstructors = scoreConstructors(cls);
|
||||
|
||||
ArrayList<RuntimeException> errors = new ArrayList<RuntimeException>();
|
||||
|
||||
// search the constructors in score order ...
|
||||
// ... we need to find a set of readers for each
|
||||
// ... type in the constructor
|
||||
for (int i = 0; i < scoreConstructors.length; i++) {
|
||||
Constructor<?> constructor = scoreConstructors[i].constructor;
|
||||
private static final Logger logger = LoggerFactory.getLogger(ImmutableMetaFactory.class);
|
||||
|
||||
try {
|
||||
Method[] getters = findGetters(cls, constructor);
|
||||
public ImmutableMeta createImmutableMeta(Class<?> cls) {
|
||||
|
||||
return new ImmutableMeta(constructor, getters);
|
||||
|
||||
} catch (NoSuchMethodException e){
|
||||
String msg = "Error finding getter method on "+cls+" with constructor "+constructor;
|
||||
errors.add(new RuntimeException(msg, e));
|
||||
}
|
||||
}
|
||||
|
||||
String msg = "Was unable to use reflection to find a constructor and appropriate getters for" +
|
||||
"immutable type "+cls+". The errors while looking for the getter methods follow:";
|
||||
logger.error(msg);
|
||||
|
||||
for (RuntimeException runtimeException : errors) {
|
||||
logger.error("Error with " + cls, runtimeException);
|
||||
}
|
||||
ScoreConstructor[] scoreConstructors = scoreConstructors(cls);
|
||||
|
||||
msg = "Unable to use reflection to build ImmutableMeta for " + cls
|
||||
+ ". Associated Errors trying to find a constructor and getter methods have been logged";
|
||||
ArrayList<RuntimeException> errors = new ArrayList<RuntimeException>();
|
||||
|
||||
throw new RuntimeException(msg);
|
||||
// search the constructors in score order ...
|
||||
// ... we need to find a set of readers for each
|
||||
// ... type in the constructor
|
||||
for (int i = 0; i < scoreConstructors.length; i++) {
|
||||
Constructor<?> constructor = scoreConstructors[i].constructor;
|
||||
|
||||
try {
|
||||
Method[] getters = findGetters(cls, constructor);
|
||||
|
||||
return new ImmutableMeta(constructor, getters);
|
||||
|
||||
} catch (NoSuchMethodException e) {
|
||||
String msg = "Error finding getter method on " + cls + " with constructor " + constructor;
|
||||
errors.add(new RuntimeException(msg, e));
|
||||
}
|
||||
}
|
||||
|
||||
private ScoreConstructor getScore(Constructor<?> c) {
|
||||
|
||||
Class<?>[] parameterTypes = c.getParameterTypes();
|
||||
int score = -1000 * parameterTypes.length;
|
||||
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
if (parameterTypes[i].equals(String.class)){
|
||||
// string is very generic and we would prefer
|
||||
// a more specific type if that was available
|
||||
score = score + 1;
|
||||
|
||||
} else if (parameterTypes[i].equals(BigDecimal.class)) {
|
||||
score = score - 10;
|
||||
} else if (parameterTypes[i].equals(Timestamp.class)) {
|
||||
score = score - 10;
|
||||
} else if (parameterTypes[i].equals(double.class)) {
|
||||
score = score - 9;
|
||||
} else if (parameterTypes[i].equals(Double.class)) {
|
||||
score = score - 8;
|
||||
} else if (parameterTypes[i].equals(float.class)) {
|
||||
score = score - 7;
|
||||
} else if (parameterTypes[i].equals(Float.class)) {
|
||||
score = score - 6;
|
||||
} else if (parameterTypes[i].equals(long.class)) {
|
||||
score = score - 5;
|
||||
} else if (parameterTypes[i].equals(Long.class)) {
|
||||
score = score - 4;
|
||||
} else if (parameterTypes[i].equals(int.class)) {
|
||||
score = score - 3;
|
||||
} else if (parameterTypes[i].equals(Integer.class)) {
|
||||
score = score - 2;
|
||||
}
|
||||
}
|
||||
|
||||
return new ScoreConstructor(score, c);
|
||||
|
||||
String msg = "Was unable to use reflection to find a constructor and appropriate getters for" +
|
||||
"immutable type " + cls + ". The errors while looking for the getter methods follow:";
|
||||
logger.error(msg);
|
||||
|
||||
for (RuntimeException runtimeException : errors) {
|
||||
logger.error("Error with " + cls, runtimeException);
|
||||
}
|
||||
|
||||
private ScoreConstructor[] scoreConstructors(Class<?> cls) {
|
||||
|
||||
// find the constructor with the most number of parameters
|
||||
int maxParamCount = 0;
|
||||
|
||||
Constructor<?>[] constructors = cls.getConstructors();
|
||||
|
||||
ScoreConstructor[] score = new ScoreConstructor[constructors.length];
|
||||
|
||||
for (int i = 0; i < constructors.length; i++) {
|
||||
score[i] = getScore(constructors[i]);
|
||||
if (score[i].hasDuplicateParamTypes()){
|
||||
String msg = "Duplicate parameter types in "+score[i].constructor;
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
if (score[i].getParamCount() > maxParamCount){
|
||||
maxParamCount = score[i].getParamCount();
|
||||
}
|
||||
}
|
||||
|
||||
// filter out any constructors with less parameters than the max
|
||||
ArrayList<ScoreConstructor> list = new ArrayList<ScoreConstructor>();
|
||||
for (int i = 0; i < score.length; i++) {
|
||||
if (score[i].getParamCount() == maxParamCount){
|
||||
list.add(score[i]);
|
||||
}
|
||||
}
|
||||
|
||||
score = list.toArray(new ScoreConstructor[list.size()]);
|
||||
|
||||
// sort into score ascending order
|
||||
Arrays.sort(score);
|
||||
msg = "Unable to use reflection to build ImmutableMeta for " + cls
|
||||
+ ". Associated Errors trying to find a constructor and getter methods have been logged";
|
||||
|
||||
return score;
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
private ScoreConstructor getScore(Constructor<?> c) {
|
||||
|
||||
Class<?>[] parameterTypes = c.getParameterTypes();
|
||||
int score = -1000 * parameterTypes.length;
|
||||
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
if (parameterTypes[i].equals(String.class)) {
|
||||
// string is very generic and we would prefer
|
||||
// a more specific type if that was available
|
||||
score = score + 1;
|
||||
|
||||
} else if (parameterTypes[i].equals(BigDecimal.class)) {
|
||||
score = score - 10;
|
||||
} else if (parameterTypes[i].equals(Timestamp.class)) {
|
||||
score = score - 10;
|
||||
} else if (parameterTypes[i].equals(double.class)) {
|
||||
score = score - 9;
|
||||
} else if (parameterTypes[i].equals(Double.class)) {
|
||||
score = score - 8;
|
||||
} else if (parameterTypes[i].equals(float.class)) {
|
||||
score = score - 7;
|
||||
} else if (parameterTypes[i].equals(Float.class)) {
|
||||
score = score - 6;
|
||||
} else if (parameterTypes[i].equals(long.class)) {
|
||||
score = score - 5;
|
||||
} else if (parameterTypes[i].equals(Long.class)) {
|
||||
score = score - 4;
|
||||
} else if (parameterTypes[i].equals(int.class)) {
|
||||
score = score - 3;
|
||||
} else if (parameterTypes[i].equals(Integer.class)) {
|
||||
score = score - 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Method[] findGetters(Class<?> cls, Constructor<?> c) throws NoSuchMethodException {
|
||||
|
||||
Method[] methods = cls.getMethods();
|
||||
return new ScoreConstructor(score, c);
|
||||
}
|
||||
|
||||
Class<?>[] paramTypes = c.getParameterTypes();
|
||||
|
||||
Method[] readers = new Method[paramTypes.length];
|
||||
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
Method getter = findGetter(paramTypes[i], methods);
|
||||
if (getter == null && paramTypes.length == 1 && paramTypes[i].equals(String.class)){
|
||||
getter = findToString(cls);
|
||||
}
|
||||
if (getter == null) {
|
||||
throw new NoSuchMethodException("Get Method not found for "+paramTypes[i]+" in "+cls);
|
||||
}
|
||||
readers[i] = getter;
|
||||
}
|
||||
|
||||
return readers;
|
||||
private ScoreConstructor[] scoreConstructors(Class<?> cls) {
|
||||
|
||||
// find the constructor with the most number of parameters
|
||||
int maxParamCount = 0;
|
||||
|
||||
Constructor<?>[] constructors = cls.getConstructors();
|
||||
|
||||
ScoreConstructor[] score = new ScoreConstructor[constructors.length];
|
||||
|
||||
for (int i = 0; i < constructors.length; i++) {
|
||||
score[i] = getScore(constructors[i]);
|
||||
if (score[i].hasDuplicateParamTypes()) {
|
||||
String msg = "Duplicate parameter types in " + score[i].constructor;
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
if (score[i].getParamCount() > maxParamCount) {
|
||||
maxParamCount = score[i].getParamCount();
|
||||
}
|
||||
}
|
||||
|
||||
private Method findToString(Class<?> cls) throws NoSuchMethodException {
|
||||
|
||||
try {
|
||||
return cls.getDeclaredMethod("toString", new Class<?>[0]);
|
||||
} catch (SecurityException e) {
|
||||
throw new NoSuchMethodException("SecurityException "+e+" trying to find toString method on "+cls);
|
||||
}
|
||||
|
||||
// filter out any constructors with less parameters than the max
|
||||
ArrayList<ScoreConstructor> list = new ArrayList<ScoreConstructor>();
|
||||
for (int i = 0; i < score.length; i++) {
|
||||
if (score[i].getParamCount() == maxParamCount) {
|
||||
list.add(score[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private Method findGetter(Class<?> paramType, Method[] methods) {
|
||||
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (!Modifier.isStatic(methods[i].getModifiers())) {
|
||||
if (methods[i].getParameterTypes().length == 0) {
|
||||
// could be a getter
|
||||
String methName = methods[i].getName();
|
||||
if (methName.equals("hashCode")){
|
||||
|
||||
} else if (methName.equals("toString")) {
|
||||
score = list.toArray(new ScoreConstructor[list.size()]);
|
||||
|
||||
} else {
|
||||
Class<?> returnType = methods[i].getReturnType();
|
||||
if (paramType.equals(returnType)){
|
||||
return methods[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
// sort into score ascending order
|
||||
Arrays.sort(score);
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
|
||||
private Method[] findGetters(Class<?> cls, Constructor<?> c) throws NoSuchMethodException {
|
||||
|
||||
Method[] methods = cls.getMethods();
|
||||
|
||||
Class<?>[] paramTypes = c.getParameterTypes();
|
||||
|
||||
Method[] readers = new Method[paramTypes.length];
|
||||
|
||||
for (int i = 0; i < paramTypes.length; i++) {
|
||||
Method getter = findGetter(paramTypes[i], methods);
|
||||
if (getter == null && paramTypes.length == 1 && paramTypes[i].equals(String.class)) {
|
||||
getter = findToString(cls);
|
||||
}
|
||||
if (getter == null) {
|
||||
throw new NoSuchMethodException("Get Method not found for " + paramTypes[i] + " in " + cls);
|
||||
}
|
||||
readers[i] = getter;
|
||||
}
|
||||
|
||||
return readers;
|
||||
}
|
||||
|
||||
private Method findToString(Class<?> cls) throws NoSuchMethodException {
|
||||
|
||||
try {
|
||||
return cls.getDeclaredMethod("toString", new Class<?>[0]);
|
||||
} catch (SecurityException e) {
|
||||
throw new NoSuchMethodException("SecurityException " + e + " trying to find toString method on " + cls);
|
||||
}
|
||||
}
|
||||
|
||||
private Method findGetter(Class<?> paramType, Method[] methods) {
|
||||
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
if (!Modifier.isStatic(methods[i].getModifiers())) {
|
||||
if (methods[i].getParameterTypes().length == 0) {
|
||||
// could be a getter
|
||||
String methName = methods[i].getName();
|
||||
if (methName.equals("hashCode")) {
|
||||
|
||||
} else if (methName.equals("toString")) {
|
||||
|
||||
} else {
|
||||
Class<?> returnType = methods[i].getReturnType();
|
||||
if (paramType.equals(returnType)) {
|
||||
return methods[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class ScoreConstructor implements Comparable<ScoreConstructor> {
|
||||
|
||||
final int score;
|
||||
final Constructor<?> constructor;
|
||||
|
||||
private ScoreConstructor(int score, Constructor<?> constructor) {
|
||||
this.score = score;
|
||||
this.constructor = constructor;
|
||||
}
|
||||
|
||||
private static class ScoreConstructor implements Comparable<ScoreConstructor>{
|
||||
|
||||
final int score;
|
||||
final Constructor<?> constructor;
|
||||
|
||||
private ScoreConstructor(int score, Constructor<?> constructor) {
|
||||
this.score = score;
|
||||
this.constructor = constructor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// remove FindBugs warning
|
||||
return obj == this;
|
||||
}
|
||||
|
||||
public int compareTo(ScoreConstructor o) {
|
||||
return (score<o.score ? -1 : (score==o.score ? 0 : 1));
|
||||
}
|
||||
|
||||
public int getParamCount() {
|
||||
return constructor.getParameterTypes().length;
|
||||
}
|
||||
|
||||
public boolean hasDuplicateParamTypes() {
|
||||
|
||||
Class<?>[] parameterTypes = constructor.getParameterTypes();
|
||||
if (parameterTypes.length < 2){
|
||||
return false;
|
||||
}
|
||||
HashSet<Class<?>> set = new HashSet<Class<?>>();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
if (!set.add(parameterTypes[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// remove FindBugs warning
|
||||
return obj == this;
|
||||
}
|
||||
|
||||
public int compareTo(ScoreConstructor o) {
|
||||
return (score < o.score ? -1 : (score == o.score ? 0 : 1));
|
||||
}
|
||||
|
||||
public int getParamCount() {
|
||||
return constructor.getParameterTypes().length;
|
||||
}
|
||||
|
||||
public boolean hasDuplicateParamTypes() {
|
||||
|
||||
Class<?>[] parameterTypes = constructor.getParameterTypes();
|
||||
if (parameterTypes.length < 2) {
|
||||
return false;
|
||||
}
|
||||
HashSet<Class<?>> set = new HashSet<Class<?>>();
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
if (!set.add(parameterTypes[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+32
-32
@@ -6,41 +6,41 @@ import java.util.Arrays;
|
||||
import com.avaje.ebean.config.CompoundType;
|
||||
import com.avaje.ebean.config.CompoundTypeProperty;
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public class ReflectionBasedCompoundType implements CompoundType {
|
||||
|
||||
private final Constructor<?> constructor;
|
||||
|
||||
private final ReflectionBasedCompoundTypeProperty[] props;
|
||||
|
||||
public ReflectionBasedCompoundType(Constructor<?> constructor, ReflectionBasedCompoundTypeProperty[] props) {
|
||||
this.constructor = constructor;
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "ReflectionBasedCompoundType "+constructor+" "+Arrays.toString(props);
|
||||
}
|
||||
|
||||
public Object create(Object[] propertyValues) {
|
||||
|
||||
try {
|
||||
return constructor.newInstance(propertyValues);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
private final Constructor<?> constructor;
|
||||
|
||||
public CompoundTypeProperty[] getProperties() {
|
||||
return props;
|
||||
}
|
||||
private final ReflectionBasedCompoundTypeProperty[] props;
|
||||
|
||||
public Class<?> getPropertyType(int i){
|
||||
return props[i].getPropertyType();
|
||||
public ReflectionBasedCompoundType(Constructor<?> constructor, ReflectionBasedCompoundTypeProperty[] props) {
|
||||
this.constructor = constructor;
|
||||
this.props = props;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "ReflectionBasedCompoundType " + constructor + " " + Arrays.toString(props);
|
||||
}
|
||||
|
||||
public Object create(Object[] propertyValues) {
|
||||
|
||||
try {
|
||||
return constructor.newInstance(propertyValues);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
public Class<?> getCompoundType() {
|
||||
return constructor.getDeclaringClass();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public CompoundTypeProperty[] getProperties() {
|
||||
return props;
|
||||
}
|
||||
|
||||
public Class<?> getPropertyType(int i) {
|
||||
return props[i].getPropertyType();
|
||||
}
|
||||
|
||||
public Class<?> getCompoundType() {
|
||||
return constructor.getDeclaringClass();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+37
-37
@@ -4,47 +4,47 @@ import java.lang.reflect.Method;
|
||||
|
||||
import com.avaje.ebean.config.CompoundTypeProperty;
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public class ReflectionBasedCompoundTypeProperty implements CompoundTypeProperty {
|
||||
|
||||
private static final Object[] NO_ARGS = new Object[0];
|
||||
|
||||
private final Method reader;
|
||||
|
||||
private final String name;
|
||||
|
||||
private final Class<?> propertyType;
|
||||
|
||||
public ReflectionBasedCompoundTypeProperty(String name, Method reader, Class<?> propertyType) {
|
||||
this.name = name;
|
||||
this.reader = reader;
|
||||
this.propertyType = propertyType;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getDbType() {
|
||||
return 0;
|
||||
}
|
||||
private static final Object[] NO_ARGS = new Object[0];
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
private final Method reader;
|
||||
|
||||
public Object getValue(Object valueObject) {
|
||||
|
||||
try {
|
||||
return reader.invoke(valueObject, NO_ARGS);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
private final String name;
|
||||
|
||||
public Class<?> getPropertyType(){
|
||||
return propertyType;
|
||||
private final Class<?> propertyType;
|
||||
|
||||
public ReflectionBasedCompoundTypeProperty(String name, Method reader, Class<?> propertyType) {
|
||||
this.name = name;
|
||||
this.reader = reader;
|
||||
this.propertyType = propertyType;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public int getDbType() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Object getValue(Object valueObject) {
|
||||
|
||||
try {
|
||||
return reader.invoke(valueObject, NO_ARGS);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public Class<?> getPropertyType() {
|
||||
return propertyType;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+35
-35
@@ -5,45 +5,45 @@ import java.lang.reflect.Method;
|
||||
|
||||
import com.avaje.ebean.config.ScalarTypeConverter;
|
||||
|
||||
@SuppressWarnings({ "rawtypes" })
|
||||
@SuppressWarnings({"rawtypes"})
|
||||
public class ReflectionBasedScalarTypeConverter implements ScalarTypeConverter {
|
||||
|
||||
private static final Object[] NO_ARGS = new Object[0];
|
||||
|
||||
private final Constructor<?> constructor;
|
||||
|
||||
private final Method reader;
|
||||
|
||||
public ReflectionBasedScalarTypeConverter(Constructor<?> constructor, Method reader) {
|
||||
this.constructor = constructor;
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
public Object getNullValue() {
|
||||
return null;
|
||||
}
|
||||
private static final Object[] NO_ARGS = new Object[0];
|
||||
|
||||
public Object unwrapValue(Object beanType) {
|
||||
if (beanType == null){
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return reader.invoke(beanType, NO_ARGS);
|
||||
} catch (Exception e) {
|
||||
String msg = "Error invoking read method "+reader.getName()
|
||||
+" on "+beanType.getClass().getName();
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
private final Constructor<?> constructor;
|
||||
|
||||
private final Method reader;
|
||||
|
||||
public ReflectionBasedScalarTypeConverter(Constructor<?> constructor, Method reader) {
|
||||
this.constructor = constructor;
|
||||
this.reader = reader;
|
||||
}
|
||||
|
||||
public Object getNullValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Object unwrapValue(Object beanType) {
|
||||
if (beanType == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return reader.invoke(beanType, NO_ARGS);
|
||||
} catch (Exception e) {
|
||||
String msg = "Error invoking read method " + reader.getName()
|
||||
+ " on " + beanType.getClass().getName();
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public Object wrapValue(Object scalarType) {
|
||||
try {
|
||||
return constructor.newInstance(scalarType);
|
||||
} catch (Exception e) {
|
||||
String msg = "Error invoking constructor " + constructor + " with " + scalarType;
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
public Object wrapValue(Object scalarType) {
|
||||
try {
|
||||
return constructor.newInstance(scalarType);
|
||||
} catch (Exception e) {
|
||||
String msg = "Error invoking constructor "+constructor+" with "+scalarType;
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+61
-61
@@ -9,70 +9,70 @@ import com.avaje.ebeaninternal.server.type.TypeManager;
|
||||
|
||||
public class ReflectionBasedTypeBuilder {
|
||||
|
||||
private final TypeManager typeManager;
|
||||
|
||||
public ReflectionBasedTypeBuilder(TypeManager typeManager) {
|
||||
this.typeManager = typeManager;
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public ScalarType<?> buildScalarType(ImmutableMeta meta) {
|
||||
|
||||
if (meta.isCompoundType()){
|
||||
throw new RuntimeException("Must be scalar");
|
||||
}
|
||||
|
||||
Constructor<?> constructor = meta.getConstructor();
|
||||
|
||||
Class<?> logicalType = constructor.getDeclaringClass();
|
||||
|
||||
Method[] readers = meta.getReaders();
|
||||
Class<?> returnType = readers[0].getReturnType();
|
||||
|
||||
ScalarType<?> scalarType = typeManager.recursiveCreateScalarTypes(returnType);
|
||||
|
||||
ReflectionBasedScalarTypeConverter r = new ReflectionBasedScalarTypeConverter(constructor, readers[0]);
|
||||
|
||||
return new ScalarTypeWrapper(logicalType, scalarType, r);
|
||||
}
|
||||
|
||||
public ReflectionBasedCompoundType buildCompound(ImmutableMeta meta) {
|
||||
|
||||
Constructor<?> constructor = meta.getConstructor();
|
||||
private final TypeManager typeManager;
|
||||
|
||||
Method[] readers = meta.getReaders();
|
||||
public ReflectionBasedTypeBuilder(TypeManager typeManager) {
|
||||
this.typeManager = typeManager;
|
||||
}
|
||||
|
||||
ReflectionBasedCompoundTypeProperty[] props = new ReflectionBasedCompoundTypeProperty[readers.length];
|
||||
|
||||
|
||||
for (int i = 0; i < readers.length; i++) {
|
||||
Class<?> returnType = readers[i].getReturnType();
|
||||
|
||||
// ensure that return type is also a ScalarDataReader
|
||||
typeManager.recursiveCreateScalarDataReader(returnType);
|
||||
|
||||
String name = getPropertyName(readers[i]);
|
||||
|
||||
props[i] = new ReflectionBasedCompoundTypeProperty(name, readers[i], returnType);
|
||||
}
|
||||
|
||||
return new ReflectionBasedCompoundType(constructor, props);
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
public ScalarType<?> buildScalarType(ImmutableMeta meta) {
|
||||
|
||||
if (meta.isCompoundType()) {
|
||||
throw new RuntimeException("Must be scalar");
|
||||
}
|
||||
|
||||
private String getPropertyName(Method method){
|
||||
|
||||
String name = method.getName();
|
||||
if (name.startsWith("is")){
|
||||
return lowerFirstChar(name.substring(2));
|
||||
} else if (name.startsWith("get")){
|
||||
return lowerFirstChar(name.substring(3));
|
||||
}
|
||||
String msg = "Expecting method "+name+" to start with is or get "
|
||||
+" so as to follow bean specification?";
|
||||
throw new RuntimeException(msg);
|
||||
|
||||
Constructor<?> constructor = meta.getConstructor();
|
||||
|
||||
Class<?> logicalType = constructor.getDeclaringClass();
|
||||
|
||||
Method[] readers = meta.getReaders();
|
||||
Class<?> returnType = readers[0].getReturnType();
|
||||
|
||||
ScalarType<?> scalarType = typeManager.recursiveCreateScalarTypes(returnType);
|
||||
|
||||
ReflectionBasedScalarTypeConverter r = new ReflectionBasedScalarTypeConverter(constructor, readers[0]);
|
||||
|
||||
return new ScalarTypeWrapper(logicalType, scalarType, r);
|
||||
}
|
||||
|
||||
public ReflectionBasedCompoundType buildCompound(ImmutableMeta meta) {
|
||||
|
||||
Constructor<?> constructor = meta.getConstructor();
|
||||
|
||||
Method[] readers = meta.getReaders();
|
||||
|
||||
ReflectionBasedCompoundTypeProperty[] props = new ReflectionBasedCompoundTypeProperty[readers.length];
|
||||
|
||||
|
||||
for (int i = 0; i < readers.length; i++) {
|
||||
Class<?> returnType = readers[i].getReturnType();
|
||||
|
||||
// ensure that return type is also a ScalarDataReader
|
||||
typeManager.recursiveCreateScalarDataReader(returnType);
|
||||
|
||||
String name = getPropertyName(readers[i]);
|
||||
|
||||
props[i] = new ReflectionBasedCompoundTypeProperty(name, readers[i], returnType);
|
||||
}
|
||||
|
||||
private String lowerFirstChar(String name) {
|
||||
return Character.toLowerCase(name.charAt(0))+name.substring(1);
|
||||
|
||||
return new ReflectionBasedCompoundType(constructor, props);
|
||||
}
|
||||
|
||||
private String getPropertyName(Method method) {
|
||||
|
||||
String name = method.getName();
|
||||
if (name.startsWith("is")) {
|
||||
return lowerFirstChar(name.substring(2));
|
||||
} else if (name.startsWith("get")) {
|
||||
return lowerFirstChar(name.substring(3));
|
||||
}
|
||||
String msg = "Expecting method " + name + " to start with is or get "
|
||||
+ " so as to follow bean specification?";
|
||||
throw new RuntimeException(msg);
|
||||
}
|
||||
|
||||
private String lowerFirstChar(String name) {
|
||||
return Character.toLowerCase(name.charAt(0)) + name.substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user