blob: 83c36cf24bf1a25565cc79303dfedb4d7b59ed18 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2005 Sybase, Inc. and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Sybase, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.jst.jsf.facesconfig.ui.util;
import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jst.jsf.common.ui.internal.utils.JavaModelUtil;
/**
* This utility class is used to access java bean class, e.g., get java bean's
* property
*
* @author xgzhang
* @version
*/
public final class JavaBeanUtils {
/**
* fully qualified name of a List
*/
private static final String JAVA_UTIL_LIST = "java.util.List"; //$NON-NLS-1$
/**
* fully qualifed name of a Map
*/
private static final String JAVA_UTIL_MAP = "java.util.Map"; //$NON-NLS-1$
/**
*
*/
private JavaBeanUtils() {
super();
}
/**
* get the getter method according to property name
*
* @param type
* @param propertyName
* @return - can be <b>null</b>, if not found
* @throws JavaModelException
* @throws JavaModelException
*/
private static IMethod getPropertyGetterMethod(IType type,
String propertyName) {
if (type == null || !type.exists() || propertyName == null) {
return null;
}
IMethod getterMethod = null;
String methodBaseName = null;
// Uppercase 1st letter
if (propertyName.length() == 1) {
methodBaseName = propertyName.substring(0, 1).toUpperCase();
} else {
methodBaseName = propertyName.substring(0, 1).toUpperCase()
+ propertyName.substring(1);
}
String getterMethodName = "get" + methodBaseName; //$NON-NLS-1$
getterMethod = type.getMethod(getterMethodName, null);
if (getterMethod == null || !getterMethod.exists()
|| !JavaClassUtils.isPublicMethod(getterMethod)) {
getterMethodName = "is" + methodBaseName; //$NON-NLS-1$
getterMethod = type.getMethod(getterMethodName, null);
if (getterMethod == null || !getterMethod.exists()
|| !JavaClassUtils.isPublicMethod(getterMethod)) {
getterMethod = null;
}
}
return getterMethod;
}
/**
* get the getter method in the type hierarchy according to property name
*
* @param type
* @param propertyName
* @return - can be <b>null</b>, if not found
* @throws JavaModelException
* @throws JavaModelException
*/
private static IMethod getPropertyGetterMethodInTypeHierarchy(IType type,
String propertyName) throws JavaModelException {
if (type == null || !type.exists() || propertyName == null) {
return null;
}
IMethod getterMethod = null;
getterMethod = getPropertyGetterMethod(type, propertyName);
if (getterMethod == null) {
ITypeHierarchy typeHierarchy = null;
typeHierarchy = type.newSupertypeHierarchy(null);
if (typeHierarchy == null) {
return null;
}
IType[] superTypes = typeHierarchy.getAllSuperclasses(type);
if (superTypes == null || superTypes.length == 0) {
return null;
}
for (int i = 0; i < superTypes.length; i++) {
if (!superTypes[i].getFullyQualifiedName().equals(
"java.lang.Object")) { //$NON-NLS-1$
getterMethod = getPropertyGetterMethod(superTypes[i],
propertyName);
if (getterMethod != null) {
break;
}
}
}
}
return getterMethod;
}
/**
* get the setter method in the type hierarchy according to property name
*
* @param type
* @param propertyName
* @return - can be <b>null</b>, if not found
* @throws JavaModelException
*/
private static IMethod getPropertySetterMethodInTypeHierarchy(IType type,
String propertyName) throws JavaModelException {
if (type == null || !type.exists() || propertyName == null) {
return null;
}
IMethod setterMethod = null;
setterMethod = getPropertySetterMethod(type, propertyName);
if (setterMethod == null) {
ITypeHierarchy typeHierarchy = null;
typeHierarchy = type.newSupertypeHierarchy(null);
if (typeHierarchy == null) {
return null;
}
IType[] superTypes = typeHierarchy.getAllSuperclasses(type);
if (superTypes == null || superTypes.length == 0) {
return null;
}
for (int i = 0; i < superTypes.length; i++) {
if (!superTypes[i].getFullyQualifiedName().equals(
"java.lang.Object")) { //$NON-NLS-1$
setterMethod = getPropertySetterMethod(superTypes[i],
propertyName);
if (setterMethod != null) {
break;
}
}
}
}
return setterMethod;
}
/**
* get the setter method according to property name
*
* @param type
* @param propertyName
* @return - can be <b>null</b>, if not found
* @throws JavaModelException
*/
private static IMethod getPropertySetterMethod(IType type,
String propertyName) throws JavaModelException {
if (type == null || !type.exists() || propertyName == null) {
return null;
}
IMethod setterMethod = null;
String methodBaseName = null;
// Uppercase 1st letter
if (propertyName.length() == 1) {
methodBaseName = propertyName.substring(0, 1).toUpperCase();
} else {
methodBaseName = propertyName.substring(0, 1).toUpperCase()
+ propertyName.substring(1);
}
String setterMethodName = "set" + methodBaseName; //$NON-NLS-1$
IMethod[] methods = null;
methods = type.getMethods();
if (methods == null || methods.length == 0) {
return null;
}
for (int i = 0; i < methods.length; i++) {
if (methods[i].getElementName().equals(setterMethodName)) {
if (methods[i] == null || !methods[i].exists()
|| !JavaClassUtils.isPublicMethod(methods[i])) {
continue;
}
// Method must return void
String returnType = methods[i].getReturnType();
if (!returnType.equals(Signature.SIG_VOID)) {
continue;
}
String params[] = methods[i].getParameterTypes();
// method must have only one argument
if (params.length != 1) {
continue;
}
setterMethod = methods[i];
}
}
return setterMethod;
}
/**
* Check whether the propertyName is bean's property or not.
*
* @param baseType
* @param propertyName
*
* @return - True means the property name is valid bean's property,
* otherwise, not.
*
*/
public static boolean isBeanProperty(IType baseType, String propertyName)
{
if (baseType == null || !baseType.exists() || propertyName == null) {
return false;
}
return (getBeanPropertyType(baseType, propertyName) != null);
}
/**
* get the bean's property type
*
* @param baseType
* @param propertyName
* @return - can be <b>null</b>, if not found
*
*/
public static IType getBeanPropertyType(IType baseType, String propertyName) {
if (baseType == null || !baseType.exists() || propertyName == null) {
return null;
}
String typeSignature = null;
IMethod getterMethod = null;
IMethod setterMethod = null;
IType declaredType = baseType;
try {
getterMethod = getPropertyGetterMethodInTypeHierarchy(baseType,
propertyName);
setterMethod = getPropertySetterMethodInTypeHierarchy(baseType,
propertyName);
} catch (JavaModelException e1) {
// Need not any error handling.
}
if (getterMethod != null && setterMethod == null) {
declaredType = getterMethod.getDeclaringType();
try {
typeSignature = getterMethod.getReturnType();
} catch (JavaModelException e2) {
// Need not any error handling.
}
} else if (setterMethod != null && getterMethod == null) {
declaredType = setterMethod.getDeclaringType();
typeSignature = setterMethod.getParameterTypes()[0];
} else if (setterMethod != null && getterMethod != null) {
declaredType = getterMethod.getDeclaringType();
try {
// FIXME: should check the type hierachy
if (getterMethod.getReturnType().equals(
setterMethod.getParameterTypes()[0])) {
typeSignature = getterMethod.getReturnType();
}
} catch (JavaModelException e2) {
// Need not any error handling.
}
}
if (typeSignature == null) {
return null;
}
IType type = null;
try {
String typeName = JavaModelUtil.getResolvedTypeName(typeSignature,
declaredType);
if (typeName != null) {
type = baseType.getJavaProject().findType(typeName);
}
} catch (JavaModelException e) {
// Need not any error handling.
}
return type;
}
/**
* get the bean's property's getter and setter methods.
*
* @param baseType
* @param propertyName
* @return - IMethod[], the first is getter and the second is setter method,
* however, both of them can be null.
*/
public static IMethod[] getBeanPropertyMethods(IType baseType,
String propertyName) {
if (baseType == null || !baseType.exists() || propertyName == null) {
return null;
}
IMethod[] methods = new IMethod[2];
IMethod getterMethod = null;
IMethod setterMethod = null;
try {
getterMethod = getPropertyGetterMethodInTypeHierarchy(baseType,
propertyName);
setterMethod = getPropertySetterMethodInTypeHierarchy(baseType,
propertyName);
} catch (JavaModelException e) {
// Need not any error handling.
}
if (getterMethod != null && setterMethod == null) {
methods[0] = getterMethod;
} else if (setterMethod != null && getterMethod == null) {
methods[1] = setterMethod;
} else if (setterMethod != null && getterMethod != null) {
try {
// FIXME: should check the type hierachy
if (getterMethod.getReturnType().equals(
setterMethod.getParameterTypes()[0])) {
methods[0] = getterMethod;
methods[1] = setterMethod;
}
} catch (JavaModelException e1) {
// Need not any error handling.
}
}
return methods;
}
/**
* check whether the type implements <code>java.util.List</code>
*
* @param type
* @return - True if the type is the sub class of
* <code>java.util.List</code>, otherwise, not.
*/
public static boolean isListType(IType type) {
if (type == null) {
return false;
}
if (type.getFullyQualifiedName().equalsIgnoreCase(JAVA_UTIL_LIST)) {
return true;
}
return JavaClassUtils.isSubClassOf(type.getJavaProject(), type
.getFullyQualifiedName(), JAVA_UTIL_LIST);
}
/**
* check whether the type implements <code>java.util.Map</code>
*
* @param type
* @return - True if the type is the sub class of <code>java.uitl.Map</code>,
* otherwise, not.
*/
public static boolean isMapType(IType type) {
if (type == null) {
return false;
}
if (type.getFullyQualifiedName().equalsIgnoreCase(JAVA_UTIL_MAP)) {
return true;
}
return JavaClassUtils.isSubClassOf(type.getJavaProject(), type
.getFullyQualifiedName(), JAVA_UTIL_MAP);
}
/**
* Test for method inclusion in bindings list.
* <p>
* This test has the following conditions:
* </p>
* <ul>
* <li>method starts with <code>get</code></li>
* <li>method has no arguments</li>
* <li>method does not return void</li>
* </ul>
*
* @param method -
* the IMethod to examine
* @return boolean - true, if method satisfies the condition test
*/
public static boolean isGetterMethod(IMethod method) {
try {
if (!JavaClassUtils.isPublicMethod(method)) {
return false;
}
String params[] = method.getParameterTypes();
// Has no arguments
if (params.length > 0) {
return false;
}
// Starts with "get"
if (!(method.getElementName().startsWith("get") || method.getElementName().startsWith("is"))) //$NON-NLS-1$ //$NON-NLS-2$
{
return false;
}
// Does not return void
String rtn = method.getReturnType();
if (!rtn.equals(Signature.SIG_VOID)) {
return true;
}
} catch (JavaModelException e) {
// Need not any error handling.
}
return false;
}
/**
* Test for method inclusion in bindings list.
* <p>
* This test has the following conditions:
* </p>
* <ul>
* <li>method starts with <code>set</code></li>
* <li>method returns void</li>
* </ul>
*
* @param method -
* the IMethod to examine
* @return boolean - true, if method satisfies the condition test
*/
public static boolean isSetterMethod(IMethod method) {
try {
if (!JavaClassUtils.isPublicMethod(method)) {
return false;
}
// Starts with "set"
if (!method.getElementName().startsWith("set")) //$NON-NLS-1$
{
return false;
}
// the parameter's number should be one.
if (method.getParameterTypes().length != 1) {
return false;
}
// Returns void
String rtn = method.getReturnType();
if (rtn.equals(Signature.SIG_VOID)) {
return true;
}
} catch (JavaModelException e) {
// Need not any error handling.
}
return false;
}
/**
* set the first character into low case.
*
* @param str
* @return str with the first char lower cased
*/
public static String toLowCaseFirstChar(String str) {
// change the first alphabet to lowcase.
if (str != null && str.length() > 0) {
if (str.length() == 1) {
str = str.toLowerCase();
} else {
str = str.substring(0, 1).toLowerCase() + str.substring(1);
}
}
return str;
}
/**
* set the first character into low case.
*
* @param str
* @return str with the first char upper-cased
*/
public static String toUpperCaseFirstChar(String str) {
// change the first alphabet to lowcase.
if (str != null && str.length() > 0) {
if (str.length() == 1) {
str = str.toUpperCase();
} else {
str = str.substring(0, 1).toUpperCase() + str.substring(1);
}
}
return str;
}
/**
* get property name from getter method.
*
* @param method
* @return - can be <b>null</b>, if the method is not a valid getter method
*/
public static String getPropertyNameFromGetterMethod(IMethod method) {
if (!isGetterMethod(method)) {
return null;
}
String methodName = method.getElementName();
String propertyName = null;
// Starts with "get"
if (methodName.startsWith("get") && methodName.length() > 3) { //$NON-NLS-1$
propertyName = methodName.substring(3);
} else if (methodName.startsWith("is") && methodName.length() > 2) // Starts //$NON-NLS-1$
// with
// "is"
{
propertyName = methodName.substring(2);
}
propertyName = Introspector.decapitalize(propertyName);
return propertyName;
}
/**
* get property name from setter class.
*
* @param method
* @return - can be <b>null</b>, if the method is not a valid setter method
*/
public static String getPropertyNameFromSetterMethod(IMethod method) {
if (!isSetterMethod(method)) {
return null;
}
String methodName = method.getElementName();
String propertyName = null;
// Starts with "get"
if (methodName.startsWith("set") && methodName.length() > 3) { //$NON-NLS-1$
propertyName = methodName.substring(3);
}
propertyName = Introspector.decapitalize(propertyName);
return propertyName;
}
/**
* get the method with the same parameters
*
* @param methods
* @param visitedMethods
* @param foundMethod
* @param foundMethodName
* @param foundParamTypes
* @return
*/
private static IMethod getMethodWithSameParamters(IMethod[] methods,
Map visitedMethods, IMethod foundMethod, String foundMethodName,
String[] foundParamTypes) {
// get all qualified type name for the found method's parameters.
String[] foundParamQulifiedTypeNames = null;
if (foundParamTypes != null && foundParamTypes.length > 0) {
foundParamQulifiedTypeNames = new String[foundParamTypes.length];
for (int i = 0; i < foundParamTypes.length; i++) {
foundParamQulifiedTypeNames[i] = JavaClassUtils
.getQualifiedTypeNameInTypeHierarchy(foundMethod
.getDeclaringType(), foundParamTypes[i]);
}
}
for (int i = 0; i < methods.length; i++) {
if (visitedMethods.get(methods[i]) != null) {
continue;
}
if (!methods[i].getElementName().equals(foundMethodName)) {
continue;
}
if (methods[i].getParameterTypes() == null
&& foundParamTypes == null) {
return methods[i];
} else if (methods[i].getParameterTypes() != null
&& foundParamTypes != null
&& foundParamTypes.length == methods[i].getParameterTypes().length) {
boolean bSameParams = true;
String[] methodParamTypes = methods[i].getParameterTypes();
for (int j = 0; j < foundParamQulifiedTypeNames.length; j++) {
String methodParamQualifiedTypeName = JavaClassUtils
.getQualifiedTypeNameInTypeHierarchy(methods[i]
.getDeclaringType(), methodParamTypes[j]);
// if the qualified type name is not same or not subclass or
// supper class between each other.
if (!methodParamQualifiedTypeName
.equals(foundParamQulifiedTypeNames[j])
&& !JavaClassUtils.isSubClassOf(methods[i]
.getJavaProject(),
methodParamQualifiedTypeName,
foundParamQulifiedTypeNames[j])
&& !JavaClassUtils.isSubClassOf(methods[i]
.getJavaProject(),
foundParamQulifiedTypeNames[j],
methodParamQualifiedTypeName)) {
bSameParams = false;
break;
}
}
if (bSameParams) {
return methods[i];
}
}
}
return null;
}
/**
* Creates an array of bean properties
*
*
* @param classType
* @return it can be <b>null</b>, if property is not found.
*/
public static JavaBeanProperty[] getBeanProperties(IType classType) {
IMethod[] methods;
try {
methods = JavaClassUtils.getMethods(classType);
} catch (JavaModelException e2) {
return null;
}
return getBeanProperties(classType, methods);
}
/**
* Creates an array of bean properties
*
* @param type
* @param methods
*
* @return - the array of java bean properties.
*/
public static JavaBeanProperty[] getBeanProperties(IType type,
IMethod[] methods) {
if (methods == null || methods.length == 0) {
return null;
}
List properties = new ArrayList();
Map visitedMethods = new HashMap();
for (int m = 0; m < methods.length; m++) {
String propertyName = null;
// if a property's getter method or setter method already visited,
// just skip it.
if (visitedMethods.get(methods[m]) != null) {
continue;
}
visitedMethods.put(methods[m], methods[m]);
// Check getter firstly
propertyName = JavaBeanUtils
.getPropertyNameFromGetterMethod(methods[m]);
if (propertyName != null && propertyName.length() > 0)
{
String setterMethodName = "set" //$NON-NLS-1$
+ JavaBeanUtils.toUpperCaseFirstChar(propertyName);
String getterReturnType = null;
try {
getterReturnType = methods[m].getReturnType();
} catch (JavaModelException e1) {
continue;
}
IMethod setterMethod = getMethodWithSameParamters(methods,
visitedMethods, methods[m], setterMethodName,
new String[] { getterReturnType });
if (setterMethod != null && setterMethod.exists()) {
visitedMethods.put(setterMethod, setterMethod);
}
properties.add(new JavaBeanProperty(propertyName,
getterReturnType, methods[m], setterMethod));
continue;
}
// Check setter secondly.
propertyName = JavaBeanUtils
.getPropertyNameFromSetterMethod(methods[m]);
if (propertyName != null && propertyName.length() > 0)
{
// first form of getter method, "get..."
String getterMethodName = "get" //$NON-NLS-1$
+ JavaBeanUtils.toUpperCaseFirstChar(propertyName);
IMethod getterMethod = getMethodWithSameParamters(methods,
visitedMethods, methods[m], getterMethodName, null);
if (getterMethod != null && getterMethod.exists()) {
try {
if (getterMethod.getReturnType().equals(
methods[m].getParameterTypes()[0])) {
visitedMethods.put(getterMethod, getterMethod);
}
} catch (JavaModelException e) {
// need not error logging
}
} else {
// another form of getter method, "is...".
getterMethodName = "is" //$NON-NLS-1$
+ JavaBeanUtils.toUpperCaseFirstChar(propertyName);
getterMethod = getMethodWithSameParamters(methods,
visitedMethods, methods[m], getterMethodName, null);
try {
if (getterMethod != null
&& getterMethod.exists()
&& getterMethod.getReturnType().equals(
methods[m].getParameterTypes()[0])) {
visitedMethods.put(getterMethod, getterMethod);
}
} catch (JavaModelException e) {
// need not error logging
}
}
properties.add(new JavaBeanProperty(propertyName, methods[m]
.getParameterTypes()[0], getterMethod, methods[m]));
continue;
}
}
JavaBeanProperty[] propertyArray = (JavaBeanProperty[]) properties
.toArray(new JavaBeanProperty[properties.size()]);
Arrays.sort(propertyArray, new Comparator() {
public int compare(Object o1, Object o2) {
String name1 = ((JavaBeanProperty) o1).getName();
String name2 = ((JavaBeanProperty) o2).getName();
return name1.compareTo(name2);
}
});
return propertyArray;
}
}