Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.sun.javafx.fxml;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.AbstractMap;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.lang.reflect.*;
import javafx.beans.value.ObservableValue;
import sun.reflect.misc.FieldUtil;
import sun.reflect.misc.MethodUtil;
import sun.reflect.misc.ReflectUtil;
/**
* Exposes Java Bean properties of an object via the {@link Map} interface.
* A call to {@link Map#get(Object)} invokes the getter for the corresponding
* property, and a call to {@link Map#put(Object, Object)} invokes the
* property's setter. Appending a "Property" suffix to the key returns the
* corresponding property model.
*/
public class BeanAdapter extends AbstractMap {
private final Object bean;
private static ClassLoader contextClassLoader;
private static HashMap, HashMap>> globalMethodCache =
new HashMap, HashMap>>();
public static final String GET_PREFIX = "get";
public static final String IS_PREFIX = "is";
public static final String SET_PREFIX = "set";
public static final String PROPERTY_SUFFIX = "Property";
public static final String VALUE_OF_METHOD_NAME = "valueOf";
static {
contextClassLoader = Thread.currentThread().getContextClassLoader();
if (contextClassLoader == null) {
throw new NullPointerException();
}
}
/**
* Creates a new Bean adapter.
*
* @param bean
* The Bean object to wrap.
*/
public BeanAdapter(Object bean) {
this.bean = bean;
Class type = bean.getClass();
while (type != Object.class && !globalMethodCache.containsKey(type)) {
globalMethodCache.put(type, getClassMethodCache(type));
type = type.getSuperclass();
}
}
private static HashMap> getClassMethodCache(Class type) {
HashMap> classMethodCache = new HashMap>();
ReflectUtil.checkPackageAccess(type);
Method[] declaredMethods = type.getDeclaredMethods();
for (int i = 0; i < declaredMethods.length; i++) {
Method method = declaredMethods[i];
int modifiers = method.getModifiers();
if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers)) {
String name = method.getName();
LinkedList namedMethods = classMethodCache.get(name);
if (namedMethods == null) {
namedMethods = new LinkedList();
classMethodCache.put(name, namedMethods);
}
namedMethods.add(method);
}
}
return classMethodCache;
}
/**
* Returns the Bean object this adapter wraps.
*
* @return
* The Bean object, or null if no Bean has been set.
*/
public Object getBean() {
return bean;
}
private Method getMethod(String name, Class... parameterTypes) {
Class type = bean.getClass();
Method method = null;
while (type != Object.class) {
HashMap> classMethodCache = globalMethodCache.get(type);
LinkedList namedMethods = classMethodCache.get(name);
if (namedMethods != null) {
for (Method namedMethod : namedMethods) {
if (namedMethod.getName().equals(name)
&& Arrays.equals(namedMethod.getParameterTypes(), parameterTypes)) {
method = namedMethod;
break;
}
}
}
if (method != null) {
break;
}
type = type.getSuperclass();
}
return method;
}
private Method getGetterMethod(String key) {
Method getterMethod = getMethod(getMethodName(GET_PREFIX, key));
if (getterMethod == null) {
getterMethod = getMethod(getMethodName(IS_PREFIX, key));
}
return getterMethod;
}
private Method getSetterMethod(String key) {
Class type = getType(key);
if (type == null) {
throw new UnsupportedOperationException("Cannot determine type for property.");
}
return getMethod(getMethodName(SET_PREFIX, key), type);
}
private static String getMethodName(String prefix, String key) {
return prefix + Character.toUpperCase(key.charAt(0)) + key.substring(1);
}
/**
* Invokes the getter method for the given property.
*
* @param key
* The property name.
*
* @return
* The value returned by the method, or null if no such method
* exists.
*/
@Override
public Object get(Object key) {
if (key == null) {
throw new NullPointerException();
}
return get(key.toString());
}
private Object get(String key) {
Method getterMethod = key.endsWith(PROPERTY_SUFFIX) ? getMethod(key) : getGetterMethod(key);
Object value;
if (getterMethod != null) {
try {
value = MethodUtil.invoke(getterMethod, bean, (Object[]) null);
} catch (IllegalAccessException exception) {
throw new RuntimeException(exception);
} catch (InvocationTargetException exception) {
throw new RuntimeException(exception);
}
} else {
value = null;
}
return value;
}
/**
* Invokes a setter method for the given property. The
* {@link #coerce(Object, Class)} method is used as needed to attempt to
* convert a given value to the property type, as defined by the return
* value of the getter method.
*
* @param key
* The property name.
*
* @param value
* The new property value.
*
* @return
* Returns null, since returning the previous value would require
* an unnecessary call to the getter method.
*
* @throws PropertyNotFoundException
* If the given property does not exist or is read-only.
*/
@Override
public Object put(String key, Object value) {
if (key == null) {
throw new NullPointerException();
}
Method setterMethod = getSetterMethod(key);
if (setterMethod == null) {
throw new PropertyNotFoundException("Property \"" + key + "\" does not exist"
+ " or is read-only.");
}
try {
MethodUtil.invoke(setterMethod, bean, new Object[] { coerce(value, getType(key)) });
} catch (IllegalAccessException exception) {
throw new RuntimeException(exception);
} catch (InvocationTargetException exception) {
throw new RuntimeException(exception);
}
return null;
}
/**
* Verifies the existence of a property.
*
* @param key
* The property name.
*
* @return
* true if the property exists; false, otherwise.
*/
@Override
public boolean containsKey(Object key) {
if (key == null) {
throw new NullPointerException();
}
return getType(key.toString()) != null;
}
@Override
public Set> entrySet() {
throw new UnsupportedOperationException();
}
/**
* Tests the mutability of a property.
*
* @param key
* The property name.
*
* @return
* true if the property is read-only; false, otherwise.
*/
public boolean isReadOnly(String key) {
if (key == null) {
throw new NullPointerException();
}
return getSetterMethod(key) == null;
}
/**
* Returns the property model for the given property.
*
* @param key
* The property name.
*
* @return
* The named property model, or null if no such property exists.
*/
@SuppressWarnings("unchecked")
public ObservableValue getPropertyModel(String key) {
if (key == null) {
throw new NullPointerException();
}
return (ObservableValue)get(key + BeanAdapter.PROPERTY_SUFFIX);
}
/**
* Returns the type of a property.
*
* @param key
* The property name.
*/
public Class getType(String key) {
if (key == null) {
throw new NullPointerException();
}
Method getterMethod = getGetterMethod(key);
return (getterMethod == null) ? null : getterMethod.getReturnType();
}
/**
* Returns the generic type of a property.
*
* @param key
* The property name.
*/
public Type getGenericType(String key) {
if (key == null) {
throw new NullPointerException();
}
Method getterMethod = getGetterMethod(key);
return (getterMethod == null) ? null : getterMethod.getGenericReturnType();
}
@Override
public boolean equals(Object object) {
boolean equals = false;
if (object instanceof BeanAdapter) {
BeanAdapter beanAdapter = (BeanAdapter)object;
equals = (bean == beanAdapter.bean);
}
return equals;
}
@Override
public int hashCode() {
return (bean == null) ? -1 : bean.hashCode();
}
/**
* Coerces a value to a given type.
*
* @param value
* @param type
*
* @return
* The coerced value.
*/
@SuppressWarnings("unchecked")
public static T coerce(Object value, Class type) {
if (type == null) {
throw new NullPointerException();
}
Object coercedValue = null;
if (value == null) {
// Null values can only be coerced to null
coercedValue = null;
} else if (type.isAssignableFrom(value.getClass())) {
// Value doesn't require coercion
coercedValue = value;
} else if (type == Boolean.class
|| type == Boolean.TYPE) {
coercedValue = Boolean.valueOf(value.toString());
} else if (type == Character.class
|| type == Character.TYPE) {
coercedValue = value.toString().charAt(0);
} else if (type == Byte.class
|| type == Byte.TYPE) {
if (value instanceof Number) {
coercedValue = ((Number)value).byteValue();
} else {
coercedValue = Byte.valueOf(value.toString());
}
} else if (type == Short.class
|| type == Short.TYPE) {
if (value instanceof Number) {
coercedValue = ((Number)value).shortValue();
} else {
coercedValue = Short.valueOf(value.toString());
}
} else if (type == Integer.class
|| type == Integer.TYPE) {
if (value instanceof Number) {
coercedValue = ((Number)value).intValue();
} else {
coercedValue = Integer.valueOf(value.toString());
}
} else if (type == Long.class
|| type == Long.TYPE) {
if (value instanceof Number) {
coercedValue = ((Number)value).longValue();
} else {
coercedValue = Long.valueOf(value.toString());
}
} else if (type == BigInteger.class) {
if (value instanceof Number) {
coercedValue = BigInteger.valueOf(((Number)value).longValue());
} else {
coercedValue = new BigInteger(value.toString());
}
} else if (type == Float.class
|| type == Float.TYPE) {
if (value instanceof Number) {
coercedValue = ((Number)value).floatValue();
} else {
coercedValue = Float.valueOf(value.toString());
}
} else if (type == Double.class
|| type == Double.TYPE) {
if (value instanceof Number) {
coercedValue = ((Number)value).doubleValue();
} else {
coercedValue = Double.valueOf(value.toString());
}
} else if (type == Number.class) {
String number = value.toString();
if (number.contains(".")) {
coercedValue = Double.valueOf(number);
} else {
coercedValue = Long.valueOf(number);
}
} else if (type == BigDecimal.class) {
if (value instanceof Number) {
coercedValue = BigDecimal.valueOf(((Number)value).doubleValue());
} else {
coercedValue = new BigDecimal(value.toString());
}
} else if (type == Class.class) {
try {
ReflectUtil.checkPackageAccess(value.toString());
coercedValue = Class.forName(
value.toString(),
false,
BeanAdapter.contextClassLoader);
} catch (ClassNotFoundException exception) {
throw new IllegalArgumentException(exception);
}
} else {
Class valueType = value.getClass();
Method valueOfMethod = null;
while (valueOfMethod == null
&& valueType != null) {
try {
ReflectUtil.checkPackageAccess(type);
valueOfMethod = type.getDeclaredMethod(VALUE_OF_METHOD_NAME, valueType);
} catch (NoSuchMethodException exception) {
// No-op
}
if (valueOfMethod == null) {
valueType = valueType.getSuperclass();
}
}
if (valueOfMethod == null) {
throw new IllegalArgumentException("Unable to coerce " + value + " to " + type + ".");
}
if (type.isEnum()
&& value instanceof String
&& Character.isLowerCase(((String)value).charAt(0))) {
value = toAllCaps((String)value);
}
try {
coercedValue = MethodUtil.invoke(valueOfMethod, null, new Object[] { value });
} catch (IllegalAccessException exception) {
throw new RuntimeException(exception);
} catch (InvocationTargetException exception) {
throw new RuntimeException(exception);
} catch (SecurityException exception) {
throw new RuntimeException(exception);
}
}
return (T)coercedValue;
}
/**
* Invokes the static getter method for the given property.
*
* @param target
* The object to which the property is attached.
*
* @param sourceType
* The class that defines the property.
*
* @param key
* The property name.
*
* @return
* The value returned by the method, or null if no such method
* exists.
*/
@SuppressWarnings("unchecked")
public static T get(Object target, Class sourceType, String key) {
T value = null;
Class targetType = target.getClass();
Method getterMethod = getStaticGetterMethod(sourceType, key, targetType);
if (getterMethod != null) {
try {
value = (T) MethodUtil.invoke(getterMethod, null, new Object[] { target } );
} catch (InvocationTargetException exception) {
throw new RuntimeException(exception);
} catch (IllegalAccessException exception) {
throw new RuntimeException(exception);
}
}
return value;
}
/**
* Invokes a static setter method for the given property. If the value is
* null or there is no explicit setter for a given type, the
* {@link #coerce(Object, Class)} method is used to attempt to convert the
* value to the actual property type (defined by the return value of the
* getter method).
*
* @param target
* The object to which the property is or will be attached.
*
* @param sourceType
* The class that defines the property.
*
* @param key
* The property name.
*
* @param value
* The new property value.
*
* @throws PropertyNotFoundException
* If the given static property does not exist or is read-only.
*/
public static void put(Object target, Class sourceType, String key, Object value) {
Class targetType = target.getClass();
Method setterMethod = null;
if (value != null) {
setterMethod = getStaticSetterMethod(sourceType, key, value.getClass(), targetType);
}
if (setterMethod == null) {
// Get the property type and attempt to coerce the value to it
Class propertyType = getType(sourceType, key, targetType);
if (propertyType != null) {
setterMethod = getStaticSetterMethod(sourceType, key, propertyType, targetType);
value = coerce(value, propertyType);
}
}
if (setterMethod == null) {
throw new PropertyNotFoundException("Static property \"" + key + "\" does not exist"
+ " or is read-only.");
}
// Invoke the setter
try {
MethodUtil.invoke(setterMethod, null, new Object[] { target, value });
} catch (InvocationTargetException exception) {
throw new RuntimeException(exception);
} catch (IllegalAccessException exception) {
throw new RuntimeException(exception);
}
}
/**
* Tests the existence of a static property.
*
* @param sourceType
* The class that defines the property.
*
* @param key
* The property name.
*
* @param targetType
* The type of the object to which the property applies.
*
* @return
* true if the property exists; false, otherwise.
*/
public static boolean isDefined(Class sourceType, String key, Class targetType) {
return (getStaticGetterMethod(sourceType, key, targetType) != null);
}
/**
* Returns the type of a static property.
*
* @param sourceType
* The class that defines the property.
*
* @param key
* The property name.
*
* @param targetType
* The type of the object to which the property applies.
*/
public static Class getType(Class sourceType, String key, Class targetType) {
Method getterMethod = getStaticGetterMethod(sourceType, key, targetType);
return (getterMethod == null) ? null : getterMethod.getReturnType();
}
/**
* Returns the generic type of a static property.
*
* @param sourceType
* The class that defines the property.
*
* @param key
* The property name.
*
* @param targetType
* The type of the object to which the property applies.
*/
public static Type getGenericType(Class sourceType, String key, Class targetType) {
Method getterMethod = getStaticGetterMethod(sourceType, key, targetType);
return (getterMethod == null) ? null : getterMethod.getGenericReturnType();
}
/**
* Determines the type of a list item.
*
* @param listType
*/
public static Class getListItemType(Type listType) {
Type itemType = getGenericListItemType(listType);
if (itemType instanceof ParameterizedType) {
itemType = ((ParameterizedType)itemType).getRawType();
}
return (Class)itemType;
}
/**
* Determines the type of a map value.
*
* @param listType
*/
public static Class getMapValueType(Type mapType) {
Type valueType = getGenericMapValueType(mapType);
if (valueType instanceof ParameterizedType) {
valueType = ((ParameterizedType)valueType).getRawType();
}
return (Class)valueType;
}
/**
* Determines the type of a list item.
*
* @param listType
*/
public static Type getGenericListItemType(Type listType) {
Type itemType = null;
Type parentType = listType;
while (parentType != null) {
if (parentType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)parentType;
Class rawType = (Class)parameterizedType.getRawType();
if (List.class.isAssignableFrom(rawType)) {
itemType = parameterizedType.getActualTypeArguments()[0];
}
break;
}
Class classType = (Class)parentType;
Type[] genericInterfaces = classType.getGenericInterfaces();
for (int i = 0; i < genericInterfaces.length; i++) {
Type genericInterface = genericInterfaces[i];
if (genericInterface instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)genericInterface;
Class interfaceType = (Class)parameterizedType.getRawType();
if (List.class.isAssignableFrom(interfaceType)) {
itemType = parameterizedType.getActualTypeArguments()[0];
break;
}
}
}
if (itemType != null) {
break;
}
parentType = classType.getGenericSuperclass();
}
if (itemType != null && itemType instanceof TypeVariable) {
itemType = Object.class;
}
return itemType;
}
/**
* Determines the type of a map value.
*
* @param mapType
*/
public static Type getGenericMapValueType(Type mapType) {
Type valueType = null;
Type parentType = mapType;
while (parentType != null) {
if (parentType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)parentType;
Class rawType = (Class)parameterizedType.getRawType();
if (Map.class.isAssignableFrom(rawType)) {
valueType = parameterizedType.getActualTypeArguments()[1];
}
break;
}
Class classType = (Class)parentType;
Type[] genericInterfaces = classType.getGenericInterfaces();
for (int i = 0; i < genericInterfaces.length; i++) {
Type genericInterface = genericInterfaces[i];
if (genericInterface instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType)genericInterface;
Class interfaceType = (Class)parameterizedType.getRawType();
if (Map.class.isAssignableFrom(interfaceType)) {
valueType = parameterizedType.getActualTypeArguments()[1];
break;
}
}
}
if (valueType != null) {
break;
}
parentType = classType.getGenericSuperclass();
}
if (valueType != null && valueType instanceof TypeVariable) {
valueType = Object.class;
}
return valueType;
}
/**
* Returns the value of a named constant.
*
* @param type
* The type that defines the constant.
*
* @param name
* The name of the constant.
*/
public static Object getConstantValue(Class type, String name) {
if (type == null) {
throw new IllegalArgumentException();
}
if (name == null) {
throw new IllegalArgumentException();
}
Field field;
try {
field = FieldUtil.getField(type, name);
} catch (NoSuchFieldException exception) {
throw new IllegalArgumentException(exception);
}
int fieldModifiers = field.getModifiers();
if ((fieldModifiers & Modifier.STATIC) == 0
|| (fieldModifiers & Modifier.FINAL) == 0) {
throw new IllegalArgumentException("Field is not a constant.");
}
Object value;
try {
value = field.get(null);
} catch (IllegalAccessException exception) {
throw new IllegalArgumentException(exception);
}
return value;
}
private static Method getStaticGetterMethod(Class sourceType, String key,
Class targetType) {
if (sourceType == null) {
throw new NullPointerException();
}
if (key == null) {
throw new NullPointerException();
}
Method method = null;
if (targetType != null) {
key = Character.toUpperCase(key.charAt(0)) + key.substring(1);
String getMethodName = GET_PREFIX + key;
String isMethodName = IS_PREFIX + key;
try {
method = MethodUtil.getMethod(sourceType, getMethodName, new Class[] { targetType });
} catch (NoSuchMethodException exception) {
// No-op
}
if (method == null) {
try {
method = MethodUtil.getMethod(sourceType, isMethodName, new Class[] { targetType });
} catch (NoSuchMethodException exception) {
// No-op
}
}
// Check for interfaces
if (method == null) {
Class[] interfaces = targetType.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
try {
method = MethodUtil.getMethod(sourceType, getMethodName, new Class[] { interfaces[i] });
} catch (NoSuchMethodException exception) {
// No-op
}
if (method == null) {
try {
method = MethodUtil.getMethod(sourceType, isMethodName, new Class[] { interfaces[i] });
} catch (NoSuchMethodException exception) {
// No-op
}
}
if (method != null) {
break;
}
}
}
if (method == null) {
method = getStaticGetterMethod(sourceType, key, targetType.getSuperclass());
}
}
return method;
}
private static Method getStaticSetterMethod(Class sourceType, String key,
Class valueType, Class targetType) {
if (sourceType == null) {
throw new NullPointerException();
}
if (key == null) {
throw new NullPointerException();
}
if (valueType == null) {
throw new NullPointerException();
}
Method method = null;
if (targetType != null) {
key = Character.toUpperCase(key.charAt(0)) + key.substring(1);
String setMethodName = SET_PREFIX + key;
try {
method = MethodUtil.getMethod(sourceType, setMethodName, new Class[] { targetType, valueType });
} catch (NoSuchMethodException exception) {
// No-op
}
// Check for interfaces
if (method == null) {
Class[] interfaces = targetType.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
try {
method = MethodUtil.getMethod(sourceType, setMethodName, new Class[] { interfaces[i], valueType });
} catch (NoSuchMethodException exception) {
// No-op
}
if (method != null) {
break;
}
}
}
if (method == null) {
method = getStaticSetterMethod(sourceType, key, valueType, targetType.getSuperclass());
}
}
return method;
}
private static String toAllCaps(String value) {
if (value == null) {
throw new NullPointerException();
}
StringBuilder allCapsBuilder = new StringBuilder();
for (int i = 0, n = value.length(); i < n; i++) {
char c = value.charAt(i);
if (Character.isUpperCase(c)) {
allCapsBuilder.append('_');
}
allCapsBuilder.append(Character.toUpperCase(c));
}
return allCapsBuilder.toString();
}
}