/*
* Copyright 2011 cruxframework.org.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.cruxframework.crux.core.utils;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.cruxframework.crux.core.client.Legacy;
import org.cruxframework.crux.core.client.utils.StringUtils;
import org.cruxframework.crux.core.rebind.AbstractProxyCreator.SourcePrinter;
import org.cruxframework.crux.core.rebind.CruxGeneratorException;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameter;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JPrimitiveType;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
/**
* @author Thiago da Rosa de Bustamante
*
*/
public class JClassUtils
{
public static JType buildGetValueExpression(StringBuilder out, JClassType dtoType, String propertyPath,
String objectVariable, boolean finishCommand)
throws NoSuchFieldException
{
return buildGetValueExpression(out, dtoType, propertyPath, objectVariable, finishCommand, false, false);
}
public static JType buildGetValueExpression(StringBuilder out, JClassType dtoType, String propertyPath,
String objectVariable, boolean finishCommand, boolean replaceNullForEmptyOnStringDefault, boolean checkObjectNull)
throws NoSuchFieldException
{
StringBuilder checkNullExpression = new StringBuilder();
if (checkObjectNull)
{
checkNullExpression.append(objectVariable+"==null");
}
if (StringUtils.isEmpty(propertyPath))
{
if (replaceNullForEmptyOnStringDefault)
{
out.append(checkNullExpression.toString()+"?"+getEmptyValueForType(dtoType, !replaceNullForEmptyOnStringDefault)+":");
}
out.append(objectVariable);
if (finishCommand)
{
out.append(";");
}
return dtoType;
}
String[] props;
if (propertyPath.contains("."))
{
props = propertyPath.split("\\.");
}
else
{
props = new String[]{propertyPath};
}
if (props != null && props.length > 0)
{
StringBuilder getExpression = new StringBuilder();
getExpression.append(objectVariable);
JType baseType = dtoType;
JClassType baseClassType = baseType.isClassOrInterface();
for (int i=0; i < props.length; i++)
{
if (baseClassType == null && i < props.length-1)
{
throw new NoSuchFieldException(propertyPath);
}
String prop = props[i];
if (i>0)
{
if ((i > 1) || checkObjectNull)
{
checkNullExpression.append(" || ");
}
checkNullExpression.append(getExpression.toString()+"==null ");
}
baseType = buildGetExpression(prop, baseClassType, getExpression);
if (baseType == null)
{
throw new NoSuchFieldException(propertyPath);
}
baseClassType = baseType.isClassOrInterface();
}
if (finishCommand)
{
getExpression.append(";");
}
if (checkNullExpression.length() > 0)
{
out.append(checkNullExpression.toString()+"?"+getEmptyValueForType(baseType, !replaceNullForEmptyOnStringDefault)+":");
}
out.append(getExpression.toString());
return baseType;
}
else
{
throw new NoSuchFieldException(propertyPath);
}
}
public static JType buildSetValueExpression(SourcePrinter out, JClassType dtoType, String propertyPath, String objectVariable, String value)
throws NoSuchFieldException
{
StringBuilder str = new StringBuilder();
JType ret = buildSetValueExpression(str, dtoType, propertyPath, objectVariable, value);
out.print(str.toString());
return ret;
}
public static JType buildSetValueExpression(StringBuilder out, JClassType dtoType, String propertyPath, String objectVariable, String value)
throws NoSuchFieldException
{
if (StringUtils.isEmpty(propertyPath))
{
throw new NoSuchFieldException(propertyPath);
}
String[] props;
if (propertyPath.contains("."))
{
props = propertyPath.split("\\.");
}
else
{
props = new String[]{propertyPath};
}
if (props != null && props.length > 0)
{
StringBuilder getExpression = new StringBuilder();
getExpression.append(objectVariable);
JType baseType = dtoType;
JClassType baseClassType = baseType.isClassOrInterface();
for (int i=0; i < props.length-1; i++)
{
if (baseClassType == null && i < props.length-1)
{
throw new NoSuchFieldException(propertyPath);
}
String prop = props[i];
JClassType propertyType = getTypeForProperty(prop, baseClassType).isClassOrInterface();
String getterMethod = getGetterMethod(prop, baseClassType);
String setterMethod = getSetterMethod(prop, baseClassType, propertyType);
out.append("if ("+getExpression.toString()+"."+getterMethod+"()==null){\n");
out.append("\t"+getExpression+"."+setterMethod+"(("+propertyType.getParameterizedQualifiedSourceName()+")"+GWT.class.getCanonicalName()+".create("+propertyType.getQualifiedSourceName()+".class));\n");
out.append("}\n");
getExpression.append("."+getterMethod+"()");
baseClassType = propertyType;
}
String prop = props[props.length-1];
JType propertyType = getTypeForProperty(prop, baseClassType);
String setterMethod = getSetterMethod(prop, baseClassType, propertyType);
out.append(getExpression+"."+setterMethod+"("+value+");");
return propertyType;
}
else
{
throw new NoSuchFieldException(propertyPath);
}
}
public static PropertyInfo[] extractBeanPropertiesInfo(JClassType type)
{
List<PropertyInfo> result = new ArrayList<PropertyInfo>();
List<JMethod> getterMethods = getGetterMethods(type);
List<JMethod> setterMethods = getSetterMethods(type);
for (JMethod setterMethod : setterMethods)
{
String setterProperty = getPropertyForGetterOrSetterMethod(setterMethod);
for (JMethod getterMethod : getterMethods)
{
String getterProperty = getPropertyForGetterOrSetterMethod(getterMethod);
if (getterProperty.equals(setterProperty))
{
result.add(new PropertyInfo(setterProperty, getterMethod.getReturnType(), getterMethod, setterMethod));
break;
}
}
}
return result.toArray(new PropertyInfo[result.size()]);
}
/**
*
* @param clazz
* @param methodName
* @return
*/
public static JMethod[] findMethods(JClassType clazz, String methodName)
{
List<JMethod> result = new ArrayList<JMethod>();
JMethod[] methods = clazz.getInheritableMethods();
if (methods != null)
{
for (JMethod method : methods)
{
if (method.getName().equals(methodName))
{
result.add(method);
}
}
}
return result.toArray(new JMethod[result.size()]);
}
/**
*
* @param clazz
* @param propertyName
* @return
*/
public static JMethod[] findSetterMethods(JClassType clazz, String propertyName)
{
String setterMethodName = "set"+Character.toUpperCase(propertyName.charAt(0));
if (propertyName.length() > 1)
{
setterMethodName += propertyName.substring(1);
}
JMethod[] methods = findMethods(clazz, setterMethodName);
List<JMethod> result = new ArrayList<JMethod>();
for (JMethod method : methods)
{
if (method.getParameters().length == 1)
{
result.add(method);
}
}
return result.toArray(new JMethod[result.size()]);
}
/**
* Generates a property set block. First try to set the field directly, then try to use a javabean setter method.
*
* @param logger
* @param voClass
* @param field
* @param parentVariable
* @param valueVariable
* @param sourceWriter
*/
public static void generateFieldValueSet(JClassType voClass, JField field, String parentVariable,
String valueVariable, SourcePrinter sourceWriter, boolean allowProtected)
{
if (field.isPublic() || (allowProtected && field.isProtected()))
{
sourceWriter.println(parentVariable+"."+field.getName()+"="+valueVariable+";");
}
else
{
String setterMethodName = "set"+Character.toUpperCase(field.getName().charAt(0))+field.getName().substring(1);
try
{
if (voClass.getMethod(setterMethodName, new JType[]{field.getType()}) != null)
{
sourceWriter.println(parentVariable+"."+setterMethodName+"("+valueVariable+");");
}
}
catch (Exception e)
{
throw new CruxGeneratorException("Property ["+field.getName()+"] could not be created. This is not visible neither has a getter/setter method.");
}
}
}
public static JClassType[] getActualParameterTypes(JClassType baseType, JClassType desiredInterfaceType)
{
Set<? extends JClassType> interfaces = baseType.getFlattenedSupertypeHierarchy();
for (JClassType intf : interfaces)
{
JParameterizedType parameterized = intf.isParameterized();
if (parameterized != null)
{
if (parameterized.getBaseType().getQualifiedSourceName().equals(desiredInterfaceType.getQualifiedSourceName()))
{
return parameterized.getTypeArgs();
}
}
}
throw new RuntimeException("Desired interface ["+desiredInterfaceType.getQualifiedSourceName()+"] is nor parameterized or baseIntef does not extends that interface.");
}
/**
* @param clazz
* @param name
* @return
*/
public static JField getDeclaredField(JClassType clazz, String name) throws NoSuchFieldException
{
JField field = clazz.getField(name);
if (field == null)
{
if (clazz.getSuperclass() == null)
{
throw new NoSuchFieldException(name);
}
field = getDeclaredField(clazz.getSuperclass(), name);
}
return field;
}
/**
* @param clazz
* @return
*/
public static JField[] getDeclaredFields(JClassType clazz)
{
if (clazz.getSuperclass() == null)
{
return new JField[0];
}
Set<JField> result = new HashSet<JField>();
JField[] declaredFields = clazz.getFields();
for (JField field : declaredFields)
{
result.add(field);
}
clazz = clazz.getSuperclass();
while (clazz.getSuperclass() != null)
{
declaredFields = clazz.getFields();
for (JField field : declaredFields)
{
if (!result.contains(field))
{
result.add(field);
}
}
clazz = clazz.getSuperclass();
}
return result.toArray(new JField[result.size()]);
}
public static String getEmptyValueForType(JType objectType)
{
return getEmptyValueForType(objectType, true);
}
public static String getEmptyValueForType(JType objectType, boolean useNullForString)
{
JPrimitiveType primitiveType = objectType.isPrimitive();
if (primitiveType != null)
{
if ((primitiveType == JPrimitiveType.INT)
||(primitiveType == JPrimitiveType.SHORT)
||(primitiveType == JPrimitiveType.LONG)
||(primitiveType == JPrimitiveType.BYTE)
||(primitiveType == JPrimitiveType.FLOAT)
||(primitiveType == JPrimitiveType.DOUBLE))
{
return "0";
}
else if (primitiveType == JPrimitiveType.BOOLEAN)
{
return "false";
}
else if (primitiveType == JPrimitiveType.CHAR)
{
return "' '";
}
else if (primitiveType ==JPrimitiveType.VOID)
{
return null;
}
}
else if (objectType.getQualifiedSourceName().equals(String.class.getCanonicalName()))
{
if (!useNullForString)
{
return "\"\"";
}
}
return "null";
}
/**
* Retrieve a field from class. Searches also into the class hierarchy
* @param clazz class to search the field
* @param fieldName field name
* @return the field
*/
public static JField getField(JClassType clazz, String fieldName)
{
JField field = null;
JClassType superClass = clazz;
while (field == null && superClass != null)
{
field = superClass.findField(fieldName);
superClass = superClass.getSuperclass();
}
return field;
}
/**
* Generates a property get block. First try to get the field directly, then try to use a javabean getter method.
* @param voClass
* @param field
* @param parentVariable
* @param allowProtected
* @deprecated Use getFieldValueGet(JClassType, String, String boolean) instead.
*/
@Deprecated
@Legacy
public static String getFieldValueGet(JClassType voClass, JField field, String parentVariable, boolean allowProtected)
{
return getFieldValueGet(voClass, field.getName(), parentVariable, allowProtected);
}
/**
* Generates a property get block. First try to get the field directly, then try to use a javabean getter method.
* @param clazz class where the property will be searched.
* @param propertyName property name
* @param parentVariable the name of the parent variable to use in generated expression
* @param allowProtected if this expression allow protected fields and methods access
* @return an expression in the form {@code <parentVar>.<propertyAccessor>}
*/
public static String getFieldValueGet(JClassType clazz, String propertyName, String parentVariable, boolean allowProtected)
{
JMethod jMethod = JClassUtils.getMethod(clazz, JClassUtils.getGetterMethod(propertyName, clazz), new JType[]{});
if (jMethod != null && (jMethod.isPublic() || (allowProtected && jMethod.isProtected())))
{
return (parentVariable+"."+jMethod.getName()+"()");
}
JField field = getField(clazz, propertyName);
if (field.isPublic() || (allowProtected && field.isProtected()))
{
return parentVariable+"."+field.getName();
}
throw new CruxGeneratorException("Property ["+propertyName+"] could not be created. It is not visible neither has a getter/setter method.");
}
/**
* Returns a string to be used in generic code block, according with the given type
* @param type
* @return
*/
public static String getGenericDeclForType(JType type)
{
if (type.isPrimitive() != null)
{
JPrimitiveType jPrimitiveType = type.isPrimitive();
return jPrimitiveType.getQualifiedBoxedSourceName();
}
else
{
return type.getParameterizedQualifiedSourceName();
}
}
/**
*
* @param propertyName
* @param baseClass
* @return
*/
public static String getGetterMethod(String propertyName, JClassType baseClass)
{
if (propertyName == null || propertyName.length() == 0)
{
return null;
}
String result = getGetterMethodName(propertyName);
JMethod[] methods = findMethods(baseClass, "get"+result);
if (methods.length == 0)
{
methods = findMethods(baseClass, "is"+result);
}
if (methods.length > 0)
{
for (int i = 0; i < methods.length; i++)
{
if (methods[i].getParameters().length == 0)
{
return methods[i].getName();
}
}
}
return null;
}
public static String getGetterMethodName(String propertyName)
{
String result = ""+Character.toUpperCase(propertyName.charAt(0));
if (propertyName.length() > 1)
{
result += propertyName.substring(1);
}
return result;
}
public static List<JMethod> getGetterMethods(JClassType objectType)
{
List<JMethod> result = new ArrayList<JMethod>();
JMethod[] methods = objectType.getInheritableMethods();
for (JMethod jMethod : methods)
{
if (isValidGetterMethod(jMethod))
{
result.add(jMethod);
}
}
return result;
}
/**
* @param clazz
* @param methodName
* @param params
* @return
*/
public static JMethod getMethod(JClassType clazz, String methodName, JType[] params)
{
JMethod method = null;
JClassType superClass = clazz;
while (method == null && superClass != null)
{
method = superClass.findMethod(methodName, params);
superClass = superClass.getSuperclass();
}
return method;
}
/**
* @param method
* @return
*/
public static String getMethodDescription(JMethod method)
{
StringBuilder str = new StringBuilder();
str.append(method.getEnclosingType().getQualifiedSourceName());
str.append(".");
str.append(method.getName());
str.append("(");
boolean needsComma = false;
for (JParameter parameter: method.getParameters())
{
if (needsComma)
{
str.append(",");
}
needsComma = true;
str.append(parameter.getType().getParameterizedQualifiedSourceName());
}
str.append(")");
return str.toString();
}
/**
* Look for methods over the interfaces.
* @param clazz
* @param methodName
* @param params
* @return
*/
public static JMethod getMethodOverInterfaces(JClassType clazz, String methodName, JType[] params)
{
JMethod method = null;
for (JClassType superInterface : clazz.getImplementedInterfaces())
{
method = getMethod(superInterface, methodName, params);
if (method != null)
{
return method;
}
}
return method;
}
public static String getNullSafeExpression(String widgetExpression, JType propertyType, String widgetVariable)
{
String getExpression = null;
JPrimitiveType primitiveType = propertyType.isPrimitive();
if (primitiveType == null)
{
getExpression = "(" + widgetVariable + "==null?null:" + widgetExpression + ")";
}
else if (primitiveType.equals(JPrimitiveType.BOOLEAN))
{
getExpression = "(" + widgetVariable + "==null?false:" + widgetExpression + "==null?false:" + widgetExpression + ")";
}
else if (primitiveType.equals(JPrimitiveType.CHAR))
{
getExpression = "(" + widgetVariable + "==null?' ':" + widgetExpression + "==null?' ':" + widgetExpression + ")";
}
else if (!primitiveType.equals(JPrimitiveType.VOID))
{
getExpression = "(" + widgetVariable + "==null?0:" + widgetExpression + "==null?0:" + widgetExpression + ")";
}
return getExpression;
}
/**
*
* @param valueVariable
* @param expectedType
* @return
* @throws NotFoundException
*/
public static String getParsingExpressionForSimpleType(String valueVariable, JType expectedType) throws NotFoundException
{
if (expectedType == JPrimitiveType.INT || Integer.class.getCanonicalName().equals(expectedType.getQualifiedSourceName()))
{
return "Integer.parseInt("+valueVariable+")";
}
else if (expectedType == JPrimitiveType.SHORT || Short.class.getCanonicalName().equals(expectedType.getQualifiedSourceName()))
{
return "Short.parseShort("+valueVariable+")";
}
else if (expectedType == JPrimitiveType.LONG || Long.class.getCanonicalName().equals(expectedType.getQualifiedSourceName()))
{
return "Long.parseLong("+valueVariable+")";
}
else if (expectedType == JPrimitiveType.BYTE || Byte.class.getCanonicalName().equals(expectedType.getQualifiedSourceName()))
{
return "Byte.parseByte("+valueVariable+")";
}
else if (expectedType == JPrimitiveType.FLOAT || Float.class.getCanonicalName().equals(expectedType.getQualifiedSourceName()))
{
return "Float.parseFloat("+valueVariable+")";
}
else if (expectedType == JPrimitiveType.DOUBLE || Double.class.getCanonicalName().equals(expectedType.getQualifiedSourceName()))
{
return "Double.parseDouble("+valueVariable+")";
}
else if (expectedType == JPrimitiveType.BOOLEAN || Boolean.class.getCanonicalName().equals(expectedType.getQualifiedSourceName()))
{
return "Boolean.parseBoolean("+valueVariable+")";
}
else if (expectedType == JPrimitiveType.CHAR || Character.class.getCanonicalName().equals(expectedType.getQualifiedSourceName()))
{
return valueVariable+".charAt(1)";
}
else if (Date.class.getCanonicalName().equals(expectedType.getQualifiedSourceName()))
{
return "new "+Date.class.getCanonicalName()+"(Long.parseLong("+valueVariable+"))";
}
else if (expectedType.isEnum() != null)
{
return expectedType.getQualifiedSourceName()+".valueOf("+valueVariable+")";
}
else
{
JClassType stringType = ((JClassType)expectedType).getOracle().getType(String.class.getName());
if (stringType.isAssignableFrom((JClassType)expectedType))
{
return valueVariable;
}
if (((JClassType)expectedType).findConstructor(new JType[]{stringType}) != null)
{
return "new "+expectedType.getQualifiedSourceName()+"("+valueVariable+")";
}
JMethod valueOfMethod = ((JClassType)expectedType).findMethod("valueOf", new JType[]{stringType});
if (valueOfMethod != null && valueOfMethod.isStatic())
{
return expectedType.getQualifiedSourceName()+".valueOf("+valueVariable+")";
}
JMethod fromStringMethod = ((JClassType)expectedType).findMethod("fromString", new JType[]{stringType});
if (fromStringMethod != null && fromStringMethod.isStatic())
{
return expectedType.getQualifiedSourceName()+".fromString("+valueVariable+")";
}
}
return null;
}
public static String getPropertyForGetterOrSetterMethod(JMethod method)
{
String name = method.getName();
if (name.startsWith("get") || name.startsWith("set"))
{
name = name.substring(3);
}
else if (name.startsWith("is"))
{
name = name.substring(2);
}
name = Character.toLowerCase(name.charAt(0))+ name.substring(1);
return name;
}
/**
* Retrieve the property type on the given class
* @param clazz base class
* @param propertyPath property path
* @return property type or null, if property is not present
*/
public static JType getPropertyType(JClassType clazz, String propertyPath)
{
JType propertyType = null;
JClassType baseClass = clazz;
String[] props;
if (propertyPath.contains("."))
{
props = propertyPath.split("\\.");
}
else
{
props = new String[]{propertyPath};
}
int i;
for (i = 0; baseClass != null && i < props.length; i++)
{
String propertyName = props[i];
JMethod method = getMethod(baseClass, getGetterMethod(propertyName, baseClass), new JType[]{});
if (method != null)
{
propertyType = method.getReturnType();
baseClass = propertyType.isClassOrInterface();
}
else
{
if (i == props.length - 1)
{
JMethod[] setterMethods = findSetterMethods(clazz, propertyName);
if (setterMethods != null && setterMethods.length > 0)
{
propertyType = setterMethods[0].getParameters()[0].getType();
return propertyType;
}
}
JField field = getField(baseClass, propertyName);
if (field != null)
{
propertyType = field.getType();
baseClass = propertyType.isClassOrInterface();
}
else
{
return null;
}
}
}
if (i < props.length)
{
return null;
}
return propertyType;
}
/**
* @param methodName
* @return
*/
public static JType getReturnTypeFromMethodClass(JClassType clazz, String methodName, JType[] params)
{
JMethod method = getMethod(clazz, methodName, params);
if (method == null)
{
return null;
}
JType returnType = method.getReturnType();
return returnType;
}
/**
*
* @param propertyName
* @param baseClass
* @return
*/
public static String getSetterMethod(String propertyName, JClassType baseClass, JType propertyType)
{
if (propertyName == null || propertyName.length() == 0)
{
return null;
}
String result = ""+Character.toUpperCase(propertyName.charAt(0));
result += propertyName.substring(1);
if (propertyName.length() > 1)
{
try
{
baseClass.getMethod("set"+result, new JType[]{propertyType});
result = "set"+result;
}
catch (Exception e)
{
if (baseClass.getSuperclass() == null)
{
result = null;
}
else
{
result = getSetterMethod(propertyName, baseClass.getSuperclass(), propertyType);
}
}
}
return result;
}
public static List<JMethod> getSetterMethods(JClassType objectType)
{
List<JMethod> result = new ArrayList<JMethod>();
JMethod[] methods = objectType.getInheritableMethods();
for (JMethod jMethod : methods)
{
if (isValidSetterMethod(jMethod))
{
result.add(jMethod);
}
}
return result;
}
public static JClassType getType(TypeOracle typeOracle, String className) throws NotFoundException
{
return getType(typeOracle, className, null);
}
public static JClassType getType(TypeOracle typeOracle, String className, String viewName) throws NotFoundException
{
try
{
return typeOracle.getType(className);
}
catch (Exception e)
{
String message = "Class ["+className+"] " + (viewName != null ? ", declared on view ["+viewName+"]," : "") + " could not be loaded. "
+ "\n Possible causes:"
+ "\n\t 1. Check if any type or subtype used by this class refers to another module and if this module is inherited in the .gwt.xml file."
+ "\n\t 2. Check if your class or its members belongs to a client package."
+ "\n\t 3. Check the versions of all your modules.";
throw new NotFoundException(message, e);
}
}
public static JClassType getTypeArgForGenericType(JClassType type)
{
JParameterizedType parameterized = type.isParameterized();
if (parameterized == null)
{
return type.getOracle().findType("java.lang.Object");
}
JClassType jClassType = parameterized.getTypeArgs()[0];
return jClassType;
}
public static JType getTypeForProperty(String property, JClassType objectType)
{
if (objectType == null)
{
return null;
}
int index = property.indexOf('.');
if (index < 0)
{
String getterMethod = JClassUtils.getGetterMethod(property, objectType);
if (StringUtils.isEmpty(getterMethod))
{
return null;
}
return JClassUtils.getReturnTypeFromMethodClass(objectType, getterMethod, new JType[]{});
}
String getterMethod = JClassUtils.getGetterMethod(property.substring(0, index), objectType);
if (StringUtils.isEmpty(getterMethod))
{
return null;
}
return getTypeForProperty(property.substring(index+1), JClassUtils.getReturnTypeFromMethodClass(objectType, getterMethod, new JType[]{}).isClassOrInterface());
}
/**
* Returns <code>true</code> is the given field has both a "get" and a "set" methods.
* @param clazz
* @param field
* @return
*/
public static boolean hasGetAndSetMethods(JField field, JClassType clazz)
{
return hasGetMethod(field, clazz) && hasSetMethod(field, clazz);
}
/**
* Returns <code>true</code> is the given field has an associated public "get" method.
* @param clazz
* @param field
* @return
*/
public static boolean hasGetMethod(JField field, JClassType clazz)
{
String getterMethodName = "get"+Character.toUpperCase(field.getName().charAt(0))+field.getName().substring(1);
try
{
return (clazz.getMethod(getterMethodName, new JType[]{}) != null);
}
catch (Exception e)
{
try
{
getterMethodName = "is"+Character.toUpperCase(field.getName().charAt(0))+field.getName().substring(1);
return (clazz.getMethod(getterMethodName, new JType[]{}) != null);
}
catch (Exception e1)
{
if (clazz.getSuperclass() == null)
{
return false;
}
else
{
return hasGetMethod(field, clazz.getSuperclass());
}
}
}
}
/**
* Returns <code>true</code> is the given field has an associated public "set" method.
* @param field
* @param clazz
* @return
*/
public static boolean hasSetMethod(JField field, JClassType clazz)
{
String setterMethodName = "set"+Character.toUpperCase(field.getName().charAt(0))+field.getName().substring(1);
try
{
return (clazz.getMethod(setterMethodName, new JType[]{field.getType()}) != null);
}
catch (Exception e)
{
if (clazz.getSuperclass() == null)
{
return false;
}
else
{
return hasSetMethod(field, clazz.getSuperclass());
}
}
}
public static boolean isCollection(JType type)
{
JClassType classOrInterface = type.isClassOrInterface();
if (classOrInterface != null)
{
if (classOrInterface.isAssignableTo(classOrInterface.getOracle().findType(List.class.getCanonicalName())) ||
classOrInterface.isAssignableTo(classOrInterface.getOracle().findType(Set.class.getCanonicalName())) ||
classOrInterface.isAssignableTo(classOrInterface.getOracle().findType(Map.class.getCanonicalName())))
{
return true;
}
}
return false;
}
/**
* Check if a type can be assigned to another
* @param from
* @param to
* @return
*/
public static boolean isCompatibleTypes(JType from, JType to)
{
if (from == to)
{
return true;
}
JPrimitiveType primitiveFrom = from.isPrimitive();
if (primitiveFrom != null)
{
return primitiveFrom.getQualifiedBoxedSourceName().equals(to.getQualifiedSourceName());
}
JPrimitiveType primitiveTo = to.isPrimitive();
if (primitiveTo != null)
{
return primitiveTo.getQualifiedBoxedSourceName().equals(from.getQualifiedSourceName());
}
JClassType classOrInterfaceFrom = from.isClassOrInterface();
JClassType classOrInterfaceTo = to.isClassOrInterface();
if (classOrInterfaceFrom != null && classOrInterfaceTo != null)
{
return classOrInterfaceFrom.isAssignableTo(classOrInterfaceTo);
}
return false;
}
/**
* Verify if the given field is fully accessible.
* @param field
* @param clazz
* @return <code>true</code> if the field is public or has associated "get" and "set" methods.
*/
public static boolean isFullAccessibleField(JField field, JClassType clazz)
{
return field.isPublic() || hasGetAndSetMethods(field, clazz);
}
public static boolean isNumeric(JType widgetPropertyType)
{
JPrimitiveType primitiveType = widgetPropertyType.isPrimitive();
if (primitiveType != null)
{
return ((primitiveType == JPrimitiveType.INT)
||(primitiveType == JPrimitiveType.SHORT)
||(primitiveType == JPrimitiveType.LONG)
||(primitiveType == JPrimitiveType.BYTE)
||(primitiveType == JPrimitiveType.FLOAT)
||(primitiveType == JPrimitiveType.DOUBLE));
}
return (widgetPropertyType.getQualifiedSourceName().equals(JPrimitiveType.INT.getQualifiedBoxedSourceName()))||
(widgetPropertyType.getQualifiedSourceName().equals(JPrimitiveType.SHORT.getQualifiedBoxedSourceName()))||
(widgetPropertyType.getQualifiedSourceName().equals(JPrimitiveType.LONG.getQualifiedBoxedSourceName()))||
(widgetPropertyType.getQualifiedSourceName().equals(JPrimitiveType.BYTE.getQualifiedBoxedSourceName()))||
(widgetPropertyType.getQualifiedSourceName().equals(JPrimitiveType.FLOAT.getQualifiedBoxedSourceName()))||
(widgetPropertyType.getQualifiedSourceName().equals(JPrimitiveType.DOUBLE.getQualifiedBoxedSourceName()));
}
/**
* Verify if the given field is a visible property
* @param voClass
* @param field
* @param allowProtected
* @return
*/
public static boolean isPropertyVisibleToRead(JClassType voClass, JField field, boolean allowProtected)
{
if (field.isPublic() || (allowProtected && field.isProtected()))
{
return true;
}
else
{
return hasGetMethod(field, voClass);
}
}
/**
* Verify if the given field is a visible property
* @param voClass
* @param field
* @param allowProtected
* @return
*/
public static boolean isPropertyVisibleToWrite(JClassType voClass, JField field, boolean allowProtected)
{
if ((field.isPublic() || (allowProtected && field.isProtected())) && !field.isFinal())
{
return true;
}
else
{
return hasSetMethod(field, voClass);
}
}
/**
* @param type
* @return
*/
public static boolean isSimpleType(JType type)
{
if (type instanceof JPrimitiveType)
{
return true;
}
else
{
try
{
JClassType classType = (JClassType)type;
JClassType charSequenceType = classType.getOracle().getType(CharSequence.class.getCanonicalName());
JClassType dateType = classType.getOracle().getType(Date.class.getCanonicalName());
JClassType sqlDateType = classType.getOracle().getType(java.sql.Date.class.getCanonicalName());
JClassType numberType = classType.getOracle().getType(Number.class.getCanonicalName());
JClassType booleanType = classType.getOracle().getType(Boolean.class.getCanonicalName());
JClassType characterType = classType.getOracle().getType(Character.class.getCanonicalName());
JClassType bigIntegerType = classType.getOracle().getType(BigInteger.class.getCanonicalName());
JClassType bigDecimalType = classType.getOracle().getType(BigDecimal.class.getCanonicalName());
return (classType.isPrimitive() != null) ||
(numberType.isAssignableFrom(classType)) ||
(booleanType.isAssignableFrom(classType)) ||
(characterType.isAssignableFrom(classType)) ||
(charSequenceType.isAssignableFrom(classType)) ||
(charSequenceType.isAssignableFrom(classType)) ||
(dateType.isAssignableFrom(classType)) ||
(sqlDateType.isAssignableFrom(classType)) ||
(bigIntegerType.isAssignableFrom(classType)) ||
(bigDecimalType.isAssignableFrom(classType)) ||
(classType.isEnum() != null);
}
catch (NotFoundException e)
{
throw new CruxGeneratorException(e.getMessage(), e);
}
}
}
public static boolean isValidGetterMethod(JMethod method)
{
return ((method.isPublic() && method.getName().startsWith("get") && method.getName().length() >3
&& method.getParameters().length == 0) && !method.getName().equals("getClass")
|| (method.isPublic() && method.getName().startsWith("is") && method.getName().length() >2
&& method.getParameters().length == 0)
&& (method.getReturnType() == JPrimitiveType.BOOLEAN || Boolean.class.getCanonicalName().equals(method.getReturnType().getQualifiedSourceName()))
);
}
public static boolean isValidSetterMethod(JMethod method)
{
return (method.isPublic() && method.getName().startsWith("set") && method.getName().length() >3 && method.getParameters().length == 1);
}
private static JType buildGetExpression(String prop, JClassType baseClassType, StringBuilder getExpression)
{
String getterMethod = JClassUtils.getGetterMethod(prop, baseClassType);
if (getterMethod == null)
{
JMethod method = getMethod(baseClassType, prop, new JType[]{});
if (method == null)
{
method = getMethodOverInterfaces(baseClassType, prop, new JType[]{});
if (method == null)
{
return null;
}
getterMethod = method.getName();
baseClassType = method.getEnclosingType();
}
else
{
getterMethod = prop;
}
}
getExpression.append("."+getterMethod+"()");
return JClassUtils.getReturnTypeFromMethodClass(baseClassType, getterMethod, new JType[]{});
}
public static class PropertyInfo
{
private final String name;
private final JMethod readMethod;
private final JType type;
private final JMethod writeMethod;
public PropertyInfo(String name, JType type, JMethod readMethod, JMethod writeMethod)
{
this.name = name;
this.type = type;
this.readMethod = readMethod;
this.writeMethod = writeMethod;
}
public String getName()
{
return name;
}
public JMethod getReadMethod()
{
return readMethod;
}
public JType getType()
{
return type;
}
public JMethod getWriteMethod()
{
return writeMethod;
}
}
}