/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.rdfbean.object;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;
import com.mysema.util.BeanMap;
/**
* @author sasa
*
*/
@Immutable
public final class MethodProperty extends MappedProperty<Method> {
@Nullable
public static MethodProperty getMethodPropertyOrNull(Method method, MappedClass declaringClass) {
try {
return new MethodProperty(method, declaringClass);
} catch (IllegalArgumentException e) {
return null;
}
}
public static String getPropertyName(Method method) {
String name = method.getName();
Class<?> returnType = method.getReturnType();
Class<?>[] parameterTypes = method.getParameterTypes();
if (name.startsWith("is")
&& parameterTypes.length == 0
&& (returnType.equals(boolean.class)
|| returnType.equals(Boolean.class))) {
return Character.toString(Character.toLowerCase(name.charAt(2))) + name.substring(3);
} else if (name.startsWith("get")
&& parameterTypes.length == 0
&& !returnType.equals(void.class)) {
return Character.toString(Character.toLowerCase(name.charAt(3))) + name.substring(4);
} else if (name.startsWith("set") // allow method chaining by returning
// "this"
&& parameterTypes.length == 1) {
return Character.toString(Character.toLowerCase(name.charAt(3))) + name.substring(4);
} else {
throw new IllegalArgumentException("Not getter or setter method: " + method);
}
}
private final boolean getter;
private final Method method;
public MethodProperty(Method method, MappedClass declaringClass) {
this(method, method.getAnnotations(), declaringClass);
}
public MethodProperty(Method method, Annotation[] annotations, MappedClass declaringClass) {
super(getPropertyName(method), annotations, declaringClass);
this.method = method;
if (method.getName().startsWith("set")) {
getter = false;
} else {
getter = true;
}
}
@Override
public Method getMember() {
return method;
}
@Override
protected Class<?> getTypeInternal() {
if (getter) {
return method.getReturnType();
} else {
return method.getParameterTypes()[0];
}
}
@Override
public Type getGenericType() {
Type gtype = null;
if (getter) {
gtype = method.getGenericReturnType();
} else {
Type[] ptypes = method.getGenericParameterTypes();
gtype = ptypes[0];
}
return gtype;
}
@Override
public void setValue(BeanMap beanMap, Object value) {
beanMap.put(getName(), value);
}
@Override
public Object getValue(BeanMap instance) {
return instance.get(getName());
}
@Override
public boolean isVirtual() {
return getSetter() == null;
}
@Nullable
private Method getSetter() {
Method setter = null;
if (!getter) {
setter = method;
} else {
Class<?> clazz = method.getDeclaringClass();
Class<?> type = getType();
if (boolean.class.equals(type) || Boolean.class.equals(type)) {
try {
setter = clazz.getDeclaredMethod("is" + capitalize(getName()), type);
} catch (SecurityException e) {
// ignore
} catch (NoSuchMethodException e) {
// ignore
}
}
if (setter == null) {
try {
setter = clazz.getDeclaredMethod("get" + capitalize(getName()), type);
} catch (SecurityException e) {
// ignore
} catch (NoSuchMethodException e) {
// ignore
}
}
}
return setter;
}
private String capitalize(String name) {
return Character.toUpperCase(name.charAt(0)) + name.substring(1);
}
}