Author: nbelaevski
Date: 2009-12-04 15:55:31 -0500 (Fri, 04 Dec 2009)
New Revision: 16075
Added:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELParserUtils.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/NullType.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AbstractBinaryOperationTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryArithmeticIntegerOperationTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryArithmeticOperationTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryBooleanOperationTreeNode.java
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/TypeUtilsTest.java
Removed:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELReflectionUtils.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryOperationTreeNode.java
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELNodeConstants.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELVisitor.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AbstractTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstBracketSuffixTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstChoiceTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstDeferredOrDynamicExpressionTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstEmptyTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstFloatingPointTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstFunctionTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstIdentifierTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstIntegerTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstLiteralTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstMethodSuffixTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstNegativeTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstNotTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstPropertySuffixTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstStringTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstValueTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/ConstantValueTreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/ITreeNode.java
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/templatecompiler/RendererClassVisitor.java
root/cdk/trunk/plugins/generator/src/main/resources/META-INF/templates/java/write-text.ftl
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/Bean.java
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/ELParserTest.java
Log:
https://jira.jboss.org/jira/browse/RF-7732
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELNodeConstants.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELNodeConstants.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELNodeConstants.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -45,18 +45,14 @@
public static final String TRUE_VALUE = "true";
//
- public static final String ARRAY_INDICATOR = "[L";
public static final String COLON = " : ";
public static final String COMMA = ",";
public static final String CONVERT_TO_STRING_FUNCTION = "convertToString";
public static final String DOT = ".";
public static final String DOUBLE_VALUE_OF_FUNCTION = "Double.valueOf";
public static final String EXCLAMATION_MARK = "!";
- public static final String GET_ELEMENT_BY_INDEX_FUNCTION =
"getElementByIndex";
public static final String GET_FUNCTION = "get";
public static final String GET_UTILS_FUNCTION = "getUtils";
- public static final String JAVA_UTIL_LIST = "java.util.List";
- public static final String JAVA_UTIL_MAP = "java.util.Map";
public static final String LEFT_BRACKET = "(";
public static final String LEFT_SQUARE_BRACKET = "[";
public static final String NEGATIVE = "-";
@@ -66,8 +62,8 @@
public static final String RIGHT_SQUARE_BRACKET = "]";
public static final String THIS_GET_UTILS_IS_EMPTY_FUNCTION =
"this.getUtils().isEmpty";
public static final String THIS_PREFIX = "this";
- public static final String UTILS_PREFIX = "utils";
-
+ public static final String GETTER_PREFIX = "get";
+
private ELNodeConstants() {
}
}
Copied:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELParserUtils.java
(from rev 16062,
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELReflectionUtils.java)
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELParserUtils.java
(rev 0)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELParserUtils.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -0,0 +1,617 @@
+/**
+ * License Agreement.
+ *
+ * Rich Faces - Natural Ajax for Java Server Faces (JSF)
+ *
+ * Copyright (C) 2007 Exadel, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+
+package org.richfaces.cdk.parser.el;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+import org.jboss.el.parser.AstAnd;
+import org.jboss.el.parser.AstBracketSuffix;
+import org.jboss.el.parser.AstChoice;
+import org.jboss.el.parser.AstDeferredExpression;
+import org.jboss.el.parser.AstDiv;
+import org.jboss.el.parser.AstDynamicExpression;
+import org.jboss.el.parser.AstEmpty;
+import org.jboss.el.parser.AstEqual;
+import org.jboss.el.parser.AstFalse;
+import org.jboss.el.parser.AstFloatingPoint;
+import org.jboss.el.parser.AstFunction;
+import org.jboss.el.parser.AstGreaterThan;
+import org.jboss.el.parser.AstGreaterThanEqual;
+import org.jboss.el.parser.AstIdentifier;
+import org.jboss.el.parser.AstInteger;
+import org.jboss.el.parser.AstLessThan;
+import org.jboss.el.parser.AstLessThanEqual;
+import org.jboss.el.parser.AstLiteralExpression;
+import org.jboss.el.parser.AstMethodSuffix;
+import org.jboss.el.parser.AstMinus;
+import org.jboss.el.parser.AstMod;
+import org.jboss.el.parser.AstMult;
+import org.jboss.el.parser.AstNegative;
+import org.jboss.el.parser.AstNot;
+import org.jboss.el.parser.AstNotEqual;
+import org.jboss.el.parser.AstNull;
+import org.jboss.el.parser.AstOr;
+import org.jboss.el.parser.AstPlus;
+import org.jboss.el.parser.AstPropertySuffix;
+import org.jboss.el.parser.AstString;
+import org.jboss.el.parser.AstTrue;
+import org.jboss.el.parser.AstValue;
+import org.jboss.el.parser.Node;
+import org.richfaces.cdk.parser.el.node.AstBracketSuffixTreeNode;
+import org.richfaces.cdk.parser.el.node.AstChoiceTreeNode;
+import org.richfaces.cdk.parser.el.node.AstDeferredOrDynamicExpressionTreeNode;
+import org.richfaces.cdk.parser.el.node.AstEmptyTreeNode;
+import org.richfaces.cdk.parser.el.node.AstFloatingPointTreeNode;
+import org.richfaces.cdk.parser.el.node.AstFunctionTreeNode;
+import org.richfaces.cdk.parser.el.node.AstIdentifierTreeNode;
+import org.richfaces.cdk.parser.el.node.AstIntegerTreeNode;
+import org.richfaces.cdk.parser.el.node.AstLiteralTreeNode;
+import org.richfaces.cdk.parser.el.node.AstMethodSuffixTreeNode;
+import org.richfaces.cdk.parser.el.node.AstNegativeTreeNode;
+import org.richfaces.cdk.parser.el.node.AstNotTreeNode;
+import org.richfaces.cdk.parser.el.node.AstPropertySuffixTreeNode;
+import org.richfaces.cdk.parser.el.node.AstStringTreeNode;
+import org.richfaces.cdk.parser.el.node.AstValueTreeNode;
+import org.richfaces.cdk.parser.el.node.BinaryArithmeticIntegerOperationTreeNode;
+import org.richfaces.cdk.parser.el.node.BinaryArithmeticOperationTreeNode;
+import org.richfaces.cdk.parser.el.node.BinaryBooleanOperationTreeNode;
+import org.richfaces.cdk.parser.el.node.ConstantValueTreeNode;
+import org.richfaces.cdk.parser.el.node.ITreeNode;
+
+/**
+ * Class, that encapsulate all functionality, related to Reflection calls, such as
loading classes, get property
+ * descriptors etc...
+ * @author amarkhel
+ *
+ */
+public final class ELParserUtils {
+
+ private static final class ClassDataHolder implements ClassVisitor {
+
+ private Map<String, PropertyDescriptor> resolvedProperties;
+
+ private List<Method> resolvedMethods;
+
+ public ClassDataHolder() {
+ super();
+
+ this.resolvedProperties = new HashMap<String, PropertyDescriptor>();
+ this.resolvedMethods = new ArrayList<Method>();
+ }
+
+ public Map<String, PropertyDescriptor> getResolvedProperties() {
+ return resolvedProperties;
+ }
+
+ public List<Method> getResolvedMethods() {
+ return resolvedMethods;
+ }
+
+ @Override
+ public void visit(Class<?> clazz) throws ParsingException {
+ PropertyDescriptor[] pds;
+ Method[] declaredMethods;
+
+ try {
+ pds = getPropertyDescriptors(clazz);
+ declaredMethods = clazz.getDeclaredMethods();
+ } catch (LinkageError e) {
+ throw new ParsingException(e.getMessage(), e);
+ }
+
+ for (PropertyDescriptor descriptor : pds) {
+ String descriptorName = descriptor.getName();
+ if (resolvedProperties.get(descriptorName) == null) {
+ resolvedProperties.put(descriptorName, descriptor);
+ }
+ }
+
+ for (Method declaredMethod : declaredMethods) {
+ resolvedMethods.add(declaredMethod);
+ }
+ }
+ }
+
+ private static Map<Class<?>, ClassDataHolder> classDataCache =
+ new WeakHashMap<Class<?>, ClassDataHolder>();
+
+ private ELParserUtils() { }
+
+ public static void verifyClassPropertiesAndMethods(Class<?> initialClass)
throws ParsingException {
+ resolveClassPropertiesAndMethods(initialClass);
+ }
+
+ private static ClassDataHolder resolveClassPropertiesAndMethods(Class<?>
initialClass) throws ParsingException {
+ ClassDataHolder classDataHolder = classDataCache.get(initialClass);
+ if (classDataHolder == null) {
+ classDataHolder = new ClassDataHolder();
+ new ClassWalkingLogic(initialClass).walk(classDataHolder);
+ classDataCache.put(initialClass, classDataHolder);
+ }
+
+ return classDataHolder;
+ }
+
+ /**
+ * This method determine type of parsed node and create wrapper for them, that
extends AbstractTreeNode.
+ * If node type is not recognized - throws ParsingException.
+ * @param child - parsed node
+ * @throws ParsingException - if node type is not recognized.
+ * @return wrapper for parsed node(if node type is recognized), that implement
ITreeNode interface.
+ */
+ public static ITreeNode determineNodeType(Node child) throws ParsingException {
+ ITreeNode treeNode = null;
+
+ if (child instanceof AstIdentifier) {
+ treeNode = new AstIdentifierTreeNode(child);
+ } else if (child instanceof AstValue) {
+ treeNode = new AstValueTreeNode(child);
+ } else if (child instanceof AstInteger) {
+ treeNode = new AstIntegerTreeNode(child);
+ } else if (child instanceof AstString) {
+ treeNode = new AstStringTreeNode(child);
+ } else if (child instanceof AstFunction) {
+ treeNode = new AstFunctionTreeNode(child);
+ } else if (child instanceof AstDeferredExpression || child instanceof
AstDynamicExpression) {
+ treeNode = new AstDeferredOrDynamicExpressionTreeNode(child);
+ } else if (child instanceof AstNot) {
+ treeNode = new AstNotTreeNode(child);
+ } else if (child instanceof AstChoice) {
+ treeNode = new AstChoiceTreeNode(child);
+ } else if (child instanceof AstEmpty) {
+ treeNode = new AstEmptyTreeNode(child);
+ } else if (child instanceof AstLiteralExpression) {
+ treeNode = new AstLiteralTreeNode(child);
+ } else if (child instanceof AstFalse) {
+ treeNode = ConstantValueTreeNode.FALSE_NODE;
+ } else if (child instanceof AstTrue) {
+ treeNode = ConstantValueTreeNode.TRUE_NODE;
+ } else if (child instanceof AstNull) {
+ treeNode = ConstantValueTreeNode.NULL_NODE;
+ } else if (child instanceof AstAnd) {
+ treeNode = new BinaryBooleanOperationTreeNode(child,
ELNodeConstants.AND_OPERATOR);
+ } else if (child instanceof AstEqual) {
+ treeNode = new BinaryBooleanOperationTreeNode(child,
ELNodeConstants.EQUALITY_OPERATOR);
+ } else if (child instanceof AstGreaterThan) {
+ treeNode = new BinaryBooleanOperationTreeNode(child,
ELNodeConstants.GREATER_THEN_OPERATOR);
+ } else if (child instanceof AstGreaterThanEqual) {
+ treeNode = new BinaryBooleanOperationTreeNode(child,
ELNodeConstants.GREATER_THEN_OR_EQUALITY_OPERATOR);
+ } else if (child instanceof AstLessThan) {
+ treeNode = new BinaryBooleanOperationTreeNode(child,
ELNodeConstants.LESS_THEN_OPERATOR);
+ } else if (child instanceof AstLessThanEqual) {
+ treeNode = new BinaryBooleanOperationTreeNode(child,
ELNodeConstants.LESS_THEN_OR_EQUALITY_OPERATOR);
+ } else if (child instanceof AstNotEqual) {
+ treeNode = new BinaryBooleanOperationTreeNode(child,
ELNodeConstants.INEQUALITY_OPERATOR);
+ } else if (child instanceof AstOr) {
+ treeNode = new BinaryBooleanOperationTreeNode(child,
ELNodeConstants.OR_OPERATOR);
+ } else if (child instanceof AstDiv) {
+ treeNode = new BinaryArithmeticOperationTreeNode(child,
ELNodeConstants.DIV_OPERATOR);
+ } else if (child instanceof AstMult) {
+ treeNode = new BinaryArithmeticOperationTreeNode(child,
ELNodeConstants.MULT_OPERATOR);
+ } else if (child instanceof AstMod) {
+ treeNode = new BinaryArithmeticIntegerOperationTreeNode(child,
ELNodeConstants.MOD_OPERATOR);
+ } else if (child instanceof AstPlus) {
+ treeNode = new BinaryArithmeticOperationTreeNode(child,
ELNodeConstants.PLUS_OPERATOR);
+ } else if (child instanceof AstMinus) {
+ treeNode = new BinaryArithmeticOperationTreeNode(child,
ELNodeConstants.MINUS_OPERATOR);
+ } else if (child instanceof AstBracketSuffix) {
+ treeNode = new AstBracketSuffixTreeNode(child);
+ } else if (child instanceof AstNegative) {
+ treeNode = new AstNegativeTreeNode(child);
+ } else if (child instanceof AstFloatingPoint) {
+ treeNode = new AstFloatingPointTreeNode(child);
+ } else if (child instanceof AstMethodSuffix) {
+ treeNode = new AstMethodSuffixTreeNode(child);
+ } else if (child instanceof AstPropertySuffix) {
+ treeNode = new AstPropertySuffixTreeNode(child);
+ } else if (child instanceof AstBracketSuffix) {
+ treeNode = new AstBracketSuffixTreeNode(child);
+ } else {
+ throw new ParsingException("Node " +
child.getClass().getSimpleName() + "[" + child.getImage() + "] is not
recognized;");
+ }
+
+ //TODO: add support for closures
+
+ return treeNode;
+ }
+
+ /**
+ * This method return PropertyDescriptor by specified propertyName and clazz.
+ * @param clazz - class to search
+ * @param propertyName - propertyName to search
+ * @return property descriptor if found.
+ * @throws ParsingException if error occured.
+ */
+ public static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String
propertyName)
+ throws ParsingException {
+ if (clazz == null) {
+ return null;
+ }
+
+ ClassDataHolder classDataHolder = resolveClassPropertiesAndMethods(clazz);
+ return classDataHolder.getResolvedProperties().get(propertyName);
+ }
+
+ /**
+ * Returns wrapper classes for passed-in class. If type is primitive, then
corresponding
+ * wrapper class is returned (e.g. boolean -> Boolean), otherwise does nothing and
returns
+ * passed-in class.
+ *
+ * @return wrapper for primitive types, or passed-in class
+ */
+ private static Class<?> getWrapperClass(Class<?> inClazz) {
+ if (inClazz == null) {
+ return null;
+ }
+
+ if (inClazz.isPrimitive()) {
+ return getPrimitiveWrapper(inClazz);
+ } else {
+ return inClazz;
+ }
+ }
+
+ /**
+ * <p>Retrieve the property descriptors for the specified class,
+ * introspecting and caching them the first time a particular bean class
+ * is encountered.</p>
+ *
+ * <p><strong>FIXME</strong> - Does not work with
DynaBeans.</p>
+ *
+ * @param beanClass Bean class for which property descriptors are requested
+ * @return the property descriptors
+ * @throws ParsingException if error occured.
+ *
+ * @exception IllegalArgumentException if <code>beanClass</code> is null
+ */
+ private static PropertyDescriptor[] getPropertyDescriptors(Class<?> beanClass)
throws ParsingException {
+ if (beanClass == null) {
+ throw new IllegalArgumentException("No bean class specified");
+ }
+
+ // Look up any cached descriptors for this bean class
+ PropertyDescriptor[] descriptors = null;
+
+ // Introspect the bean and cache the generated descriptors
+ BeanInfo beanInfo = null;
+
+ try {
+ beanInfo = Introspector.getBeanInfo(beanClass);
+ descriptors = beanInfo.getPropertyDescriptors();
+ } catch (IntrospectionException e) {
+ return new PropertyDescriptor[0];
+ }
+
+ if (descriptors == null) {
+ descriptors = new PropertyDescriptor[0];
+ }
+
+ return descriptors;
+ }
+
+ private static boolean isMethodVisible(Method method) {
+ return !Modifier.isPrivate(method.getModifiers());
+ }
+
+ /**
+ * <p>Find an accessible method that matches the given name and has compatible
parameters.
+ * Compatible parameters mean that every method parameter is assignable from
+ * the given parameters.
+ * In other words, it finds a method with the given name
+ * that will take the parameters given.<p>
+ *
+ * <p>This method is slightly undeterminstic since it loops
+ * through methods names and return the first matching method.</p>
+ *
+ * <p>This method is used by
+ * {@link
+ * #invokeMethod(Object object,String methodName,Object [] args,Class[]
parameterTypes)}.
+ *
+ * <p>This method can match primitive parameter by passing in wrapper classes.
+ * For example, a <code>Boolean</code> will match a primitive
<code>boolean</code>
+ * parameter.
+ *
+ * @param clazz find method in this class
+ * @param methodName find method with this name
+ * @param parameterTypes find method with compatible parameters
+ * @return The accessible method
+ * @throws ParsingException if error occured.
+ */
+ public static Type getMatchingVisibleMethodReturnType(Class<?> clazz, final
String methodName,
+ Type[] parameterTypes) throws ParsingException {
+
+ if (clazz == null) {
+ return Object.class;
+ }
+
+ ClassDataHolder classDataHolder = resolveClassPropertiesAndMethods(clazz);
+ List<Method> resolvedMethods = classDataHolder.getResolvedMethods();
+
+ // search through all methods
+ int paramSize = parameterTypes.length;
+ Method bestMatch = null;
+ float bestMatchCost = Float.MAX_VALUE;
+ float myCost = Float.MAX_VALUE;
+
+ for (Method resolvedMethod: resolvedMethods) {
+ if (!isMethodVisible(resolvedMethod)) {
+ continue;
+ }
+
+ if (!resolvedMethod.getName().equals(methodName)) {
+ continue;
+ }
+
+ // compare parameters
+ Class<?>[] methodsParams = resolvedMethod.getParameterTypes();
+ int methodParamSize = methodsParams.length;
+
+ if (methodParamSize == paramSize) {
+ boolean match = true;
+
+ for (int n = 0; n < methodParamSize; n++) {
+ if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n])) {
+ match = false;
+
+ break;
+ }
+ }
+
+ if (match) {
+ myCost = getTotalTransformationCost(methodsParams, parameterTypes);
+
+ if (myCost < bestMatchCost) {
+ bestMatch = resolvedMethod;
+ bestMatchCost = myCost;
+ }
+ }
+ }
+ }
+
+ if (bestMatch != null) {
+ return bestMatch.getGenericReturnType();
+ } else {
+ return Object.class;
+ }
+ }
+
+ /**
+ * Returns the sum of the object transformation cost for each class in the source
+ * argument list.
+ * @param srcArgs The source arguments
+ * @param destArgs The destination arguments
+ * @return The total transformation cost
+ */
+ private static float getTotalTransformationCost(Type[] destArgs, Type[] srcArgs) {
+ float totalCost = 0.0f;
+
+ for (int i = 0; i < srcArgs.length; i++) {
+ Type destType = destArgs[i];
+ Type srcType = srcArgs[i];
+
+ totalCost += getObjectTransformationCost(destType, srcType);
+ }
+
+ return totalCost;
+ }
+
+ /**
+ * Gets the number of steps required needed to turn the source class into the
+ * destination class. This represents the number of steps in the object hierarchy
+ * graph.
+ * @param srcClass The source class
+ * @param destClass The destination class
+ * @return The cost of transforming an object
+ */
+ private static float getObjectTransformationCost(Type destType, Type srcType) {
+ float cost = 0.0f;
+
+ if (ELParserUtils.isNullType(srcType)) {
+ return cost;
+ }
+
+ Class<?> srcClass = ELParserUtils.getRawType(srcType);
+ Class<?> destClass = ELParserUtils.getRawType(destType);
+
+ while (srcClass != null &&
!getWrapperClass(destClass).equals(getWrapperClass(srcClass))) {
+ if (destClass.isInterface() && isAssignmentCompatible(destClass, srcClass))
{
+
+ // slight penalty for interface match.
+ // we still want an exact match to override an interface match, but
+ // an interface match should override anything where we have to get a
+ // superclass.
+ cost += 0.25f;
+
+ break;
+ }
+
+ cost++;
+ srcClass = srcClass.getSuperclass();
+ }
+
+ /*
+ * If the destination class is null, we've travelled all the way up to
+ * an Object match. We'll penalize this by adding 1.5 to the cost.
+ */
+ if (srcClass == null) {
+ cost += 1.5f;
+ }
+
+ return cost;
+ }
+
+ /**
+ * <p>Determine whether a type can be used as a parameter in a method
invocation.
+ * This method handles primitive conversions correctly.</p>
+ *
+ * <p>In order words, it will match a <code>Boolean</code> to a
<code>boolean</code>,
+ * a <code>Long</code> to a <code>long</code>,
+ * a <code>Float</code> to a <code>float</code>,
+ * a <code>Integer</code> to a <code>int</code>,
+ * and a <code>Double</code> to a <code>double</code>.
+ * Now logic widening matches are allowed.
+ * For example, a <code>Long</code> will not match a
<code>int</code>.
+ *
+ * @param parameterType the type of parameter accepted by the method
+ * @param parameterization the type of parameter being tested
+ *
+ * @return true if the assignement is compatible.
+ */
+ public static boolean isAssignmentCompatible(Type parameterType, Type
parameterization) {
+ Class<?> parameterClass = ELParserUtils.getRawType(parameterType);
+
+ if (ELParserUtils.isNullType(parameterization)) {
+ //null value can be assigned to any class except primitive
+ return !parameterClass.isPrimitive();
+ } else {
+ Class<?> parameterWrappedClass = getWrapperClass(parameterClass);
+ Class<?> parameterizationWrappedClass =
getWrapperClass(ELParserUtils.getRawType(parameterization));
+ return parameterWrappedClass.isAssignableFrom(parameterizationWrappedClass);
+ }
+ }
+
+ /**
+ * Gets the wrapper object class for the given primitive type class.
+ * For example, passing <code>boolean.class</code> returns
<code>Boolean.class</code>
+ * @param primitiveType the primitive type class for which a match is to be found
+ * @return the wrapper type associated with the given primitive
+ * or null if no match is found
+ */
+ private static Class<?> getPrimitiveWrapper(Class<?> primitiveType) {
+
+ // does anyone know a better strategy than comparing names?
+ if (boolean.class.equals(primitiveType)) {
+ return Boolean.class;
+ } else if (float.class.equals(primitiveType)) {
+ return Float.class;
+ } else if (long.class.equals(primitiveType)) {
+ return Long.class;
+ } else if (int.class.equals(primitiveType)) {
+ return Integer.class;
+ } else if (short.class.equals(primitiveType)) {
+ return Short.class;
+ } else if (byte.class.equals(primitiveType)) {
+ return Byte.class;
+ } else if (double.class.equals(primitiveType)) {
+ return Double.class;
+ } else if (char.class.equals(primitiveType)) {
+ return Character.class;
+ } else {
+ throw new IllegalArgumentException(
+ MessageFormat.format("Type {0} is not primitive!",
primitiveType.getName()));
+ }
+ }
+
+ interface ClassVisitor {
+ public void visit(Class<?> clazz) throws ParsingException;
+ }
+
+ static class ClassWalkingLogic {
+ private Queue<Class<?>> classesList = new
LinkedList<Class<?>>();
+
+ private Set<Class<?>> visitedClasses = new
HashSet<Class<?>>();
+
+ public ClassWalkingLogic(Class<?> clazz) {
+ super();
+
+ this.classesList.add(clazz);
+ }
+
+ public void walk(ClassVisitor visitor) throws ParsingException {
+ //BFS algorithm
+ while (!classesList.isEmpty()) {
+ Class<?> clazz = classesList.remove();
+
+ visitor.visit(clazz);
+
+ Class<?> superclass = clazz.getSuperclass();
+ if (superclass != null) {
+ if (visitedClasses.add(superclass)) {
+ classesList.add(superclass);
+ }
+ }
+
+ Class<?>[] interfaces = clazz.getInterfaces();
+ if (interfaces != null) {
+ for (Class<?> iface : interfaces) {
+ if (visitedClasses.add(superclass)) {
+ classesList.add(iface);
+ }
+ }
+ }
+ }
+
+ //this is for the case when we started just from interface, not class
+ if (visitedClasses.add(Object.class)) {
+ visitor.visit(Object.class);
+ }
+ }
+ }
+
+ public static boolean isNullType(Type type) {
+ return type instanceof NullType;
+ }
+
+ public static Type getLastTypeArgument(Type type) {
+ Type[] actualTypeArguments = null;
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+ actualTypeArguments = parameterizedType.getActualTypeArguments();
+ }
+
+ if (actualTypeArguments != null && actualTypeArguments.length != 0) {
+ return actualTypeArguments[actualTypeArguments.length - 1];
+ } else {
+ return null;
+ }
+ }
+
+ public static Class<?> getRawType(Type type) {
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = (ParameterizedType) type;
+ return (Class<?>) parameterizedType.getRawType();
+ } else if (type instanceof Class<?>) {
+ return (Class<?>) type;
+ } else {
+ return null;
+ }
+ }
+}
Deleted:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELReflectionUtils.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELReflectionUtils.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELReflectionUtils.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -1,785 +0,0 @@
-/**
- * License Agreement.
- *
- * Rich Faces - Natural Ajax for Java Server Faces (JSF)
- *
- * Copyright (C) 2007 Exadel, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-package org.richfaces.cdk.parser.el;
-
-import org.jboss.el.parser.*;
-import org.richfaces.cdk.parser.el.node.*;
-
-import java.beans.BeanInfo;
-import java.beans.IndexedPropertyDescriptor;
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * Class, that encapsulate all functionality, related to Reflection calls, such as
loading classes, get property
- * descriptors etc...
- *
- * @author amarkhel
- */
-public final class ELReflectionUtils {
- private static final Class<?>[] EMPTY_CLASS_PARAMETERS = new
Class<?>[0];
- private static Map<String, Map<String, PropertyDescriptor>>
resolvedProperties =
- new HashMap<String, Map<String, PropertyDescriptor>>();
-
- private ELReflectionUtils() {
- }
-
- /**
- * This method determine type of parsed node and create wrapper for them, that
extends AbstractTreeNode.
- * If node type is not recognized - throws ParsingException.
- *
- * @param child - parsed node
- * @return wrapper for parsed node(if node type is recognized), that implement
ITreeNode interface.
- * @throws ParsingException - if node type is not recognized.
- */
- public static ITreeNode determineNodeType(Node child) throws ParsingException {
- ITreeNode treeNode = null;
-
- if (child instanceof AstIdentifier) {
- treeNode = new AstIdentifierTreeNode(child);
- } else if (child instanceof AstValue) {
- treeNode = new AstValueTreeNode(child);
- } else if (child instanceof AstInteger) {
- treeNode = new AstIntegerTreeNode(child);
- } else if (child instanceof AstString) {
- treeNode = new AstStringTreeNode(child);
- } else if (child instanceof AstFunction) {
- treeNode = new AstFunctionTreeNode(child);
- } else if (child instanceof AstDeferredExpression || child instanceof
AstDynamicExpression) {
- treeNode = new AstDeferredOrDynamicExpressionTreeNode(child);
- } else if (child instanceof AstNot) {
- treeNode = new AstNotTreeNode(child);
- } else if (child instanceof AstChoice) {
- treeNode = new AstChoiceTreeNode(child);
- } else if (child instanceof AstEmpty) {
- treeNode = new AstEmptyTreeNode(child);
- } else if (child instanceof AstLiteralExpression) {
- treeNode = new AstLiteralTreeNode(child);
- } else if (child instanceof AstFalse) {
- treeNode = ConstantValueTreeNode.FALSE_NODE;
- } else if (child instanceof AstTrue) {
- treeNode = ConstantValueTreeNode.TRUE_NODE;
- } else if (child instanceof AstNull) {
- treeNode = ConstantValueTreeNode.NULL_NODE;
- } else if (child instanceof AstAnd) {
- treeNode = new BinaryOperationTreeNode(child, ELNodeConstants.AND_OPERATOR);
- } else if (child instanceof AstEqual) {
- treeNode = new BinaryOperationTreeNode(child,
ELNodeConstants.EQUALITY_OPERATOR);
- } else if (child instanceof AstGreaterThan) {
- treeNode = new BinaryOperationTreeNode(child,
ELNodeConstants.GREATER_THEN_OPERATOR);
- } else if (child instanceof AstGreaterThanEqual) {
- treeNode = new BinaryOperationTreeNode(child,
ELNodeConstants.GREATER_THEN_OR_EQUALITY_OPERATOR);
- } else if (child instanceof AstLessThan) {
- treeNode = new BinaryOperationTreeNode(child,
ELNodeConstants.LESS_THEN_OPERATOR);
- } else if (child instanceof AstLessThanEqual) {
- treeNode = new BinaryOperationTreeNode(child,
ELNodeConstants.LESS_THEN_OR_EQUALITY_OPERATOR);
- } else if (child instanceof AstNotEqual) {
- treeNode = new BinaryOperationTreeNode(child,
ELNodeConstants.INEQUALITY_OPERATOR);
- } else if (child instanceof AstOr) {
- treeNode = new BinaryOperationTreeNode(child, ELNodeConstants.OR_OPERATOR);
- } else if (child instanceof AstDiv) {
- treeNode = new BinaryOperationTreeNode(child, ELNodeConstants.DIV_OPERATOR);
- } else if (child instanceof AstMult) {
- treeNode = new BinaryOperationTreeNode(child,
ELNodeConstants.MULT_OPERATOR);
- } else if (child instanceof AstMod) {
- treeNode = new BinaryOperationTreeNode(child, ELNodeConstants.MOD_OPERATOR);
- } else if (child instanceof AstPlus) {
- treeNode = new BinaryOperationTreeNode(child,
ELNodeConstants.PLUS_OPERATOR);
- } else if (child instanceof AstMinus) {
- treeNode = new BinaryOperationTreeNode(child,
ELNodeConstants.MINUS_OPERATOR);
- } else if (child instanceof AstBracketSuffix) {
- treeNode = new AstBracketSuffixTreeNode(child);
- } else if (child instanceof AstNegative) {
- treeNode = new AstNegativeTreeNode(child);
- } else if (child instanceof AstFloatingPoint) {
- treeNode = new AstFloatingPointTreeNode(child);
- } else if (child instanceof AstMethodSuffix) {
- treeNode = new AstMethodSuffixTreeNode(child);
- } else if (child instanceof AstPropertySuffix) {
- treeNode = new AstPropertySuffixTreeNode(child);
- } else if (child instanceof AstBracketSuffix) {
- treeNode = new AstBracketSuffixTreeNode(child);
- } else {
- throw new ParsingException("Node " +
child.getClass().getSimpleName() + "[" + child.getImage() + "] is not
recognized;");
- }
-
- //TODO: add support for closures
-
- return treeNode;
- }
-
- /**
- * This method return PropertyDescriptor by specified propertyName and clazz.
- *
- * @param clazz - class to search
- * @param propertyName - propertyName to search
- * @return property descriptor if found.
- * @throws ParsingException if error occured.
- */
- private static PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String
propertyName)
- throws ParsingException {
-
- Map<String, PropertyDescriptor> descriptors =
resolvedProperties.get(clazz.getName());
-
- if (descriptors == null) {
- descriptors = resolveProperties(clazz);
- resolvedProperties.put(clazz.getName(), descriptors);
- }
-
- return descriptors.get(propertyName);
- }
-
- /**
- * This method resolve all properties of specified class.
- *
- * @param clazz - class to resolve
- * @return Map<String, PropertyDescriptor>, populated by property descriptors.
- * @throws ParsingException if error occured.
- */
- private static Map<String, PropertyDescriptor> resolveProperties(Class<?>
clazz) throws ParsingException {
- final Map<String, PropertyDescriptor> descriptors = new HashMap<String,
PropertyDescriptor>();
-
- new ClassWalkingLogic(clazz).walk(new ClassVisitor() {
- public void visit(Class<?> clazz) throws ParsingException {
- PropertyDescriptor[] pds = getPropertyDescriptors(clazz);
-
- for (PropertyDescriptor descriptor : pds) {
- descriptors.put(descriptor.getName(), descriptor);
- }
- }
- });
-
- return descriptors;
- }
-
- /**
- * This method load specified class.
- *
- * @param className - class to load.
- * @return loaded class.
- * @throws ClassNotFoundException if class not found.
- */
- private static Class<?> loadClass(Class<?> className) throws
ClassNotFoundException {
- Class<?> clazz = null;
-
- try {
- if (className.isPrimitive()) {
- clazz = getPrimitiveWrapper(className);
- } else {
- clazz = loadClass(className.getName());
- }
- } catch (ClassNotFoundException e) {
- throw e;
- }
-
- if (null == clazz) {
- throw new ClassNotFoundException(className.getName());
- }
-
- return clazz;
- }
-
- /**
- * This method load class by specified representation of class name..
- *
- * @param className - string representation of class.
- * @return loaded class.
- * @throws ClassNotFoundException if class not found.
- */
- private static Class<?> loadClass(String className) throws
ClassNotFoundException {
- Class<?> clazz = null;
-
- try {
- clazz = Thread.currentThread().getContextClassLoader().loadClass(className);
- } catch (ClassNotFoundException e) {
- throw e;
- }
-
- if (null == clazz) {
- throw new ClassNotFoundException(className);
- }
-
- return clazz;
- }
-
- /**
- * <p>Retrieve the property descriptors for the specified class,
- * introspecting and caching them the first time a particular bean class
- * is encountered.</p>
- * <p/>
- * <p><strong>FIXME</strong> - Does not work with
DynaBeans.</p>
- *
- * @param beanClass Bean class for which property descriptors are requested
- * @return the property descriptors
- * @throws ParsingException if error occured.
- * @throws IllegalArgumentException if <code>beanClass</code> is null
- */
- private static PropertyDescriptor[] getPropertyDescriptors(Class<?> beanClass)
throws ParsingException {
- if (beanClass == null) {
- throw new IllegalArgumentException("No bean class specified");
- }
-
- // Look up any cached descriptors for this bean class
- PropertyDescriptor[] descriptors = null;
-
- // Introspect the bean and cache the generated descriptors
- BeanInfo beanInfo = null;
-
- try {
- beanInfo = Introspector.getBeanInfo(beanClass);
- } catch (IntrospectionException e) {
- return new PropertyDescriptor[0];
- }
-
- descriptors = beanInfo.getPropertyDescriptors();
-
- if (descriptors == null) {
- descriptors = new PropertyDescriptor[0];
- }
-
- for (int i = 0; i < descriptors.length; i++) {
- if (descriptors[i] instanceof IndexedPropertyDescriptor) {
- IndexedPropertyDescriptor descriptor = (IndexedPropertyDescriptor)
descriptors[i];
- String propName = descriptor.getName().substring(0, 1).toUpperCase()
- + descriptor.getName().substring(1);
-
- if (descriptor.getReadMethod() == null) {
- String methodName = descriptor.getIndexedReadMethod() != null
- ? descriptor.getIndexedReadMethod().getName() : "get" +
propName;
- Method readMethod = getMatchingAccessibleMethod(beanClass,
methodName, EMPTY_CLASS_PARAMETERS);
-
- if (readMethod != null) {
- try {
- descriptor.setReadMethod(readMethod);
- } catch (Exception e) {
-
- // TODO Refactoring
- }
- }
- }
- }
- }
-
- return descriptors;
- }
-
- /**
- * <p>Find an accessible method that matches the given name and has compatible
parameters.
- * Compatible parameters mean that every method parameter is assignable from
- * the given parameters.
- * In other words, it finds a method with the given name
- * that will take the parameters given.<p>
- * <p/>
- * <p>This method is slightly undeterminstic since it loops
- * through methods names and return the first matching method.</p>
- * <p/>
- * <p>This method is used by
- * {@link
- * #invokeMethod(Object object,String methodName,Object [] args,Class[]
parameterTypes)}.
- * <p/>
- * <p>This method can match primitive parameter by passing in wrapper classes.
- * For example, a <code>Boolean</code> will match a primitive
<code>boolean</code>
- * parameter.
- *
- * @param clazz find method in this class
- * @param methodName find method with this name
- * @param parameterTypes find method with compatible parameters
- * @return The accessible method
- * @throws ParsingException if error occured.
- */
- private static Method getMatchingAccessibleMethod(Class<?> clazz, String
methodName, Class<?>[] parameterTypes)
- throws ParsingException {
-
- // see if we can find the method directly
- // most of the time this works and it's much faster
- try {
- Method method = clazz.getMethod(methodName, parameterTypes);
-
- setMethodAccessible(method); // Default access superclass workaround
-
- return method;
- } catch (NoSuchMethodException e) {
-
- /* SWALLOW */
- }
-
- // search through all methods
- int paramSize = parameterTypes.length;
- Method bestMatch = null;
- Method[] methods = clazz.getMethods();
- float bestMatchCost = Float.MAX_VALUE;
- float myCost = Float.MAX_VALUE;
- int size = methods.length;
-
- for (int i = 0; i < size; i++) {
- if (methods[i].getName().equals(methodName)) {
-
- // compare parameters
- Class<?>[] methodsParams = methods[i].getParameterTypes();
- int methodParamSize = methodsParams.length;
-
- if (methodParamSize == paramSize) {
- boolean match = true;
-
- for (int n = 0; n < methodParamSize; n++) {
- if (!isAssignmentCompatible(methodsParams[n], parameterTypes[n]))
{
- match = false;
-
- break;
- }
- }
-
- if (match) {
-
- // get accessible version of method
- Method method = getAccessibleMethod(clazz, methods[i]);
-
- if (method != null) {
- setMethodAccessible(method); // Default access superclass
workaround
- myCost = getTotalTransformationCost(parameterTypes,
method.getParameterTypes());
-
- if (myCost < bestMatchCost) {
- bestMatch = method;
- bestMatchCost = myCost;
- }
- }
- }
- }
- }
- }
-
- return bestMatch;
- }
-
- /**
- * <p>Return an accessible method (that is, one that can be invoked via
- * reflection) that implements the specified Method. If no such method
- * can be found, return <code>null</code>.</p>
- *
- * @param clazz The class of the object
- * @param method The method that we wish to call
- * @return The accessible method
- * @throws ParsingException if error occured.
- */
- private static Method getAccessibleMethod(Class<?> clazz, Method method) throws
ParsingException {
-
- // Make sure we have a method to check
- if (method == null) {
- return null;
- }
-
- // If the requested method is not public we cannot call it
- if (!Modifier.isPublic(method.getModifiers())) {
- return null;
- }
-
- boolean sameClass = true;
-
- if (clazz == null) {
- clazz = method.getDeclaringClass();
- } else {
- sameClass = clazz.equals(method.getDeclaringClass());
-
- if (!method.getDeclaringClass().isAssignableFrom(clazz)) {
- throw new IllegalArgumentException(clazz.getName() + " is not
assignable from "
- + method.getDeclaringClass().getName());
- }
- }
-
- // If the class is public, we are done
- if (Modifier.isPublic(clazz.getModifiers())) {
- if (!sameClass &&
!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {
- setMethodAccessible(method); // Default access superclass workaround
- }
-
- return method;
- }
-
- String methodName = method.getName();
- Class<?>[] parameterTypes = method.getParameterTypes();
-
- // Check the implemented interfaces and subinterfaces
- method = getAccessibleMethodFromInterfaceNest(clazz, methodName,
parameterTypes);
-
- // Check the superclass chain
- if (method == null) {
- method = getAccessibleMethodFromSuperclass(clazz, methodName,
parameterTypes);
- }
-
- return method;
- }
-
- /**
- * <p>Return an accessible method (that is, one that can be invoked via
- * reflection) by scanning through the superclasses. If no such method
- * can be found, return <code>null</code>.</p>
- *
- * @param clazz Class to be checked
- * @param methodName Method name of the method we wish to call
- * @param parameterTypes The parameter type signatures
- */
- private static Method getAccessibleMethodFromSuperclass(Class<?> clazz, String
methodName,
- Class<?>[]
parameterTypes) {
- Class<?> parentClazz = clazz.getSuperclass();
-
- while (parentClazz != null) {
- if (Modifier.isPublic(parentClazz.getModifiers())) {
- try {
- return parentClazz.getMethod(methodName, parameterTypes);
- } catch (NoSuchMethodException e) {
- return null;
- }
- }
-
- parentClazz = parentClazz.getSuperclass();
- }
-
- return null;
- }
-
- /**
- * <p>Return an accessible method (that is, one that can be invoked via
- * reflection) that implements the specified method, by scanning through
- * all implemented interfaces and subinterfaces. If no such method
- * can be found, return <code>null</code>.</p>
- * <p/>
- * <p> There isn't any good reason why this method must be private.
- * It is because there doesn't seem any reason why other classes should
- * call this rather than the higher level methods.</p>
- *
- * @param clazz Parent class for the interfaces to be checked
- * @param methodName Method name of the method we wish to call
- * @param parameterTypes The parameter type signatures
- */
- private static Method getAccessibleMethodFromInterfaceNest(Class<?> clazz,
String methodName,
- Class<?>[]
parameterTypes) {
- Method method = null;
-
- // Search up the superclass chain
- for (; clazz != null; clazz = clazz.getSuperclass()) {
-
- // Check the implemented interfaces of the parent class
- Class<?>[] interfaces = clazz.getInterfaces();
-
- for (int i = 0; i < interfaces.length; i++) {
-
- // Is this interface public?
- if (!Modifier.isPublic(interfaces[i].getModifiers())) {
- continue;
- }
-
- // Does the method exist on this interface?
- try {
- method = interfaces[i].getDeclaredMethod(methodName,
parameterTypes);
- } catch (NoSuchMethodException e) {
-
- /*
- * Swallow, if no method is found after the loop then this
- * method returns null.
- */
- }
-
- if (method != null) {
- return method;
- }
-
- // Recursively check our parent interfaces
- method = getAccessibleMethodFromInterfaceNest(interfaces[i], methodName,
parameterTypes);
-
- if (method != null) {
- return method;
- }
- }
- }
-
- // If we found a method return it
- if (method != null) {
- return method;
- }
-
- // We did not find anything
- return null;
- }
-
- /**
- * Returns the sum of the object transformation cost for each class in the source
- * argument list.
- *
- * @param srcArgs The source arguments
- * @param destArgs The destination arguments
- * @return The total transformation cost
- */
- private static float getTotalTransformationCost(Class<?>[] srcArgs,
Class<?>[] destArgs) {
- float totalCost = 0.0f;
-
- for (int i = 0; i < srcArgs.length; i++) {
- Class<?> srcClass = srcArgs[i];
- Class<?> destClass = destArgs[i];
-
- totalCost += getObjectTransformationCost(srcClass, destClass);
- }
-
- return totalCost;
- }
-
- /**
- * Gets the number of steps required needed to turn the source class into the
- * destination class. This represents the number of steps in the object hierarchy
- * graph.
- *
- * @param srcClass The source class
- * @param destClass The destination class
- * @return The cost of transforming an object
- */
- private static float getObjectTransformationCost(Class<?> srcClass,
Class<?> destClass) {
- float cost = 0.0f;
-
- while (destClass != null && !destClass.equals(srcClass)) {
- if (destClass.isInterface() && isAssignmentCompatible(destClass,
srcClass)) {
-
- // slight penalty for interface match.
- // we still want an exact match to override an interface match, but
- // an interface match should override anything where we have to get a
- // superclass.
- cost += 0.25f;
-
- break;
- }
-
- cost++;
- destClass = destClass.getSuperclass();
- }
-
- /*
- * If the destination class is null, we've travelled all the way up to
- * an Object match. We'll penalize this by adding 1.5 to the cost.
- */
- if (destClass == null) {
- cost += 1.5f;
- }
-
- return cost;
- }
-
- /**
- * <p>Determine whether a type can be used as a parameter in a method
invocation.
- * This method handles primitive conversions correctly.</p>
- * <p/>
- * <p>In order words, it will match a <code>Boolean</code> to a
<code>boolean</code>,
- * a <code>Long</code> to a <code>long</code>,
- * a <code>Float</code> to a <code>float</code>,
- * a <code>Integer</code> to a <code>int</code>,
- * and a <code>Double</code> to a <code>double</code>.
- * Now logic widening matches are allowed.
- * For example, a <code>Long</code> will not match a
<code>int</code>.
- *
- * @param parameterType the type of parameter accepted by the method
- * @param parameterization the type of parameter being tested
- * @return true if the assignement is compatible.
- */
- private static boolean isAssignmentCompatible(Class<?> parameterType,
Class<?> parameterization) {
-
- // try plain assignment
- if (parameterType.isAssignableFrom(parameterization)) {
- return true;
- }
-
- if (parameterType.isPrimitive()) {
-
- // this method does *not* do widening - you must specify exactly
- // is this the right behaviour?
- Class<?> parameterWrapperClazz = getPrimitiveWrapper(parameterType);
-
- if (parameterWrapperClazz != null) {
- return parameterWrapperClazz.equals(parameterization);
- }
- }
-
- return false;
- }
-
- /**
- * Gets the wrapper object class for the given primitive type class.
- * For example, passing <code>boolean.class</code> returns
<code>Boolean.class</code>
- *
- * @param primitiveType the primitive type class for which a match is to be found
- * @return the wrapper type associated with the given primitive
- * or null if no match is found
- */
- private static Class<?> getPrimitiveWrapper(Class<?> primitiveType) {
-
- // does anyone know a better strategy than comparing names?
- if (boolean.class.equals(primitiveType)) {
- return Boolean.class;
- } else if (float.class.equals(primitiveType)) {
- return Float.class;
- } else if (long.class.equals(primitiveType)) {
- return Long.class;
- } else if (int.class.equals(primitiveType)) {
- return Integer.class;
- } else if (short.class.equals(primitiveType)) {
- return Short.class;
- } else if (byte.class.equals(primitiveType)) {
- return Byte.class;
- } else if (double.class.equals(primitiveType)) {
- return Double.class;
- } else if (char.class.equals(primitiveType)) {
- return Character.class;
- } else {
- return null;
- }
- }
-
- /**
- * Try to make the method accessible
- *
- * @param method The source arguments
- * @throws ParsingException if error occured during call setAccessible method.
- */
- private static void setMethodAccessible(Method method) throws ParsingException {
- try {
-
- //
- // XXX Default access superclass workaround
- //
- // When a public class has a default access superclass
- // with public methods, these methods are accessible.
- // Calling them from compiled code works fine.
- //
- // Unfortunately, using reflection to invoke these methods
- // seems to (wrongly) to prevent access even when the method
- // modifer is public.
- //
- // The following workaround solves the problem but will only
- // work from sufficiently privilages code.
- //
- // Better workarounds would be greatfully accepted.
- //
- method.setAccessible(true);
- } catch (SecurityException se) {
- throw new ParsingException(
- "Cannot setAccessible on method. Therefore cannot use jvm access bug
workaround.", se);
- }
- }
-
- /**
- * Gets the name of read method for specified property name.
- *
- * @param propertyName - property to lookup
- * @param visitor - ELVisitor instance
- * @return String representation of read method of specified property.
- * @throws ParsingException - if property not found or class not found.
- */
- public static String getReadMethodName(String propertyName, ELVisitor visitor) throws
ParsingException {
- try {
- Class<?> clazz = loadClass(visitor.getLastVariableType());
- PropertyDescriptor propertyDescriptor = getPropertyDescriptor(clazz,
propertyName);
-
- if (propertyDescriptor == null) {
- throw new ParsingException("property: " + propertyName + "
not found in class: "
- + visitor.getLastVariableType());
- }
-
- Class<?> propertyType = propertyDescriptor.getPropertyType();
-
- visitor.setLastVariableType(propertyType);
-
- if
(visitor.getLastVariableType().getName().compareTo(ELNodeConstants.JAVA_UTIL_MAP) == 0) {
- Method readMethod = propertyDescriptor.getReadMethod();
- Type genericReturnType = readMethod.getGenericReturnType();
-
- if (genericReturnType instanceof ParameterizedType) {
- ParameterizedType type = (ParameterizedType) genericReturnType;
- Type[] typeArguments = type.getActualTypeArguments();
-
- visitor.setCollectionVariableType((Class<?>)
typeArguments[1]);
- }
- }
-
- if
(visitor.getLastVariableType().getName().compareTo(ELNodeConstants.JAVA_UTIL_LIST) == 0)
{
- Method readMethod = propertyDescriptor.getReadMethod();
- Type genericReturnType = readMethod.getGenericReturnType();
-
- if (genericReturnType instanceof ParameterizedType) {
- ParameterizedType type = (ParameterizedType) genericReturnType;
- Type[] typeArguments = type.getActualTypeArguments();
-
- visitor.setCollectionVariableType((Class<?>)
typeArguments[0]);
- }
- }
-
- if
(visitor.getLastVariableType().getName().startsWith(ELNodeConstants.ARRAY_INDICATOR)) {
- Method readMethod = propertyDescriptor.getReadMethod();
-
- visitor.setCollectionVariableType(readMethod.getReturnType());
-
- String className =
visitor.getCollectionVariableType().getName().substring(0,
- visitor.getCollectionVariableType().getName().length() -
1).substring(2);
-
- visitor.setCollectionVariableType(loadClass(className));
- }
-
- return propertyDescriptor.getReadMethod().getName();
- } catch (ClassNotFoundException cnfe) {
- throw new ParsingException(cnfe.getMessage());
- }
- }
-
- interface ClassVisitor {
- public void visit(Class<?> clazz) throws ParsingException;
- }
-
- static class ClassWalkingLogic {
- private Class<?> clazz;
-
- public ClassWalkingLogic(Class<?> clazz) {
- super();
- this.clazz = clazz;
- }
-
- public void walk(ClassVisitor visitor) throws ParsingException {
- walkClass(clazz, visitor);
- }
-
- private void walkClass(Class<?> c, ClassVisitor visitor) throws
ParsingException {
- if (c == null || Object.class.getName().equals(c.getName())) {
- return;
- }
-
- Class<?>[] interfaces = c.getInterfaces();
-
- for (Class<?> class1 : interfaces) {
- walkClass(class1, visitor);
- }
-
- walkClass(c.getSuperclass(), visitor);
- visitor.visit(c);
- }
- }
-}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELVisitor.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELVisitor.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/ELVisitor.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,41 +19,30 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.AstCompositeExpression;
import org.jboss.el.parser.ELParser;
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.node.ITreeNode;
-import java.util.Map;
-
/**
* Entry point for parsing EL expressions. @see parse() method.
- *
* @author amarkhel
+ *
*/
public final class ELVisitor {
- private static ELVisitor elVisitor;
- Class<?> collectionVariableType = null;
- String lastIndexValue = "null";
- Class<?> lastVariableType = null;
+
+ private String parsedExpression = null;
+ private Type variableType = null;
boolean useConversionToString;
boolean useEmptinessCheck;
-
- private ELVisitor() {
- }
-
- public static ELVisitor getInstance() {
- if (elVisitor == null) {
- elVisitor = new ELVisitor();
- }
-
- elVisitor.refresh();
-
- return elVisitor;
- }
-
+
public boolean isUseConversionToString() {
return useConversionToString;
}
@@ -62,65 +51,57 @@
this.useConversionToString = needConversion;
}
- public boolean isUseEmptinessCheck() {
- return useEmptinessCheck;
+ public boolean isUseEmptinessCheck() {
+ return useEmptinessCheck;
+ }
+
+ public void setUseEmptinessCheck(boolean useCheckForEmpty) {
+ this.useEmptinessCheck = useCheckForEmpty;
+ }
+
+ public Type getVariableType() {
+ return variableType;
}
- public void setUseEmptinessCheck(boolean useCheckForEmpty) {
- this.useEmptinessCheck = useCheckForEmpty;
+ public void setVariableType(Type variableType) {
+ this.variableType = variableType;
}
- public String getLastIndexValue() {
- return lastIndexValue;
- }
-
- public void setLastIndexValue(String lastIndexValue) {
- this.lastIndexValue = lastIndexValue;
- }
-
- public Class<?> getLastVariableType() {
- return lastVariableType;
- }
-
- public void setLastVariableType(Class<?> lastVariableType) {
- this.lastVariableType = lastVariableType;
- }
-
- public Class<?> getCollectionVariableType() {
- return collectionVariableType;
- }
-
- public void setCollectionVariableType(Class<?> collectionVariableType) {
- this.collectionVariableType = collectionVariableType;
- }
-
/**
+ * @return the parsedExpression
+ */
+ public String getParsedExpression() {
+ return parsedExpression;
+ }
+
+ /**
* Parse specified EL expression and return Java code, that represent this
expression
- *
* @param expression - expression to resolve
* @param contextMap - Map<String, Class<?>> - context for search
classes.
* @return generated Java code.
* @throws ParsingException - if error occurred during parsing.
*/
- public String parse(String expression, Map<String, Class<?>> contextMap)
throws ParsingException {
+ public void parse(String expression, Map<String, Type> contextMap) throws
ParsingException {
+ reset();
+
Node ret = ELParser.parse(expression);
if (ret instanceof AstCompositeExpression && ret.jjtGetNumChildren()
>= 2) {
- //AstCompositeExpression with 2+ children is a mixed expression
- this.setUseConversionToString(true);
+ //AstCompositeExpression with 2+ children is a mixed expression
+ this.setUseConversionToString(true);
}
-
- return this.visit(ret, contextMap);
+
+ parsedExpression = this.visit(ret, contextMap);
}
- private String visit(Node node, Map<String, Class<?>> context) throws
ParsingException {
+ private String visit(Node node, Map<String, Type> context) throws
ParsingException {
int numChildren = node.jjtGetNumChildren();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < numChildren; i++) {
Node child = node.jjtGetChild(i);
- ITreeNode treeNode = ELReflectionUtils.determineNodeType(child);
+ ITreeNode treeNode = ELParserUtils.determineNodeType(child);
treeNode.visit(sb, context, this);
@@ -131,22 +112,11 @@
return sb.toString();
}
-
- /**
- * Reset internal state of elVisitor instance. Called after each AstValue resolved
and parsed.
- */
- public void reset() {
- lastIndexValue = "null";
- lastVariableType = null;
- collectionVariableType = null;
+
+ private void reset() {
+ parsedExpression = null;
+ useConversionToString = false;
+ useEmptinessCheck = false;
+ variableType = null;
}
-
- private void refresh() {
- lastIndexValue = "null";
- lastVariableType = null;
- collectionVariableType = null;
- useConversionToString = false;
- useEmptinessCheck = false;
- }
-
}
Added:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/NullType.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/NullType.java
(rev 0)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/NullType.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -0,0 +1,35 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.cdk.parser.el;
+
+import java.lang.reflect.Type;
+
+/**
+ * @author Nick Belaevski
+ *
+ */
+public class NullType implements Type {
+
+ public static final NullType INSTANCE = new NullType();
+
+ private NullType() {}
+}
Copied:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AbstractBinaryOperationTreeNode.java
(from rev 16062,
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryOperationTreeNode.java)
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AbstractBinaryOperationTreeNode.java
(rev 0)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AbstractBinaryOperationTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -0,0 +1,71 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.cdk.parser.el.node;
+
+import java.lang.reflect.Type;
+import java.util.Map;
+
+import org.jboss.el.parser.Node;
+import org.richfaces.cdk.parser.el.ELNodeConstants;
+import org.richfaces.cdk.parser.el.ELVisitor;
+import org.richfaces.cdk.parser.el.ParsingException;
+
+/**
+ * <p>Abstract class for all binary (having two operands) operation expression
nodes</p>
+ * <p>For operands <code>A</code> and <code>B</code> and
operator <code>x</code> output is <code>(A x B)</code></p>
+ *
+ * @author Nick Belaevski
+ */
+public abstract class AbstractBinaryOperationTreeNode extends AbstractTreeNode {
+
+ private final String operatorString;
+
+ public AbstractBinaryOperationTreeNode(Node node, String operatorString) {
+ super(node);
+
+ this.operatorString = operatorString;
+ }
+
+ protected abstract Type getOperationType(Type firstArgumentType, Type
secondArgumentType);
+
+ /* (non-Javadoc)
+ * @see org.richfaces.cdk.parser.el.node.AbstractTreeNode#visit(java.lang.StringBuilder,
java.util.Map, org.richfaces.cdk.parser.el.ELVisitor)
+ */
+ @Override
+ public void visit(StringBuilder sb, Map<String, Type> context,
+ ELVisitor visitor) throws ParsingException {
+ String firstChildOutput = getChildOutput(0, context, visitor);
+ Type firstChildType = visitor.getVariableType();
+ String secondChildOutput = getChildOutput(1, context, visitor);
+ Type secondChildType = visitor.getVariableType();
+
+ sb.append(ELNodeConstants.LEFT_BRACKET);
+
+ sb.append(firstChildOutput);
+ sb.append(operatorString);
+ sb.append(secondChildOutput);
+
+ sb.append(ELNodeConstants.RIGHT_BRACKET);
+
+ visitor.setVariableType(getOperationType(firstChildType, secondChildType));
+ }
+}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AbstractTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AbstractTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AbstractTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,19 +19,23 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
-import org.richfaces.cdk.parser.el.ELReflectionUtils;
+import org.richfaces.cdk.parser.el.ELParserUtils;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This abstract class implement some methods of ITreeNode interface to using in
subclasses.
*
* @author amarkhel
+ *
*/
public abstract class AbstractTreeNode implements ITreeNode {
private Node node;
@@ -39,30 +43,30 @@
public AbstractTreeNode(Node node) {
this.node = node;
}
-
+
/**
- * Collects output from visiting child of the current node with the specified index
and returns
+ * Collects output from visiting child of the current node with the specified index
and returns
* collected string.
- *
+ *
* @param childIndex
* @param context
* @param visitor
* @return
* @throws ParsingException
*/
- protected String getChildOutput(int childIndex, Map<String, Class<?>>
context,
- ELVisitor visitor) throws ParsingException {
-
- StringBuilder sb = new StringBuilder();
- getChild(childIndex).visit(sb, context, visitor);
-
- return sb.toString();
+ protected String getChildOutput(int childIndex, Map<String, Type> context,
+ ELVisitor visitor) throws ParsingException {
+
+ StringBuilder sb = new StringBuilder();
+ getChild(childIndex).visit(sb, context, visitor);
+
+ return sb.toString();
}
/**
* Return node of current wrapper.
+ * @return instance of org.jboss.el.parser.Node
*
- * @return instance of org.jboss.el.parser.Node
*/
public Node getNode() {
return node;
@@ -70,18 +74,18 @@
/**
* Visit current node. Generate Java code, that represent current node.
- *
* @param stringBuilder instance to collect information.
- * @param context - context to resolve beans
- * @param visitor - ELVisitor
+ * @param context - context to resolve beans
+ * @param visitor - ELVisitor
+ * @throws ParsingException - if error occurred during parsing process.
* @return instance of org.jboss.el.parser.Node
- * @throws ParsingException - if error occurred during parsing process.
+ *
*/
public ITreeNode getChild(int index) throws ParsingException {
Node childNode = getNode().jjtGetChild(index);
if (null != childNode) {
- ITreeNode treeNode = ELReflectionUtils.determineNodeType(childNode);
+ ITreeNode treeNode = ELParserUtils.determineNodeType(childNode);
return treeNode;
} else {
@@ -90,13 +94,21 @@
}
/**
+ * Returns count of children for this node
+ * @return children count
+ */
+ public int getChildrenCount() {
+ return getNode().jjtGetNumChildren();
+ }
+
+ /**
* Return child of wrapped node by specified index. Abstract operation to override in
subclasses.
- *
* @param index - index of child.
+ * @throws ParsingException - if error occurred(child not found).
* @return wrapper for child
- * @throws ParsingException - if error occurred(child not found).
+ *
*/
- public abstract void visit(StringBuilder sb, Map<String, Class<?>>
context, ELVisitor visitor)
+ public abstract void visit(StringBuilder sb, Map<String, Type> context,
ELVisitor visitor)
throws ParsingException;
-
+
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstBracketSuffixTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstBracketSuffixTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstBracketSuffixTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,19 +19,25 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.ELNodeConstants;
+import org.richfaces.cdk.parser.el.ELParserUtils;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstBracketSuffix node.
*
* @author amarkhel
+ *
*/
public class AstBracketSuffixTreeNode extends AbstractTreeNode {
public AstBracketSuffixTreeNode(Node node) {
@@ -39,32 +45,38 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
+ Type lastVariableType = visitor.getVariableType();
+ Class<?> rawType = ELParserUtils.getRawType(lastVariableType);
+
String suffixValue = getChildOutput(0, context, visitor);
- if (visitor.getLastVariableType() != null) {
- if
(visitor.getLastVariableType().getName().startsWith(ELNodeConstants.ARRAY_INDICATOR)) {
- sb.append(ELNodeConstants.LEFT_SQUARE_BRACKET);
- sb.append(suffixValue);
- sb.append(ELNodeConstants.RIGHT_SQUARE_BRACKET);
- visitor.setLastVariableType(visitor.getCollectionVariableType());
+ if (rawType != null && rawType.isArray()) {
+ sb.append(ELNodeConstants.LEFT_SQUARE_BRACKET);
+ sb.append(suffixValue);
+ sb.append(ELNodeConstants.RIGHT_SQUARE_BRACKET);
+
+ //TODO: support for generified arrays
+ visitor.setVariableType(rawType.getComponentType());
+ } else {
+ Type collectionValueType = null;
+ if (rawType != null &&
+ (List.class.isAssignableFrom(rawType) ||
Map.class.isAssignableFrom(rawType))) {
+
+ collectionValueType = ELParserUtils.getLastTypeArgument(lastVariableType);
}
-
- if
((visitor.getLastVariableType().getName().compareTo(ELNodeConstants.JAVA_UTIL_LIST) == 0)
- ||
(visitor.getLastVariableType().getName().compareTo(ELNodeConstants.JAVA_UTIL_MAP) == 0))
{
- sb.append(ELNodeConstants.GET_FUNCTION);
- sb.append(ELNodeConstants.LEFT_BRACKET);
- sb.append(suffixValue);
- sb.append(ELNodeConstants.RIGHT_BRACKET);
- visitor.setLastVariableType(visitor.getCollectionVariableType());
+
+ if (collectionValueType == null) {
+ collectionValueType = Object.class;
}
- } else {
- sb.append(ELNodeConstants.GET_ELEMENT_BY_INDEX_FUNCTION);
- sb.append(ELNodeConstants.LEFT_BRACKET);
- sb.append(visitor.getLastIndexValue());
- sb.append(ELNodeConstants.COMMA);
- sb.append(suffixValue);
- sb.append(ELNodeConstants.RIGHT_BRACKET);
+
+ sb.append(ELNodeConstants.DOT);
+ sb.append(ELNodeConstants.GET_FUNCTION);
+ sb.append(ELNodeConstants.LEFT_BRACKET);
+ sb.append(suffixValue);
+ sb.append(ELNodeConstants.RIGHT_BRACKET);
+
+ visitor.setVariableType(collectionValueType);
}
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstChoiceTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstChoiceTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstChoiceTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,19 +19,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.ELNodeConstants;
+import org.richfaces.cdk.parser.el.ELParserUtils;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstChoice node.
*
* @author amarkhel
+ *
*/
public class AstChoiceTreeNode extends AbstractTreeNode {
public AstChoiceTreeNode(Node node) {
@@ -39,20 +44,28 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
- sb.append(ELNodeConstants.LEFT_BRACKET);
-
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
//condition ? correctConditionBranch : incorrectConditionBranch
String condition = getChildOutput(0, context, visitor);
String correctConditionBranch = getChildOutput(1, context, visitor);
+ Type correctConditionBranchType = visitor.getVariableType();
String incorrectConditionBranch = getChildOutput(2, context, visitor);
+ Type incorrectConditionBranchType = visitor.getVariableType();
+
+ sb.append(ELNodeConstants.LEFT_BRACKET);
sb.append(condition);
sb.append(ELNodeConstants.QUESTION_SIGN);
sb.append(correctConditionBranch);
sb.append(ELNodeConstants.COLON);
sb.append(incorrectConditionBranch);
-
+
sb.append(ELNodeConstants.RIGHT_BRACKET);
+
+ if (!ELParserUtils.isNullType(correctConditionBranchType)) {
+ visitor.setVariableType(correctConditionBranchType);
+ } else {
+ visitor.setVariableType(incorrectConditionBranchType);
+ }
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstDeferredOrDynamicExpressionTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstDeferredOrDynamicExpressionTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstDeferredOrDynamicExpressionTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,31 +19,36 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
+
import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstDeferredExpression node.
*
* @author amarkhel
+ *
*/
public class AstDeferredOrDynamicExpressionTreeNode extends AbstractTreeNode {
-
- public AstDeferredOrDynamicExpressionTreeNode(Node node) {
+
+ public AstDeferredOrDynamicExpressionTreeNode(Node node) {
super(node);
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
- int numChildren = getNode().jjtGetNumChildren();
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
+ int childrenCount = getChildrenCount();
- for (int i = 0; i < numChildren; i++) {
+ for (int i = 0; i < childrenCount; i++) {
if (visitor.isUseConversionToString()) {
sb.append(ELNodeConstants.CONVERT_TO_STRING_FUNCTION);
sb.append(ELNodeConstants.LEFT_BRACKET);
@@ -55,7 +60,8 @@
if (visitor.isUseConversionToString()) {
sb.append(ELNodeConstants.RIGHT_BRACKET);
- }
+ visitor.setVariableType(String.class);
+ } /* otherwise variableType will be set in child's visit invocation */
}
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstEmptyTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstEmptyTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstEmptyTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,19 +19,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
+
import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstEmpty node.
*
* @author amarkhel
+ *
*/
public class AstEmptyTreeNode extends AbstractTreeNode {
public AstEmptyTreeNode(Node node) {
@@ -39,16 +44,17 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
visitor.setUseEmptinessCheck(true);
-
- StringBuilder sb1 = new StringBuilder();
- ITreeNode treeNode = getChild(0);
-
- treeNode.visit(sb1, context, visitor);
+
sb.append(ELNodeConstants.THIS_GET_UTILS_IS_EMPTY_FUNCTION);
sb.append(ELNodeConstants.LEFT_BRACKET);
- sb.append(sb1);
+
+ String childOutput = getChildOutput(0, context, visitor);
+ sb.append(childOutput);
+
sb.append(ELNodeConstants.RIGHT_BRACKET);
+
+ visitor.setVariableType(Boolean.TYPE);
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstFloatingPointTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstFloatingPointTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstFloatingPointTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,19 +19,23 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstFloatingPoint node.
*
* @author amarkhel
+ *
*/
public class AstFloatingPointTreeNode extends AbstractTreeNode {
public AstFloatingPointTreeNode(Node node) {
@@ -39,10 +43,12 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
sb.append(ELNodeConstants.DOUBLE_VALUE_OF_FUNCTION);
sb.append(ELNodeConstants.LEFT_BRACKET);
sb.append(getNode().getImage());
sb.append(ELNodeConstants.RIGHT_BRACKET);
+
+ visitor.setVariableType(Double.TYPE);
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstFunctionTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstFunctionTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstFunctionTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,20 +19,25 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.AstFunction;
import org.jboss.el.parser.Node;
+
import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstFunction node.
*
* @author amarkhel
+ *
*/
public class AstFunctionTreeNode extends AbstractTreeNode {
public AstFunctionTreeNode(Node node) {
@@ -40,27 +45,32 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
- String functionName = ((AstFunction) getNode()).getOutputName();
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
+ AstFunction functionNode = (AstFunction) getNode();
+ String functionPrefix = functionNode.getPrefix();
+ String functionName = functionNode.getLocalName();
- sb.append(ELNodeConstants.THIS_PREFIX);
- sb.append(ELNodeConstants.DOT);
- sb.append(functionName.substring(1));
+ if (functionPrefix != null && functionPrefix.length() != 0) {
+ //TODO: this should be a property getter, not property name
+ //TODO: support "super" keyword
+ sb.append(functionPrefix);
+ } else {
+ sb.append(ELNodeConstants.THIS_PREFIX);
+ }
+ sb.append(ELNodeConstants.DOT);
+
+ sb.append(functionName);
sb.append(ELNodeConstants.LEFT_BRACKET);
- int numChildren = getNode().jjtGetNumChildren();
+ int childrenCount = getChildrenCount();
- for (int i = 0; i < numChildren; i++) {
- ITreeNode childNode = getChild(i);
- StringBuilder sb1 = new StringBuilder();
-
- childNode.visit(sb1, context, visitor);
-
+ for (int i = 0; i < childrenCount; i++) {
if (i != 0) {
sb.append(ELNodeConstants.COMMA);
}
- sb.append(sb1);
+ String childOutput = getChildOutput(i, context, visitor);
+ sb.append(childOutput);
}
sb.append(ELNodeConstants.RIGHT_BRACKET);
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstIdentifierTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstIdentifierTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstIdentifierTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,45 +19,39 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
-import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstIdentifier node.
*
* @author amarkhel
+ *
*/
public class AstIdentifierTreeNode extends AbstractTreeNode {
- public AstIdentifierTreeNode(Node node) {
- super(node);
- }
+ public AstIdentifierTreeNode(Node node) {
+ super(node);
+ }
- @Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
- String variableName = getNode().getImage();
+ @Override
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor visitor)
throws ParsingException {
+ String variableName = getNode().getImage();
- if (context.containsKey(variableName)) {
- visitor.setLastVariableType(context.get(variableName));
- sb.append(variableName);
- } else {
- //TODO - what's then?
- if (variableName.equals(ELNodeConstants.THIS_PREFIX)) {
- sb.append(variableName);
- } else if (variableName.equals(ELNodeConstants.UTILS_PREFIX)) {
- sb.append(ELNodeConstants.THIS_PREFIX);
- sb.append(ELNodeConstants.DOT);
- sb.append(ELNodeConstants.GET_UTILS_FUNCTION);
- sb.append(ELNodeConstants.LEFT_BRACKET);
- sb.append(ELNodeConstants.RIGHT_BRACKET);
- } else {
-// throw new ParsingException("No instance found in context for identifier "
+ variableName);
- }
- }
- }
+ Type variableType = context.get(variableName);
+ if (variableType == null) {
+ throw new ParsingException("No instance found in context for identifier " +
variableName);
+ }
+
+ //TODO: implement variable mapper like "utils" ->
"this.getUtils()"
+ visitor.setVariableType(variableType);
+ sb.append(variableName);
+ }
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstIntegerTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstIntegerTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstIntegerTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,18 +19,23 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
+
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstInteger node.
*
* @author amarkhel
+ *
*/
public class AstIntegerTreeNode extends AbstractTreeNode {
public AstIntegerTreeNode(Node node) {
@@ -38,7 +43,8 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
sb.append(getNode().getImage());
+ visitor.setVariableType(Integer.TYPE);
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstLiteralTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstLiteralTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstLiteralTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,20 +19,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
import org.richfaces.cdk.parser.el.StringUtils;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstLiteral node.
*
* @author amarkhel
+ *
*/
public class AstLiteralTreeNode extends AbstractTreeNode {
public AstLiteralTreeNode(Node node) {
@@ -40,11 +44,13 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
if (getNode().getImage() != null) {
sb.append(ELNodeConstants.QUOTE);
sb.append(StringUtils.getEscapedString(getNode().getImage()));
sb.append(ELNodeConstants.QUOTE);
+
+ visitor.setVariableType(String.class);
}
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstMethodSuffixTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstMethodSuffixTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstMethodSuffixTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,50 +19,64 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.ELNodeConstants;
+import org.richfaces.cdk.parser.el.ELParserUtils;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstMethodSuffix node.
*
* @author amarkhel
+ *
*/
public class AstMethodSuffixTreeNode extends AbstractTreeNode {
- public AstMethodSuffixTreeNode(Node node) {
+
+ private static final Type[] EMPTY_TYPES_ARRAY = new Type[0];
+
+ public AstMethodSuffixTreeNode(Node node) {
super(node);
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
- StringBuilder sb1 = new StringBuilder();
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
+ String methodName = getNode().getImage();
+
+ Class<?> objectClass =
ELParserUtils.getRawType(visitor.getVariableType());
+ List<Type> argumentTypes = new ArrayList<Type>();
+
+ sb.append(ELNodeConstants.DOT);
+ sb.append(methodName);
+ sb.append(ELNodeConstants.LEFT_BRACKET);
- sb1.append(getNode().getImage());
- sb1.append(ELNodeConstants.LEFT_BRACKET);
+ int childrenCount = getChildrenCount();
- int numChildren = getNode().jjtGetNumChildren();
-
- for (int k = 0; k < numChildren; k++) {
- StringBuilder sb2 = new StringBuilder();
- ITreeNode treeNode = getChild(k);
-
- treeNode.visit(sb2, context, visitor);
- sb1.append(sb2);
-
- if (k == numChildren - 1) {
-
- // Do nothing. Last argument.
- } else {
- sb1.append(ELNodeConstants.COMMA);
+ for (int k = 0; k < childrenCount; k++) {
+ if (k != 0) {
+ sb.append(ELNodeConstants.COMMA);
}
+ String childOutput = getChildOutput(k, context, visitor);
+ sb.append(childOutput);
+
+ //TODO: handle generic matches -?
+ argumentTypes.add(visitor.getVariableType());
}
- sb1.append(ELNodeConstants.RIGHT_BRACKET);
- sb.append(sb1);
+ sb.append(ELNodeConstants.RIGHT_BRACKET);
+
+ Type returnType = ELParserUtils.getMatchingVisibleMethodReturnType(objectClass,
methodName,
+ argumentTypes.toArray(EMPTY_TYPES_ARRAY));
+
+ visitor.setVariableType(returnType);
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstNegativeTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstNegativeTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstNegativeTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,19 +19,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
+
import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstNegative node.
*
* @author amarkhel
+ *
*/
public class AstNegativeTreeNode extends AbstractTreeNode {
public AstNegativeTreeNode(Node node) {
@@ -39,12 +44,12 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
- ITreeNode node = getChild(0);
- StringBuilder sb1 = new StringBuilder();
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
+ sb.append(ELNodeConstants.NEGATIVE);
- sb.append(ELNodeConstants.NEGATIVE);
- node.visit(sb1, context, visitor);
- sb.append(sb1);
+ String childOutput = getChildOutput(0, context, visitor);
+ sb.append(childOutput);
+
+ //variable type has been already set by getChildOuput()
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstNotTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstNotTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstNotTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,19 +19,23 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstNot node.
*
* @author amarkhel
+ *
*/
public class AstNotTreeNode extends AbstractTreeNode {
public AstNotTreeNode(Node node) {
@@ -39,14 +43,14 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
- StringBuilder sb1 = new StringBuilder();
- ITreeNode node1 = getChild(0);
-
- node1.visit(sb1, context, visitor);
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
sb.append(ELNodeConstants.LEFT_BRACKET);
sb.append(ELNodeConstants.EXCLAMATION_MARK);
- sb.append(sb1);
+ String childOutput = getChildOutput(0, context, visitor);
+ sb.append(childOutput);
sb.append(ELNodeConstants.RIGHT_BRACKET);
+
+ //variable type has been already set by getChildOuput()
}
+
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstPropertySuffixTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstPropertySuffixTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstPropertySuffixTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,39 +19,76 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.ELNodeConstants;
-import org.richfaces.cdk.parser.el.ELReflectionUtils;
+import org.richfaces.cdk.parser.el.ELParserUtils;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstPropertySuffix node.
*
* @author amarkhel
+ *
*/
public class AstPropertySuffixTreeNode extends AbstractTreeNode {
- public AstPropertySuffixTreeNode(Node node) {
+
+ public AstPropertySuffixTreeNode(Node node) {
super(node);
}
+ private final String capitalize(String propertyName) {
+ char[] chars = propertyName.toCharArray();
+ chars[0] = Character.toUpperCase(chars[0]);
+ return new String(chars);
+ }
+
+ private final Method getReadMethod(Class<?> clazz, String propertyName) throws
ParsingException {
+ if (clazz == null) {
+ return null;
+ }
+
+ PropertyDescriptor propertyDescriptor =
ELParserUtils.getPropertyDescriptor(clazz, propertyName);
+ if (propertyDescriptor == null) {
+ return null;
+ }
+
+ return propertyDescriptor.getReadMethod();
+ }
+
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
String propertyName = getNode().getImage();
- if (visitor.getLastVariableType() != null) {
- StringBuilder sb1 = new StringBuilder();
-
- sb1.append(ELReflectionUtils.getReadMethodName(propertyName, visitor));
- sb1.append(ELNodeConstants.LEFT_BRACKET);
- sb1.append(ELNodeConstants.RIGHT_BRACKET);
- sb.append(sb1);
+ Type variableType = visitor.getVariableType();
+ Class<?> clazz = ELParserUtils.getRawType(variableType);
+
+ String readMethodName;
+ Type readMethodReturnType;
+
+ Method readMethod = getReadMethod(clazz, propertyName);
+ if (readMethod != null) {
+ readMethodName = readMethod.getName();
+ readMethodReturnType = readMethod.getGenericReturnType();
} else {
- throw new ParsingException("Property not found: " + propertyName);
+ readMethodName = ELNodeConstants.GETTER_PREFIX + capitalize(propertyName);
+ readMethodReturnType = Object.class;
}
+
+ visitor.setVariableType(readMethodReturnType);
+
+ sb.append(ELNodeConstants.DOT);
+ sb.append(readMethodName);
+ sb.append(ELNodeConstants.LEFT_BRACKET);
+ sb.append(ELNodeConstants.RIGHT_BRACKET);
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstStringTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstStringTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstStringTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,8 +19,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.AstString;
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.ELNodeConstants;
@@ -28,12 +33,11 @@
import org.richfaces.cdk.parser.el.ParsingException;
import org.richfaces.cdk.parser.el.StringUtils;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstString node.
*
* @author amarkhel
+ *
*/
public class AstStringTreeNode extends AbstractTreeNode {
public AstStringTreeNode(Node node) {
@@ -41,9 +45,11 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
sb.append(ELNodeConstants.QUOTE);
sb.append(StringUtils.getEscapedString(((AstString) getNode()).getString()));
sb.append(ELNodeConstants.QUOTE);
+
+ visitor.setVariableType(String.class);
}
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstValueTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstValueTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/AstValueTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -19,21 +19,22 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
+
+
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
-import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
/**
* This class extend AbstractTreeNode and wrap AstValue node.
*
* @author amarkhel
+ *
*/
public class AstValueTreeNode extends AbstractTreeNode {
public AstValueTreeNode(Node node) {
@@ -41,33 +42,13 @@
}
@Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
ELVisitor visitor) throws ParsingException {
- List<String> tokens = new ArrayList<String>();
-
- for (int i = 0; i < getNode().jjtGetNumChildren(); i++) {
- StringBuilder sb1 = new StringBuilder();
- ITreeNode subChild = getChild(i);
-
- subChild.visit(sb1, context, visitor);
- tokens.add(sb1.toString());
+ public void visit(StringBuilder sb, Map<String, Type> context, ELVisitor
visitor) throws ParsingException {
+ int childrenCount = getChildrenCount();
+ for (int i = 0; i < childrenCount; i++) {
+ String childOutput = getChildOutput(i, context, visitor);
+ sb.append(childOutput);
}
- if (tokens.size() != 0) {
- StringBuilder sb2 = new StringBuilder();
-
- for (String element : tokens) {
- if (sb2.length() != 0 &&
!element.startsWith(ELNodeConstants.LEFT_SQUARE_BRACKET)) {
- sb2.append(ELNodeConstants.DOT);
- }
-
- sb2.append(element);
- }
-
- sb.append(sb2);
- } else {
- sb.append(visitor.getLastIndexValue());
- }
-
- visitor.reset();
+ //variable type has been already set by getChildOuput()
}
}
Added:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryArithmeticIntegerOperationTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryArithmeticIntegerOperationTreeNode.java
(rev 0)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryArithmeticIntegerOperationTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.cdk.parser.el.node;
+
+import java.lang.reflect.Type;
+
+import org.jboss.el.parser.Node;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public class BinaryArithmeticIntegerOperationTreeNode extends
AbstractBinaryOperationTreeNode {
+
+ /**
+ * @param node
+ * @param operatorString
+ */
+ public BinaryArithmeticIntegerOperationTreeNode(Node node, String operatorString) {
+ super(node, operatorString);
+ }
+
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.parser.el.node.AbstractBinaryOperationTreeNode#getOperationType(java.lang.reflect.Type,
java.lang.reflect.Type)
+ */
+ @Override
+ protected Type getOperationType(Type firstArgumentType,
+ Type secondArgumentType) {
+ return Integer.TYPE;
+ }
+
+}
Added:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryArithmeticOperationTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryArithmeticOperationTreeNode.java
(rev 0)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryArithmeticOperationTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -0,0 +1,59 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.cdk.parser.el.node;
+
+import java.lang.reflect.Type;
+
+import org.jboss.el.parser.Node;
+import org.richfaces.cdk.parser.el.ELParserUtils;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public class BinaryArithmeticOperationTreeNode extends AbstractBinaryOperationTreeNode {
+
+ /**
+ * @param node
+ * @param operatorString
+ */
+ public BinaryArithmeticOperationTreeNode(Node node, String operatorString) {
+ super(node, operatorString);
+ }
+
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.parser.el.node.AbstractBinaryOperationTreeNode#getOperationType(java.lang.reflect.Type,
java.lang.reflect.Type)
+ */
+ @Override
+ protected Type getOperationType(Type firstArgumentType,
+ Type secondArgumentType) {
+
+ if (ELParserUtils.isAssignmentCompatible(firstArgumentType, Double.class) ||
+ ELParserUtils.isAssignmentCompatible(secondArgumentType, Double.class)) {
+
+ return Double.TYPE;
+ }
+
+ return Integer.TYPE;
+ }
+
+}
Added:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryBooleanOperationTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryBooleanOperationTreeNode.java
(rev 0)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryBooleanOperationTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.cdk.parser.el.node;
+
+import java.lang.reflect.Type;
+
+import org.jboss.el.parser.Node;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public class BinaryBooleanOperationTreeNode extends AbstractBinaryOperationTreeNode {
+
+ /**
+ * @param node
+ * @param operatorString
+ */
+ public BinaryBooleanOperationTreeNode(Node node, String operatorString) {
+ super(node, operatorString);
+ }
+
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.parser.el.node.AbstractBinaryOperationTreeNode#getOperationType(java.lang.reflect.Type,
java.lang.reflect.Type)
+ */
+ @Override
+ protected Type getOperationType(Type firstArgumentType,
+ Type secondArgumentType) {
+ return Boolean.TYPE;
+ }
+
+}
Deleted:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryOperationTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryOperationTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/BinaryOperationTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -1,67 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, Red Hat, Inc. and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
- */
-package org.richfaces.cdk.parser.el.node;
-
-import org.jboss.el.parser.Node;
-import org.richfaces.cdk.parser.el.ELNodeConstants;
-import org.richfaces.cdk.parser.el.ELVisitor;
-import org.richfaces.cdk.parser.el.ParsingException;
-
-import java.util.Map;
-
-/**
- * <p>Abstract class for all binary (having two operands) operation expression
nodes</p>
- * <p>For operands <code>A</code> and <code>B</code> and
operator <code>x</code> output is <code>(A x B)</code></p>
- *
- * @author Nick Belaevski
- */
-public class BinaryOperationTreeNode extends AbstractTreeNode {
-
- private final String operatorString;
-
- public BinaryOperationTreeNode(Node node, String operatorString) {
- super(node);
-
- this.operatorString = operatorString;
- }
-
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.parser.el.node.AbstractTreeNode#visit(java.lang.StringBuilder,
java.util.Map, org.richfaces.cdk.parser.el.ELVisitor)
- */
- @Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
- ELVisitor visitor) throws ParsingException {
-
- sb.append(ELNodeConstants.LEFT_BRACKET);
-
- String firstChildOutput = getChildOutput(0, context, visitor);
- String secondChildOutput = getChildOutput(1, context, visitor);
-
- sb.append(firstChildOutput);
- sb.append(operatorString);
- sb.append(secondChildOutput);
-
- sb.append(ELNodeConstants.RIGHT_BRACKET);
-
- }
-
-}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/ConstantValueTreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/ConstantValueTreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/ConstantValueTreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -21,39 +21,47 @@
*/
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.richfaces.cdk.parser.el.ELNodeConstants;
import org.richfaces.cdk.parser.el.ELVisitor;
+import org.richfaces.cdk.parser.el.NullType;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* @author Nick Belaevski
+ *
*/
-public final class ConstantValueTreeNode extends AbstractTreeNode {
+public class ConstantValueTreeNode extends AbstractTreeNode {
- public static final ConstantValueTreeNode NULL_NODE = new
ConstantValueTreeNode(ELNodeConstants.NULL_VALUE);
+ private final String value;
- public static final ConstantValueTreeNode TRUE_NODE = new
ConstantValueTreeNode(ELNodeConstants.TRUE_VALUE);
+ private final Type type;
+
+ //XXX what class to use for null object: Void.class or null - null will be used
+ public static final ConstantValueTreeNode NULL_NODE = new
ConstantValueTreeNode(ELNodeConstants.NULL_VALUE, NullType.INSTANCE);
+
+ public static final ConstantValueTreeNode TRUE_NODE = new
ConstantValueTreeNode(ELNodeConstants.TRUE_VALUE, Boolean.TYPE);
+
+ public static final ConstantValueTreeNode FALSE_NODE = new
ConstantValueTreeNode(ELNodeConstants.FALSE_VALUE, Boolean.TYPE);
- public static final ConstantValueTreeNode FALSE_NODE = new
ConstantValueTreeNode(ELNodeConstants.FALSE_VALUE);
+ private ConstantValueTreeNode(String value, Type type) {
+ super(null);
+
+ this.value = value;
+ this.type = type;
+ }
- private final String value;
+ /* (non-Javadoc)
+ * @see org.richfaces.cdk.parser.el.node.AbstractTreeNode#visit(java.lang.StringBuilder,
java.util.Map, org.richfaces.cdk.parser.el.ELVisitor)
+ */
+ @Override
+ public void visit(StringBuilder sb, Map<String, Type> context,
+ ELVisitor visitor) throws ParsingException {
- private ConstantValueTreeNode(String value) {
- super(null);
- this.value = value;
- }
-
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.parser.el.node.AbstractTreeNode#visit(java.lang.StringBuilder,
java.util.Map,
- * org.richfaces.cdk.parser.el.ELVisitor)
- */
- @Override
- public void visit(StringBuilder sb, Map<String, Class<?>> context,
- ELVisitor visitor) throws ParsingException {
-
- sb.append(value);
- }
-
+ sb.append(value);
+ visitor.setVariableType(type);
+ }
+
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/ITreeNode.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/ITreeNode.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/parser/el/node/ITreeNode.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -21,12 +21,13 @@
package org.richfaces.cdk.parser.el.node;
+import java.lang.reflect.Type;
+import java.util.Map;
+
import org.jboss.el.parser.Node;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
-import java.util.Map;
-
/**
* Interface for all wrappers of org.jboss.el.parser.Node class.
*
@@ -50,7 +51,7 @@
* @return instance of org.jboss.el.parser.Node
* @throws ParsingException - if error occurred during parsing process.
*/
- void visit(StringBuilder sb, Map<String, Class<?>> context, ELVisitor
visitor) throws ParsingException;
+ void visit(StringBuilder sb, Map<String, Type> context, ELVisitor visitor)
throws ParsingException;
/**
* Return child of wrapped node by specified index
@@ -60,4 +61,11 @@
* @throws ParsingException - if error occurred(child not found).
*/
ITreeNode getChild(int index) throws ParsingException;
+
+ /**
+ * Returns count of children for this node
+ * @return children count
+ */
+ int getChildrenCount();
+
}
Modified:
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/templatecompiler/RendererClassVisitor.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/templatecompiler/RendererClassVisitor.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/java/org/richfaces/cdk/templatecompiler/RendererClassVisitor.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -23,7 +23,27 @@
package org.richfaces.cdk.templatecompiler;
-import com.google.common.collect.Lists;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.annotation.Generated;
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.Behavior;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.convert.Converter;
+import javax.faces.render.Renderer;
+import javax.xml.namespace.QName;
+
import org.richfaces.builder.model.Argument;
import org.richfaces.builder.model.JavaClass;
import org.richfaces.builder.model.JavaMethod;
@@ -47,97 +67,82 @@
import org.richfaces.cdk.templatecompiler.model.Template;
import org.richfaces.cdk.templatecompiler.model.TemplateVisitor;
-import javax.annotation.Generated;
-import javax.faces.component.UIComponent;
-import javax.faces.component.behavior.Behavior;
-import javax.faces.context.FacesContext;
-import javax.faces.context.ResponseWriter;
-import javax.faces.convert.Converter;
-import javax.xml.namespace.QName;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.ObjectInputStream;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
+import com.google.common.collect.Lists;
/**
* <p class="changed_added_4_0"></p>
- *
* @author asmirnov(a)exadel.com
+ *
*/
public class RendererClassVisitor implements TemplateVisitor {
- /**
- *
- */
- static final String RESPONSE_WRITER_VARIABLE = "responseWriter";
- /**
- *
- */
- static final String COMPONENT_VARIABLE = "cc";
- /**
- *
- */
- static final String FACES_CONTEXT_VARIABLE = "facesContext";
- /**
- *
- */
- static final String CLIENT_ID_VARIABLE = "clientId";
- /**
- *
- */
- static final String RENDERER_UTILS_VARIABLE = "utils";
+ /**
+ *
+ */
+ static final String RESPONSE_WRITER_VARIABLE = "responseWriter";
+ /**
+ *
+ */
+ static final String COMPONENT_VARIABLE = "cc";
+ /**
+ *
+ */
+ static final String THIS_VARIABLE = "this";
+ /**
+ *
+ */
+ static final String FACES_CONTEXT_VARIABLE = "facesContext";
+ /**
+ *
+ */
+ static final String CLIENT_ID_VARIABLE = "clientId";
+ /**
+ *
+ */
+ static final String RENDERER_UTILS_VARIABLE = "utils";
+
+ static final String RENDERER_UTILS_CLASS_NAME =
"org.ajax4jsf.renderkit.RendererUtils";
+
+ private static final Set<String> DEFAULT_NAMESPACES = new
HashSet<String>();
+
+ static {
+
DEFAULT_NAMESPACES.add("http://richfaces.org/xhtml-el");
+
DEFAULT_NAMESPACES.add("http://www.w3.org/1999/xhtml");
+ }
- static final String RENDERER_UTILS_CLASS_NAME =
"org.ajax4jsf.renderkit.RendererUtils";
-
- private static final Set<String> DEFAULT_NAMESPACES = new
HashSet<String>();
-
- static {
-
DEFAULT_NAMESPACES.add("http://richfaces.org/xhtml-el");
-
DEFAULT_NAMESPACES.add("http://www.w3.org/1999/xhtml");
- }
-
- private static final String[] GUESS_PACKAGES;
-
- static {
- Class<?>[] guessPackagesClasses = {
- UIComponent.class,
- Behavior.class,
- Converter.class,
- FacesContext.class,
- Collection.class,
- Object.class,
- };
-
- GUESS_PACKAGES = new String[guessPackagesClasses.length];
- int i = 0;
- for (Class<?> guessPackageClass : guessPackagesClasses) {
- GUESS_PACKAGES[i++] = guessPackageClass.getPackage().getName();
- }
- }
-
+ private static final String[] GUESS_PACKAGES;
+
+ static {
+ Class<?>[] GUESS_PACKAGES_CLASSES = {
+ UIComponent.class,
+ Behavior.class,
+ Converter.class,
+ FacesContext.class,
+ Collection.class,
+ Object.class
+ };
+
+ GUESS_PACKAGES = new String[GUESS_PACKAGES_CLASSES.length];
+ int i = 0;
+ for (Class<?> guessPackageClass : GUESS_PACKAGES_CLASSES) {
+ GUESS_PACKAGES[i++] = guessPackageClass.getPackage().getName();
+ }
+ }
+
private static final Map<String, Set<String>> ELEMENTS_ATTRIBUTES;
-
- protected MethodBodyStatementsContainer currentStatement;
-
private JavaClass rendererClass;
private CompositeInterface compositeInterface;
+ protected MethodBodyStatementsContainer currentStatement;
private final LinkedList<MethodBodyStatementsContainer> statements =
Lists.newLinkedList();
- private Map<String, Class<?>> localsTypesMap;
- private ClassLoader classLoader;
- private boolean isAddedMethodForConversionToString;
- private boolean isAddedMethodForCheckingEmptiness;
-
+ private Map<String, Type> localsTypesMap;
+ private ClassLoader classLoader;
+ private boolean isAddedMethodForConversionToString;
+ private boolean isAddedMethodForCheckingEmptiness;
+
static {
- InputStream serializedAttributesStream =
-
RendererClassVisitor.class.getResourceAsStream("/META-INF/schema/attributes.ser");
+ InputStream serializedAttributesStream =
RendererClassVisitor.class.getResourceAsStream("/META-INF/schema/attributes.ser");
try {
@@ -158,84 +163,80 @@
}
}
}
-
- public RendererClassVisitor(CompositeInterface compositeInterface, ClassLoader
classLoader) {
- this.compositeInterface = compositeInterface;
- this.classLoader = classLoader;
- }
-
- private void initializeJavaClass() {
- this.rendererClass = createJavaClassByName(compositeInterface.getJavaClass());
- this.rendererClass.addModifier(JavaModifier.PUBLIC);
+
+ private void initializeJavaClass() {
+ this.rendererClass = createJavaClassByName(compositeInterface.getJavaClass());
+ this.rendererClass.addModifier(JavaModifier.PUBLIC);
this.rendererClass.setSuperClass(createJavaClassByName(compositeInterface.getBaseClass()));
this.rendererClass.addImport(FacesContext.class);
- this.rendererClass.addImport(ResponseWriter.class);
+ this.rendererClass.addImport(ResponseWriter.class);
this.rendererClass.addImport(UIComponent.class);
- this.rendererClass.addImport(RENDERER_UTILS_CLASS_NAME);
+ this.rendererClass.addImport(RENDERER_UTILS_CLASS_NAME);
- this.rendererClass.addAnnotation(Generated.class, "\"RichFaces
CDK\"");
- //TODO remove this after improving Java model
- this.rendererClass.addImport(Generated.class);
-
+ this.rendererClass.addAnnotation(Generated.class, "\"RichFaces
CDK\"");
+ //TODO remove this after improving Java model
+ this.rendererClass.addImport(Generated.class);
+
this.createMethodContext();
- }
+ }
private void addMethodForConversionToString() {
- if (!isAddedMethodForConversionToString) {
- isAddedMethodForConversionToString = true;
+ if (!isAddedMethodForConversionToString) {
+ isAddedMethodForConversionToString = true;
+
+ JavaMethod conversionMethod = new JavaMethod("convertToString",
String.class,
+ new Argument("object", Object.class));
+
+ conversionMethod.addModifier(JavaModifier.PRIVATE);
+ conversionMethod.addModifier(JavaModifier.FINAL);
- JavaMethod conversionMethod = new JavaMethod("convertToString",
String.class,
- new Argument("object", Object.class));
-
- conversionMethod.addModifier(JavaModifier.PRIVATE);
- conversionMethod.addModifier(JavaModifier.FINAL);
-
- MethodBody conversionMethodBody = new MethodBody(conversionMethod);
- conversionMethod.setMethodBody(conversionMethodBody);
- conversionMethodBody.addStatement(new
ConversionToStringMethodBodyStatement());
-
- rendererClass.addMethod(conversionMethod);
- }
+ MethodBody conversionMethodBody = new MethodBody(conversionMethod);
+ conversionMethod.setMethodBody(conversionMethodBody);
+ conversionMethodBody.addStatement(new ConversionToStringMethodBodyStatement());
+
+ rendererClass.addMethod(conversionMethod);
+ }
}
private void addMethodForCheckingEmptiness() {
- if (!isAddedMethodForCheckingEmptiness) {
- isAddedMethodForCheckingEmptiness = true;
+ if (!isAddedMethodForCheckingEmptiness) {
+ isAddedMethodForCheckingEmptiness = true;
- JavaMethod checkingMethod = new JavaMethod("isEmpty",
boolean.class,
- new Argument("object", Object.class));
+ JavaMethod checkingMethod = new JavaMethod("isEmpty", boolean.class,
+ new Argument("object", Object.class));
+
+ checkingMethod.addModifier(JavaModifier.PRIVATE);
+ checkingMethod.addModifier(JavaModifier.FINAL);
- checkingMethod.addModifier(JavaModifier.PRIVATE);
- checkingMethod.addModifier(JavaModifier.FINAL);
-
- MethodBody checkingMethodBody = new MethodBody(checkingMethod);
- checkingMethod.setMethodBody(checkingMethodBody);
- checkingMethodBody.addStatement(new EmptinessCheckingMethodBodyStatement());
-
- rendererClass.addMethod(checkingMethod);
- }
+ MethodBody checkingMethodBody = new MethodBody(checkingMethod);
+ checkingMethod.setMethodBody(checkingMethodBody);
+ checkingMethodBody.addStatement(new EmptinessCheckingMethodBodyStatement());
+
+ rendererClass.addMethod(checkingMethod);
+ }
}
-
+
private String compileEl(String expression, Class<?> type) {
- try {
- ELVisitor elVisitor = ELVisitor.getInstance();
- String parsedExpression = elVisitor.parse(expression, localsTypesMap);
-
- if (elVisitor.isUseConversionToString()) {
- addMethodForConversionToString();
- }
-
- if (elVisitor.isUseEmptinessCheck()) {
- addMethodForCheckingEmptiness();
- }
-
- return parsedExpression + "/* " + expression.trim() + "
*/";
- } catch (ParsingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- throw new RuntimeException(e.getMessage());
- }
+ try {
+ ELVisitor elVisitor = new ELVisitor();
+ elVisitor.parse(expression, localsTypesMap);
+ String parsedExpression = elVisitor.getParsedExpression();
+
+ if (elVisitor.isUseConversionToString()) {
+ addMethodForConversionToString();
+ }
+
+ if (elVisitor.isUseEmptinessCheck()) {
+ addMethodForCheckingEmptiness();
+ }
+
+ return parsedExpression + "/* " + expression.trim() + " */";
+ } catch (ParsingException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ throw new RuntimeException(e.getMessage());
+ }
//
// if (Boolean.class.isAssignableFrom(type)) {
// //TODO just a stub!
@@ -244,59 +245,63 @@
//
// return quote(expression) + " /* " + expression.trim() + "
*/";
}
+
+ private String getElExpressionContainerType(String value) {
+ // TODO Auto-generated method stub
+ return Object.class.getName();
+ }
- private String getElExpressionContainerType(String value) {
- // TODO Auto-generated method stub
- return Object.class.getName();
- }
-
- private String getElExpressionType(String value) {
- // TODO Auto-generated method stub
- return String.class.getName();
- }
-
+ private String getElExpressionType(String value) {
+ // TODO Auto-generated method stub
+ return String.class.getName();
+ }
+
private boolean isDefaultNamespace(String namespaceURI) {
- //TODO - another namespaces
- if (namespaceURI == null || namespaceURI.length() == 0) {
- return true;
- }
-
- if (DEFAULT_NAMESPACES.contains(namespaceURI)) {
- return true;
- }
-
- return false;
+ //TODO - another namespaces
+ if (namespaceURI == null || namespaceURI.length() == 0) {
+ return true;
+ }
+
+ if (DEFAULT_NAMESPACES.contains(namespaceURI)) {
+ return true;
+ }
+
+ return false;
}
private void createMethodContext() {
- this.currentStatement = new MethodBody();
- this.localsTypesMap = new HashMap<String, Class<?>>();
- localsTypesMap.put(FACES_CONTEXT_VARIABLE, FacesContext.class);
- localsTypesMap.put(RESPONSE_WRITER_VARIABLE, ResponseWriter.class);
- localsTypesMap.put(COMPONENT_VARIABLE, UIComponent.class);
- localsTypesMap.put(CLIENT_ID_VARIABLE, String.class);
+ this.currentStatement = new MethodBody();
+ this.localsTypesMap = new HashMap<String, Type>();
+ localsTypesMap.put(FACES_CONTEXT_VARIABLE, FacesContext.class);
+ localsTypesMap.put(RESPONSE_WRITER_VARIABLE, ResponseWriter.class);
+ localsTypesMap.put(CLIENT_ID_VARIABLE, String.class);
+
+ //TODO: try load component class
+ localsTypesMap.put(COMPONENT_VARIABLE, UIComponent.class);
+ //TODO: try load renderer class
+ localsTypesMap.put(THIS_VARIABLE, Renderer.class);
}
-
+
private void flushToEncodeMethod(String encodeMethodName) {
- if (!this.currentStatement.isEmpty()) {
- Argument facesContextArgument = new Argument(FACES_CONTEXT_VARIABLE,
FacesContext.class);
- Argument componentArgument = new Argument(COMPONENT_VARIABLE,
UIComponent.class);
+ if (!this.currentStatement.isEmpty()) {
+ Argument facesContextArgument = new Argument(FACES_CONTEXT_VARIABLE,
FacesContext.class);
+ Argument componentArgument = new Argument(COMPONENT_VARIABLE,
UIComponent.class);
+
+ JavaMethod javaMethod = new JavaMethod(encodeMethodName, facesContextArgument,
componentArgument);
+ javaMethod.addModifier(JavaModifier.PUBLIC);
+ javaMethod.addAnnotation(Override.class);
+ javaMethod.getExceptions().add(IOException.class);
+
+ MethodBody methodBody = (MethodBody) currentStatement;
+ javaMethod.setMethodBody(methodBody);
+
+ methodBody.addStatement(0, new EncodeMethodPrefaceStatement());
+ rendererClass.addMethod(javaMethod);
+ }
- JavaMethod javaMethod = new JavaMethod(encodeMethodName,
facesContextArgument, componentArgument);
- javaMethod.addModifier(JavaModifier.PUBLIC);
- javaMethod.addAnnotation(Override.class);
- javaMethod.getExceptions().add(IOException.class);
-
- MethodBody methodBody = (MethodBody) currentStatement;
- javaMethod.setMethodBody(methodBody);
-
- methodBody.addStatement(0, new EncodeMethodPrefaceStatement());
- rendererClass.addMethod(javaMethod);
- }
-
- createMethodContext();
+ createMethodContext();
}
-
+
private JavaClass createJavaClassByName(String fullName) {
String simpleName = null;
String packageName = "";
@@ -311,142 +316,144 @@
return new JavaClass(simpleName, new JavaPackage(packageName));
}
+
+ //TODO handle arrays and generics
+ private Class<?> getClasByObjectTypeName(String type) {
+ Class<?> result = null;
+
+ int dotIndex = type.indexOf('.');
+ if (dotIndex < 0) {
+ //guess type
+ for (String guessPackage : GUESS_PACKAGES) {
+ try {
+ result = classLoader.loadClass(guessPackage + "." + type);
+ break;
+ } catch (ClassNotFoundException e) {
+ //ignore
+ }
+ }
+ }
+
+ if (result == null) {
+ try {
+ classLoader.loadClass(type);
+ } catch (ClassNotFoundException e) {
+ //ignore
+ }
+ }
- private Class<?> getClasByObjectTypeByName(String type) {
- Class<?> result = null;
+ if (result == null) {
+ result = Object.class;
+ }
- int dotIndex = type.indexOf('.');
- if (dotIndex < 0) {
- //guess type
- for (String guessPackage : GUESS_PACKAGES) {
- try {
- result = classLoader.loadClass(guessPackage + "." + type);
- break;
- } catch (ClassNotFoundException e) {
- //ignore
- }
- }
- }
+ return result;
+ }
- if (result == null) {
- try {
- classLoader.loadClass(type);
- } catch (ClassNotFoundException e) {
- //ignore
- }
- }
+ private void defineObject(String type, String name, String initializationExpression) {
+ currentStatement.addStatement(new DefineObjectStatement(type, name,
initializationExpression));
+ localsTypesMap.put(name, getClasByObjectTypeName(type));
+ }
+
- if (result == null) {
- result = Object.class;
- }
-
- return result;
- }
-
- private void defineObject(String type, String name, String initializationExpression)
{
- currentStatement.addStatement(new DefineObjectStatement(type, name,
initializationExpression));
- localsTypesMap.put(name, getClasByObjectTypeByName(type));
- }
-
protected void pushStatement(MethodBodyStatementsContainer container) {
- currentStatement.addStatement(container);
- statements.push(currentStatement);
- currentStatement = container;
+ currentStatement.addStatement(container);
+ statements.push(currentStatement);
+ currentStatement = container;
}
-
+
protected void popStatement() {
- currentStatement = statements.pop();
+ currentStatement = statements.pop();
}
+ public RendererClassVisitor(CompositeInterface compositeInterface, ClassLoader
classLoader) {
+ this.compositeInterface = compositeInterface;
+ this.classLoader = classLoader;
+ }
+
/**
* <p class="changed_added_4_0"></p>
- *
* @return the rendererClass
*/
public JavaClass getRendererClass() {
return this.rendererClass;
}
-
+
/* (non-Javadoc)
- * @see org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(
- * org.richfaces.cdk.templatecompiler.model.CdkBodyElement)
- */
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler.model.CdkBodyElement)
+ */
@Override
public void startElement(CdkBodyElement cdkBodyElement) throws CdkException {
- flushToEncodeMethod("encodeBegin");
+ flushToEncodeMethod("encodeBegin");
}
/* (non-Javadoc)
- * @see org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(
- * org.richfaces.cdk.templatecompiler.model.CdkBodyElement)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler.model.CdkBodyElement)
*/
@Override
public void endElement(CdkBodyElement cdkBodyElement) throws CdkException {
- flushToEncodeMethod("encodeChildren");
+ flushToEncodeMethod("encodeChildren");
}
/* (non-Javadoc)
- * @see org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(
- * org.richfaces.cdk.templatecompiler.model.AnyElement)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler.model.AnyElement)
*/
@Override
public void startElement(AnyElement anyElement) throws CdkException {
QName elementName = anyElement.getName();
Map<QName, Object> elementAttributes = anyElement.getAttributes();
-
+
if (!isDefaultNamespace(elementName.getNamespaceURI())) {
- //TODO: add support
+ //TODO: add support
}
-
+
currentStatement.addStatement(new
StartElementStatement(elementName.getLocalPart()));
-
+
if (elementAttributes != null) {
for (Map.Entry<QName, Object> attribute : elementAttributes.entrySet())
{
- QName attributeName = attribute.getKey();
- Object attributeValue = attribute.getValue();
-
- if (!isDefaultNamespace(attributeName.getNamespaceURI())) {
- //TODO: add support
-
- //TODO: optimize batch attributes encoding
- if (Template.CDK_NAMESPACE.equals(attributeName.getNamespaceURI())
- &&
"passThroughWithExclusions".equals(attributeName.getLocalPart())) {
-
- //TODO check element namespace
- Set<String> attributeSet =
ELEMENTS_ATTRIBUTES.get(elementName.getLocalPart());
- if (attributeSet != null) {
- //make a copy of original set
- TreeSet<String> actualAttributesSet = new
TreeSet<String>(attributeSet);
-
- if (attributeValue != null) {
- String[] exclusions =
attributeValue.toString().split("\\s+");
- for (String exclusion : exclusions) {
- actualAttributesSet.remove(exclusion);
- }
- }
-
- if (!actualAttributesSet.isEmpty()) {
- currentStatement.addStatement(new
WriteAttributesSetStatement(actualAttributesSet));
- }
- }
- }
-
- //TODO: cdk:passThrough
+ QName attributeName = attribute.getKey();
+ Object attributeValue = attribute.getValue();
+
+ if (!isDefaultNamespace(attributeName.getNamespaceURI())) {
+ //TODO: add support
+
+ //TODO: optimize batch attributes encoding
+ if (Template.CDK_NAMESPACE.equals(attributeName.getNamespaceURI())
&&
+
"passThroughWithExclusions".equals(attributeName.getLocalPart())) {
+
+ //TODO check element namespace
+ Set<String> attributeSet =
ELEMENTS_ATTRIBUTES.get(elementName.getLocalPart());
+ if (attributeSet != null) {
+ //make a copy of original set
+ TreeSet<String> actualAttributesSet = new
TreeSet<String>(attributeSet);
+
+ if (attributeValue != null) {
+ String[] exclusions =
attributeValue.toString().split("\\s+");
+ for (String exclusion : exclusions) {
+ actualAttributesSet.remove(exclusion);
+ }
+ }
+
+ if (!actualAttributesSet.isEmpty()) {
+ currentStatement.addStatement(new
WriteAttributesSetStatement(actualAttributesSet));
+ }
+ }
+ }
+
+ //TODO: cdk:passThrough
} else {
- currentStatement.addStatement(new
WriteAttributeStatement(attributeName.getLocalPart(),
- compileEl(attributeValue.toString(), String.class)));
+ currentStatement.addStatement(new
WriteAttributeStatement(attributeName.getLocalPart(),
+ compileEl(attributeValue.toString(), String.class)));
}
- }
+ }
}
}
/* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler
- * .model.AnyElement)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler.model.AnyElement)
*/
@Override
public void endElement(AnyElement anyElement) throws CdkException {
- QName elementName = anyElement.getName();
+ QName elementName = anyElement.getName();
currentStatement.addStatement(new
EndElementStatement(elementName.getLocalPart()));
}
@@ -455,160 +462,148 @@
*/
@Override
public void visitElement(String text) throws CdkException {
- if (text != null) {
- String trimmedText = text.trim();
- if (trimmedText.length() != 0) {
- currentStatement.addStatement(new
WriteTextStatement(compileEl(trimmedText, String.class)));
- }
- }
+ if (text != null) {
+ String trimmedText = text.trim();
+ if (trimmedText.length() != 0) {
+ currentStatement.addStatement(new WriteTextStatement(compileEl(trimmedText,
String.class)));
+ }
+ }
}
/* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#visitElement(org.richfaces.cdk.templatecompiler
- * .model.CdkCallElement)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#visitElement(org.richfaces.cdk.templatecompiler.model.CdkCallElement)
*/
@Override
public void visitElement(CdkCallElement cdkCallElement) throws CdkException {
- currentStatement.addStatement(cdkCallElement.getExpression() + ";");
+ currentStatement.addStatement(cdkCallElement.getExpression() + ";");
}
/* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler
- * .model.CdkIfElement)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler.model.CdkIfElement)
*/
- @Override
- public void startElement(CdkIfElement cdkIfElement) {
- String compiledTestExpression = compileEl(cdkIfElement.getTest(),
Boolean.class);
+ @Override
+ public void startElement(CdkIfElement cdkIfElement) {
+ String compiledTestExpression = compileEl(cdkIfElement.getTest(), Boolean.class);
+
+ pushStatement(new IfElseStatement());
+ pushStatement(new IfStatement(compiledTestExpression));
+ }
- pushStatement(new IfElseStatement());
- pushStatement(new IfStatement(compiledTestExpression));
- }
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler.model.CdkIfElement)
+ */
+ @Override
+ public void endElement(CdkIfElement cdkIfElement) {
+ popStatement();
+ popStatement();
+ }
+
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler.model.CdkChooseElement)
+ */
+ @Override
+ public void startElement(CdkChooseElement cdkChooseElement) {
+ pushStatement(new IfElseStatement());
+ }
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler
- * .model.CdkIfElement)
- */
- @Override
- public void endElement(CdkIfElement cdkIfElement) {
- popStatement();
- popStatement();
- }
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler.model.CdkChooseElement)
+ */
+ @Override
+ public void endElement(CdkChooseElement cdkChooseElement) {
+ popStatement();
+ }
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler
- * .model.CdkChooseElement)
- */
- @Override
- public void startElement(CdkChooseElement cdkChooseElement) {
- pushStatement(new IfElseStatement());
- }
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler.model.CdkWhenElement)
+ */
+ @Override
+ public void startElement(CdkWhenElement cdkWhenElement) {
+ String compiledTestExpression = compileEl(cdkWhenElement.getTest(), Boolean.class);
+
+ pushStatement(new IfStatement(compiledTestExpression));
+ }
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler
- * .model.CdkChooseElement)
- */
- @Override
- public void endElement(CdkChooseElement cdkChooseElement) {
- popStatement();
- }
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler.model.CdkWhenElement)
+ */
+ @Override
+ public void endElement(CdkWhenElement cdkWhenElement) {
+ popStatement();
+ }
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler
- * .model.CdkWhenElement)
- */
- @Override
- public void startElement(CdkWhenElement cdkWhenElement) {
- String compiledTestExpression = compileEl(cdkWhenElement.getTest(),
Boolean.class);
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler.model.CdkOtherwiseElement)
+ */
+ @Override
+ public void startElement(CdkOtherwiseElement cdkOtherwiseElement) {
+ pushStatement(new IfStatement(""));
+ }
+
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler.model.CdkOtherwiseElement)
+ */
+ @Override
+ public void endElement(CdkOtherwiseElement cdkOtherwiseElement) {
+ popStatement();
+ }
- pushStatement(new IfStatement(compiledTestExpression));
- }
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#visitElement(org.richfaces.cdk.templatecompiler.model.CdkObjectElement)
+ */
+ @Override
+ public void visitElement(CdkObjectElement cdkObjectElement) {
+ String name = cdkObjectElement.getName();
+
+ String value = cdkObjectElement.getValue();
+ if (value == null || value.length() == 0) {
+ value = cdkObjectElement.getBodyValue();
+ }
+
+ String type = cdkObjectElement.getType();
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler
- * .model.CdkWhenElement)
- */
- @Override
- public void endElement(CdkWhenElement cdkWhenElement) {
- popStatement();
- }
+ if (value != null && value.length() != 0) {
+ if (type == null || type.length() == 0) {
+ type = getElExpressionType(value);
+ }
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler
- * .model.CdkOtherwiseElement)
- */
- @Override
- public void startElement(CdkOtherwiseElement cdkOtherwiseElement) {
- pushStatement(new IfStatement(""));
- }
+ value = compileEl(value, Object.class);
+ }
+
+ defineObject(type, name, value);
+ }
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler
- * .model.CdkOtherwiseElement)
- */
- @Override
- public void endElement(CdkOtherwiseElement cdkOtherwiseElement) {
- popStatement();
- }
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler.model.CdkForEachElement)
+ */
+ @Override
+ public void startElement(CdkForEachElement cdkForEachElement) {
+ String items = cdkForEachElement.getItems();
+ String itemsExpression = compileEl(items, Iterable.class);
+ pushStatement(new ForEachStatement(itemsExpression, cdkForEachElement.getVar(),
+ getElExpressionContainerType(items)));
+ }
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#visitElement(org.richfaces.cdk.templatecompiler
- * .model.CdkObjectElement)
- */
- @Override
- public void visitElement(CdkObjectElement cdkObjectElement) {
- String name = cdkObjectElement.getName();
+ /* (non-Javadoc)
+ * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler.model.CdkForEachElement)
+ */
+ @Override
+ public void endElement(CdkForEachElement cdkForEachElement) {
+ popStatement();
+ }
- String value = cdkObjectElement.getValue();
- if (value == null || value.length() == 0) {
- value = cdkObjectElement.getBodyValue();
- }
-
- String type = cdkObjectElement.getType();
-
- if (value != null && value.length() != 0) {
- if (type == null || type.length() == 0) {
- type = getElExpressionType(value);
- }
-
- value = compileEl(value, Object.class);
- }
-
- defineObject(type, name, value);
- }
-
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#startElement(org.richfaces.cdk.templatecompiler
- * .model.CdkForEachElement)
- */
- @Override
- public void startElement(CdkForEachElement cdkForEachElement) {
- String items = cdkForEachElement.getItems();
- String itemsExpression = compileEl(items, Iterable.class);
- pushStatement(new ForEachStatement(itemsExpression, cdkForEachElement.getVar(),
- getElExpressionContainerType(items)));
- }
-
- /* (non-Javadoc)
- * @see
org.richfaces.cdk.templatecompiler.model.TemplateVisitor#endElement(org.richfaces.cdk.templatecompiler
- * .model.CdkForEachElement)
- */
- @Override
- public void endElement(CdkForEachElement cdkForEachElement) {
- popStatement();
- }
-
- /**
- *
- */
- public void preProcess() {
+ /**
+ *
+ */
+ public void preProcess() {
initializeJavaClass();
- }
+ }
- /**
- *
- */
- public void postProcess() {
- flushToEncodeMethod("encodeEnd");
- }
+ /**
+ *
+ */
+ public void postProcess() {
+ flushToEncodeMethod("encodeEnd");
+ }
}
Modified:
root/cdk/trunk/plugins/generator/src/main/resources/META-INF/templates/java/write-text.ftl
===================================================================
---
root/cdk/trunk/plugins/generator/src/main/resources/META-INF/templates/java/write-text.ftl 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/main/resources/META-INF/templates/java/write-text.ftl 2009-12-04
20:55:31 UTC (rev 16075)
@@ -1 +1,6 @@
-${rendererUtilsVariable}.writeText(${responseWriterVariable},
${modelItem.textExpression}, null);
\ No newline at end of file
+{
+ Object text = ${modelItem.textExpression};
+ if (text != null) {
+ ${responseWriterVariable}.writeText(text, null);
+ }
+}
\ No newline at end of file
Modified:
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/Bean.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/Bean.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/Bean.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -32,12 +32,14 @@
private UIComponent[] array = new UIComponent[] {new UIComponent()};
private List<UIComponent> components;
private Map<String, UIComponent> facets;
+ private Map rawMap;
private boolean readOnly;
private Bean2 testBean2;
- public Bean() {
+ public Bean() {
facets = new HashMap<String, UIComponent>();
-
+ rawMap = new HashMap();
+
UIComponent value = new UIComponent();
facets.put("header", value);
@@ -71,6 +73,10 @@
this.components = components;
}
+ public UIComponent getFacet(String name) {
+ return facets.get(name);
+ }
+
public Map<String, UIComponent> getFacets() {
return facets;
}
@@ -79,6 +85,15 @@
this.facets = facets;
}
+ public Map getRawMap() {
+ return rawMap;
+ }
+
+ public void setRawMap(Map rawMap) {
+ this.rawMap = rawMap;
+ }
+
+
public boolean isReadOnly() {
return readOnly;
}
@@ -86,4 +101,12 @@
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
+
+ public Object count(Object o) {
+ return null;
+ }
+
+ public Integer count(Integer i) {
+ return null;
+ }
}
Modified:
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/ELParserTest.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/ELParserTest.java 2009-12-04
20:54:42 UTC (rev 16074)
+++
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/ELParserTest.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -24,249 +24,452 @@
package org.richfaces.cdk.parser.el.test;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.lang.reflect.Type;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
+import org.richfaces.cdk.parser.el.ELParserUtils;
import org.richfaces.cdk.parser.el.ELVisitor;
import org.richfaces.cdk.parser.el.ParsingException;
public class ELParserTest {
+ private ELVisitor visitor;
+
+ @Before
+ public void setUp() {
+ visitor = new ELVisitor();
+ }
+
+ @After
+ public void tearDown() {
+ visitor = null;
+ }
+
@Test
public void testNull() throws Exception {
- assertEquals(resolveExpression("#{null}"), "null");
+ parseExpression("#{null}");
+ assertEquals("null", visitor.getParsedExpression());
+ assertTrue(ELParserUtils.isNullType(visitor.getVariableType()));
}
@Test
public void testTrue() throws Exception {
- assertEquals(resolveExpression("#{true}"), "true");
+ parseExpression("#{true}");
+ assertEquals("true", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testFalse() throws Exception {
- assertEquals(resolveExpression("#{false}"), "false");
+ parseExpression("#{false}");
+ assertEquals("false", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testFloat() throws Exception {
- assertEquals(resolveExpression("#{5.0}"),
"Double.valueOf(5.0)");
- assertEquals(resolveExpression("#{5.012e+34}"),
"Double.valueOf(5.012e+34)");
+ parseExpression("#{5.0}");
+ assertEquals("Double.valueOf(5.0)", visitor.getParsedExpression());
+ assertEquals(Double.TYPE, visitor.getVariableType());
+
+ parseExpression("#{5.012e+34}");
+ assertEquals("Double.valueOf(5.012e+34)",
visitor.getParsedExpression());
+ assertEquals(Double.TYPE, visitor.getVariableType());
}
@Test
public void testNegative() throws Exception {
- assertEquals(resolveExpression("#{-5}"), "-5");
+ parseExpression("#{-5}");
+ assertEquals("-5", visitor.getParsedExpression());
+ assertEquals(Integer.TYPE, visitor.getVariableType());
}
@Test
public void testNegativeFloat() throws Exception {
- assertEquals(resolveExpression("#{-5.0}"),
"-Double.valueOf(5.0)");
+ parseExpression("#{-5.0}");
+ assertEquals("-Double.valueOf(5.0)", visitor.getParsedExpression());
+ assertEquals(Double.TYPE, visitor.getVariableType());
}
@Test
public void testNotEqual() throws Exception {
- assertEquals(resolveExpression("#{1 ne 3}"), "(1 != 3)");
- assertEquals(resolveExpression("#{1 != 3}"), "(1 != 3)");
+ parseExpression("#{1 ne 3}");
+ assertEquals("(1 != 3)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+
+ parseExpression("#{2 != 3}");
+ assertEquals("(2 != 3)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testNot() throws Exception {
- assertEquals(resolveExpression("#{not 1}"), "(!1)");
- assertEquals(resolveExpression("#{!1}"), "(!1)");
+ parseExpression("#{not test}");
+ assertEquals("(!test)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+
+ parseExpression("#{!otherTest}");
+ assertEquals("(!otherTest)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testPlus() throws Exception {
- assertEquals(resolveExpression("#{1+2}"), "(1 + 2)");
+ //TODO: tests involving double values
+ parseExpression("#{1+2}");
+ assertEquals("(1 + 2)", visitor.getParsedExpression());
+ assertEquals(Integer.TYPE, visitor.getVariableType());
}
@Test
public void testMinus() throws Exception {
- assertEquals(resolveExpression("#{1-2}"), "(1 - 2)");
+ parseExpression("#{1-2}");
+ assertEquals("(1 - 2)", visitor.getParsedExpression());
+ assertEquals(Integer.TYPE, visitor.getVariableType());
}
@Test
public void testDiv() throws Exception {
- assertEquals(resolveExpression("#{1/2}"), "(1 / 2)");
+ parseExpression("#{1/2}");
+ assertEquals("(1 / 2)", visitor.getParsedExpression());
+ assertEquals(Integer.TYPE, visitor.getVariableType());
}
@Test
public void testMult() throws Exception {
- assertEquals(resolveExpression("#{1*2}"), "(1 * 2)");
+ parseExpression("#{1*2}");
+ assertEquals("(1 * 2)", visitor.getParsedExpression());
+ assertEquals(Integer.TYPE, visitor.getVariableType());
}
@Test
public void testMod() throws Exception {
- assertEquals(resolveExpression("#{1%2}"), "(1 % 2)");
+ parseExpression("#{1%2}");
+ assertEquals("(1 % 2)", visitor.getParsedExpression());
+ assertEquals(Integer.TYPE, visitor.getVariableType());
}
@Test
public void testAnd() throws Exception {
- assertEquals(resolveExpression("#{1 and 2}"), "(1 &&
2)");
- assertEquals(resolveExpression("#{1 && 2}"), "(1
&& 2)");
+ parseExpression("#{test and otherTest}");
+ assertEquals("(test && otherTest)",
visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+
+ parseExpression("#{otherTest && test}");
+ assertEquals("(otherTest && test)",
visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testOr() throws Exception {
- assertEquals(resolveExpression("#{1 or 2}"), "(1 || 2)");
- assertEquals(resolveExpression("#{1 || 2}"), "(1 || 2)");
+ parseExpression("#{test or otherTest}");
+ assertEquals("(test || otherTest)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+
+ parseExpression("#{otherTest || test}");
+ assertEquals("(otherTest || test)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testEquals() throws Exception {
- assertEquals(resolveExpression("#{1 eq 2}"), "(1 == 2)");
- assertEquals(resolveExpression("#{1 == 2}"), "(1 == 2)");
+ parseExpression("#{1 eq 2}");
+ assertEquals("(1 == 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+
+ parseExpression("#{3 == 2}");
+ assertEquals("(3 == 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testGreatThen() throws Exception {
- assertEquals(resolveExpression("#{1 gt 2}"), "(1 > 2)");
- assertEquals(resolveExpression("#{1 > 2}"), "(1 >
2)");
+ parseExpression("#{1 gt 2}");
+ assertEquals("(1 > 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+
+ parseExpression("#{3 > 2}");
+ assertEquals("(3 > 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testLessThen() throws Exception {
- assertEquals(resolveExpression("#{1 lt 2}"), "(1 < 2)");
- assertEquals(resolveExpression("#{1 < 2}"), "(1 <
2)");
+ parseExpression("#{1 lt 2}");
+ assertEquals("(1 < 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+
+ parseExpression("#{3 < 2}");
+ assertEquals("(3 < 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testLessThenEquals() throws Exception {
- assertEquals(resolveExpression("#{1 le 2}"), "(1 <= 2)");
- assertEquals(resolveExpression("#{1 <= 2}"), "(1 <=
2)");
+ parseExpression("#{1 le 2}");
+ assertEquals("(1 <= 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+
+ parseExpression("#{3 <= 2}");
+ assertEquals("(3 <= 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testGreatThenEquals() throws Exception {
- assertEquals(resolveExpression("#{1 ge 2}"), "(1 >= 2)");
- assertEquals(resolveExpression("#{1 >= 2}"), "(1 >=
2)");
+ parseExpression("#{1 ge 2}");
+ assertEquals("(1 >= 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+
+ parseExpression("#{3 >= 2}");
+ assertEquals("(3 >= 2)", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testChoice() throws Exception {
- assertEquals(resolveExpression("#{1 ? 2 : 3}"), "(1 ? 2 :
3)");
+ parseExpression("#{test ? 2 : 3}");
+ assertEquals("(test ? 2 : 3)", visitor.getParsedExpression());
+ assertEquals(Integer.TYPE, visitor.getVariableType());
+
+ parseExpression("#{test ? null : 'string'}");
+ assertEquals("(test ? null : \"string\")",
visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
}
@Test
public void testInteger() throws Exception {
- assertEquals(resolveExpression("#{152}"), "152");
+ parseExpression("#{152}");
+ assertEquals("152", visitor.getParsedExpression());
+ assertEquals(Integer.TYPE, visitor.getVariableType());
}
@Test
public void testString() throws Exception {
- assertEquals(resolveExpression("#{\"nabc\"}"),
"\"nabc\"");
- assertEquals(resolveExpression("#{'nabc'}"),
"\"nabc\"");
- assertEquals(resolveExpression("#{'\tabc'}"),
"\"\\tabc\"");
- assertEquals(resolveExpression("#{'/nabc'}"),
"\"/nabc\"");
- assertEquals(resolveExpression("#{'na\"bc'}"),
"\"na\\\"bc\"");
- assertEquals(resolveExpression("#{'na\\\\bc'}"),
"\"na\\\\bc\"");
+ parseExpression("#{\"nabc\"}");
+ assertEquals("\"nabc\"", visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
+
+ parseExpression("#{'nabc'}");
+ assertEquals("\"nabc\"", visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
+
+ parseExpression("#{'\tabc'}");
+ assertEquals("\"\\tabc\"", visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
+
+ parseExpression("#{'/nabc'}");
+ assertEquals("\"/nabc\"", visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
+
+ parseExpression("#{'na\"bc'}");
+ assertEquals("\"na\\\"bc\"",
visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
+
+ parseExpression("#{'na\\\\bc'}");
+ assertEquals("\"na\\\\bc\"", visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
}
@Test
public void testIdentifier() throws Exception {
- assertEquals(resolveExpression("#{clientId}"), "clientId");
+ parseExpression("#{clientId}");
+ assertEquals("clientId", visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
}
@Test
public void testLiteral() throws Exception {
- assertEquals(resolveExpression("clientId"),
"\"clientId\"");
+ parseExpression("clientId");
+ assertEquals("\"clientId\"", visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
}
@Test
public void testMethodReturnMap() throws Exception {
- assertEquals(resolveExpression("#{action.facets}"),
"action.getFacets()");
+ parseExpression("#{action.facets}");
+ assertEquals("action.getFacets()", visitor.getParsedExpression());
+ Type variableType = visitor.getVariableType();
+ assertEquals(Map.class, ELParserUtils.getRawType(variableType));
+ assertEquals(UIComponent.class,
ELParserUtils.getLastTypeArgument(variableType));
+
+ parseExpression("#{action.rawMap}");
+ assertEquals("action.getRawMap()", visitor.getParsedExpression());
}
@Test
public void testMethodReturnMapElement() throws Exception {
- assertEquals(resolveExpression("#{action.facets['header']}"),
"action.getFacets().get(\"header\")");
+ parseExpression("#{action.getFacet('header')}");
+ assertEquals("action.getFacet(\"header\")",
visitor.getParsedExpression());
+ assertEquals(UIComponent.class, visitor.getVariableType());
+
+ parseExpression("#{action.facets['header']}");
+ assertEquals("action.getFacets().get(\"header\")",
visitor.getParsedExpression());
+ assertEquals(UIComponent.class, visitor.getVariableType());
+
+ parseExpression("#{action.rawMap['something']}");
+ assertEquals("action.getRawMap().get(\"something\")",
visitor.getParsedExpression());
+ assertEquals(Object.class, visitor.getVariableType());
}
+// @Test
+// public void testMethodReturnMapElement1() throws Exception {
+// assertEquals("action.getFacets().get(\"header\")",
resolveExpression("#{action.facets.header}"));
+// }
+
@Test
public void testMethodReturnMapElement2() throws Exception {
-
assertEquals(resolveExpression("#{action.facets['header'].rendered}"),
-
"action.getFacets().get(\"header\").isRendered()");
+ parseExpression("#{action.facets.toString()}");
+ assertEquals("action.getFacets().toString()",
visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
}
+
+ @Test
+ public void testMethodReturnMapElement3() throws Exception {
+// assertEquals("action.getFacet(\"header\").isRendered()",
+//
resolveExpression("#{action.getFacet('header').rendered}"));
+ parseExpression("#{action.facets['header'].rendered}");
+
assertEquals("action.getFacets().get(\"header\").isRendered()",
+ visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
+ }
@Test
public void testMethod() throws Exception {
- assertEquals(resolveExpression("#{action.readOnly}"),
"action.isReadOnly()");
+ parseExpression("#{action.readOnly}");
+ assertEquals("action.isReadOnly()", visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testNestedMethod() throws Exception {
- assertEquals(resolveExpression("#{action.testBean2.string}"),
"action.getTestBean2().getString()");
+ parseExpression("#{action.testBean2.string}");
+ assertEquals("action.getTestBean2().getString()",
visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
}
@Test
public void testMethodReturnList() throws Exception {
- assertEquals(resolveExpression("#{action.components}"),
"action.getComponents()");
+ parseExpression("#{action.components}");
+ assertEquals("action.getComponents()", visitor.getParsedExpression());
+ Type variableType = visitor.getVariableType();
+ assertEquals(List.class, ELParserUtils.getRawType(variableType));
+ assertEquals(UIComponent.class,
ELParserUtils.getLastTypeArgument(variableType));
}
@Test
public void testMethodReturnListElement() throws Exception {
- assertEquals(resolveExpression("#{action.components[0]}"),
"action.getComponents().get(0)");
+ parseExpression("#{action.components[0]}");
+ assertEquals("action.getComponents().get(0)",
visitor.getParsedExpression());
+ assertEquals(UIComponent.class, visitor.getVariableType());
}
@Test
public void testMethodReturnListElement2() throws Exception {
- assertEquals(resolveExpression("#{action.components[0].rendered}"),
- "action.getComponents().get(0).isRendered()");
+ parseExpression("#{action.components[0].rendered}");
+ assertEquals("action.getComponents().get(0).isRendered()",
visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testMethodReturnArray() throws Exception {
- assertEquals(resolveExpression("#{action.array}"),
"action.getArray()");
+ parseExpression("#{action.array}");
+ assertEquals("action.getArray()", visitor.getParsedExpression());
+ assertEquals(UIComponent[].class, visitor.getVariableType());
}
@Test
public void testMethodReturnArrayElement() throws Exception {
- assertEquals(resolveExpression("#{action.array[0]}"),
"action.getArray()[0]");
+ parseExpression("#{action.array[0]}");
+ assertEquals("action.getArray()[0]", visitor.getParsedExpression());
+ assertEquals(UIComponent.class, visitor.getVariableType());
}
@Test
public void testMethodWithParam() throws Exception {
- assertEquals(resolveExpression("#{getType(action.array[0].rendered,
action.readOnly, true)}"),
-
"this.getType(action.getArray()[0].isRendered(),action.isReadOnly(),true)");
+ parseExpression("#{getType(action.array[0].rendered, action.readOnly,
true)}");
+
assertEquals("this.getType(action.getArray()[0].isRendered(),action.isReadOnly(),true)",
+ visitor.getParsedExpression());
+
+ Type variableType = visitor.getVariableType();
+
+ parseExpression("#{action.count(123)}");
+ assertEquals("action.count(123)", visitor.getParsedExpression());
+ assertEquals(Integer.class, visitor.getVariableType());
+
+ parseExpression("#{action.count(clientId)}");
+ assertEquals("action.count(clientId)", visitor.getParsedExpression());
+ assertEquals(Object.class, visitor.getVariableType());
}
@Test
public void testEmpty() throws Exception {
- assertEquals(resolveExpression("#{empty action.array}"),
"this.getUtils().isEmpty(action.getArray())");
+ parseExpression("#{empty action.array}");
+ assertEquals("this.getUtils().isEmpty(action.getArray())",
visitor.getParsedExpression());
+ assertEquals(Boolean.TYPE, visitor.getVariableType());
}
@Test
public void testFunction() throws Exception {
- assertEquals(resolveExpression("#{getType()}"),
"this.getType()");
+ parseExpression("#{super:getType()}");
+ assertEquals("super.getType()", visitor.getParsedExpression());
+ Type variableType = visitor.getVariableType();
}
@Test
public void testLiteralWithDeferred() throws Exception {
- assertEquals(resolveExpression("abs #{getType()}"), "\"abs
\" + convertToString(this.getType())");
+ parseExpression("#{1}#{2}");
+ assertEquals("convertToString(1) + convertToString(2)",
visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
+
+ parseExpression("abs #{getType()}");
+ assertEquals("\"abs \" + convertToString(this.getType())",
visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
}
@Test
public void testLiteralWithDeferred2() throws Exception {
- assertEquals(resolveExpression("#{getType()} abs "),
"convertToString(this.getType()) + \" abs \"");
+ parseExpression("#{getType()} abs ");
+ assertEquals("convertToString(this.getType()) + \" abs \"",
visitor.getParsedExpression());
+ assertEquals(String.class, visitor.getVariableType());
}
@Test
public void testThisFunction() throws Exception {
- assertEquals(resolveExpression("#{this.getType()}"),
"this.getType()");
+ parseExpression("#{getType()}");
+ assertEquals("this.getType()", visitor.getParsedExpression());
+ Type variableType = visitor.getVariableType();
+
+ parseExpression("#{this.getType()}");
+ assertEquals("this.getType()", visitor.getParsedExpression());
}
@Test
- public void testUtilsFunction() throws Exception {
- assertEquals(resolveExpression("#{utils.getType()}"),
"this.getUtils().getType()");
+ public void testVariableFunction() throws Exception {
+ parseExpression("#{objectVar.getType()}");
+ assertEquals("objectVar.getType()", visitor.getParsedExpression());
+ Type variableType = visitor.getVariableType();
}
@Test
+ public void testNonExistingMethod() throws Exception {
+ parseExpression("#{action.doSomething(clientId, 123)}");
+ assertEquals("action.doSomething(clientId,123)",
visitor.getParsedExpression());
+ assertEquals(Object.class, visitor.getVariableType());
+ }
+
+ @Test
public void testWrongExpression() throws Exception {
try {
- resolveExpression("#{bean.property}");
+ parseExpression("#{bean.property}");
fail("Parsing Exception is not thrown");
} catch (ParsingException pe) {
//TODO - check message
@@ -276,23 +479,21 @@
@Test
public void testWrongExpression2() throws Exception {
- try {
- resolveExpression("#{action.property}");
- fail("Parsing Exception is not thrown");
- } catch (ParsingException pe) {
- assertEquals(pe.getMessage(),
- "property: property not found in class: class
org.richfaces.cdk.parser.el.test.Bean");
- }
+ parseExpression("#{action.property}");
+ assertEquals("action.getProperty()", visitor.getParsedExpression());
+ assertEquals(Object.class, visitor.getVariableType());
}
- private static String resolveExpression(String expression) throws ParsingException {
- Map<String, Class<?>> contextMap = new HashMap<String,
Class<?>>();
+ private void parseExpression(String expression) throws ParsingException {
+ Map<String, Type> contextMap = new HashMap<String, Type>();
contextMap.put("action", org.richfaces.cdk.parser.el.test.Bean.class);
contextMap.put("clientId", String.class);
+ contextMap.put("test", boolean.class);
+ contextMap.put("otherTest", boolean.class);
+ contextMap.put("this", Object.class);
+ contextMap.put("objectVar", Object.class);
- String code = ELVisitor.getInstance().parse(expression, contextMap);
-
- return code;
+ visitor.parse(expression, contextMap);
}
}
Added:
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/TypeUtilsTest.java
===================================================================
---
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/TypeUtilsTest.java
(rev 0)
+++
root/cdk/trunk/plugins/generator/src/test/java/org/richfaces/cdk/parser/el/test/TypeUtilsTest.java 2009-12-04
20:55:31 UTC (rev 16075)
@@ -0,0 +1,128 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat, Inc. and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.richfaces.cdk.parser.el.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.richfaces.cdk.parser.el.ELParserUtils;
+
+/**
+ * @author Nick Belaevski
+ * @since 4.0
+ */
+public class TypeUtilsTest {
+
+ public static final class PropertyClass {
+
+ public String getString() {
+ return null;
+ }
+
+ public Integer[] getIntegerArray() {
+ return null;
+ }
+
+ public Map<String, Object> getParameterizedMap() {
+ return null;
+ }
+
+ public List<Float> getParameterizedList() {
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Map getRawMap() {
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public List getRawList() {
+ return null;
+ }
+ }
+
+ private Type stringType;
+
+ private Type integerArrayType;
+
+ private Type parameterizedMapType;
+
+ private Type parameterizedListType;
+
+ private Type rawMapType;
+
+ private Type rawListType;
+
+ @Before
+ public void setUp() throws Exception {
+ stringType = PropertyClass.class.getMethod("getString")
+ .getGenericReturnType();
+ integerArrayType = PropertyClass.class.getMethod("getIntegerArray")
+ .getGenericReturnType();
+ parameterizedMapType = PropertyClass.class.getMethod(
+ "getParameterizedMap").getGenericReturnType();
+ parameterizedListType = PropertyClass.class.getMethod(
+ "getParameterizedList").getGenericReturnType();
+ rawMapType = PropertyClass.class.getMethod("getRawMap")
+ .getGenericReturnType();
+ rawListType = PropertyClass.class.getMethod("getRawList")
+ .getGenericReturnType();
+ }
+
+ @After
+ public void tearDown() {
+ stringType = null;
+ integerArrayType = null;
+ parameterizedMapType = null;
+ parameterizedListType = null;
+ rawMapType = null;
+ rawListType = null;
+ }
+
+ @Test
+ public void testGetRawType() throws Exception {
+ assertEquals(String.class, ELParserUtils.getRawType(stringType));
+ assertEquals(Integer[].class, ELParserUtils.getRawType(integerArrayType));
+ assertEquals(Map.class, ELParserUtils.getRawType(parameterizedMapType));
+ assertEquals(List.class, ELParserUtils.getRawType(parameterizedListType));
+ assertEquals(Map.class, ELParserUtils.getRawType(rawMapType));
+ assertEquals(List.class, ELParserUtils.getRawType(rawListType));
+ }
+
+ @Test
+ public void testGetActualTypeArguments() throws Exception {
+ assertNull(ELParserUtils.getLastTypeArgument(stringType));
+ assertNull(ELParserUtils.getLastTypeArgument(integerArrayType));
+ assertEquals(Object.class, ELParserUtils.getLastTypeArgument(parameterizedMapType));
+ assertEquals(Float.class, ELParserUtils.getLastTypeArgument(parameterizedListType));
+ assertNull(ELParserUtils.getLastTypeArgument(rawMapType));
+ assertNull(ELParserUtils.getLastTypeArgument(rawListType));
+ }
+}