Author: cbrisson
Date: Wed Jul 20 12:03:01 2016
New Revision: 1753490
URL: http://svn.apache.org/viewvc?rev=1753490&view=rev
Log:
[engine] allow conversion of method args from String to Enum constant - fixes
VELOCITY-825
Added:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Converter.java
- copied, changed from r1752371,
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Info.java
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/EnumConstantConversionTestCase.java
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java
Copied:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Converter.java
(from r1752371,
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Info.java)
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Converter.java?p2=velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Converter.java&p1=velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Info.java&r1=1752371&r2=1753490&rev=1753490&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Info.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/Converter.java
Wed Jul 20 12:03:01 2016
@@ -23,75 +23,13 @@ import org.apache.velocity.runtime.parse
import org.apache.velocity.util.StringUtils;
/**
- * Little class to carry in info such as template name, line and column
- * for information error reporting from the uberspector implementations
+ * Converts a value to type T
*
- * @author <a href="mailto:[email protected]">Geir Magnusson Jr.</a>
+ * @author <a href="mailto:[email protected]">Claude Brisson</a>
* @version $Id$
*/
-public class Info
-{
- private int line;
- private int column;
- private String templateName;
-
- /**
- * @param source Usually a template name.
- * @param line The line number from <code>source</code>.
- * @param column The column number from <code>source</code>.
- */
- public Info(String source, int line, int column)
- {
- this.templateName = source;
- this.line = line;
- this.column = column;
- }
-
- public Info(Node node)
- {
- this(node.getTemplateName(), node.getLine(), node.getColumn());
- }
-
- /**
- * Force callers to set the location information.
- */
- private Info()
- {
- }
-
- /**
- * @return The template name.
- */
- public String getTemplateName()
- {
- return templateName;
- }
- /**
- * @return The line number.
- */
- public int getLine()
- {
- return line;
- }
-
- /**
- * @return The column number.
- */
- public int getColumn()
- {
- return column;
- }
-
- /**
- * Formats a textual representation of this object as <code>SOURCE
- * [line X, column Y]</code>.
- *
- * @return String representing this object.
- * @since 1.5
- */
- public String toString()
- {
- return StringUtils.formatFileString(getTemplateName(), getLine(),
getColumn());
- }
+public interface Converter<T>
+{
+ T convert(Object o);
}
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java?rev=1753490&r1=1753489&r2=1753490&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/IntrospectionUtils.java
Wed Jul 20 12:03:01 2016
@@ -112,6 +112,13 @@ public class IntrospectionUtils
return isMethodInvocationConvertible(formal.getComponentType(),
actual, false);
}
+
+ /* Check for manual conversions */
+ if (isExplicitlyConvertible(formal, actual))
+ {
+ return true;
+ }
+
return false;
}
@@ -182,4 +189,45 @@ public class IntrospectionUtils
}
return false;
}
+
+ /**
+ * Check to see if the conversion can be done using an explicit conversion
+ */
+ public static boolean isExplicitlyConvertible(Class formal, Class actual)
+ {
+ /* Check for String to Enum constant conversion */
+ if (formal.isEnum() && actual == String.class)
+ {
+ return true;
+ }
+ return false;
+ }
+
+
+ /**
+ * Returns the appropriate Converter object needed for an explicit
conversion
+ * Returns null if no conversion is needed.
+ *
+ * @param actual found argument type
+ * @param formal expected formal type
+ * @return null if no conversion is needed, or the appropriate Converter
object
+ * @since 2.0
+ */
+ public static Converter getNeededConverter(final Class formal, final Class
actual)
+ {
+ /* the only current use case is the String -> Enum constant
conversion. */
+ if (formal.isEnum() && actual == String.class)
+ {
+ Converter converter = new Converter()
+ {
+ @Override
+ public Object convert(Object o)
+ {
+ return Enum.valueOf((Class<Enum>)formal, (String)o);
+ }
+ };
+ return converter;
+ }
+ return null;
+ }
}
Modified:
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java?rev=1753490&r1=1753489&r2=1753490&view=diff
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java
(original)
+++
velocity/engine/trunk/velocity-engine-core/src/main/java/org/apache/velocity/util/introspection/UberspectImpl.java
Wed Jul 20 12:03:01 2016
@@ -189,7 +189,7 @@ public class UberspectImpl implements Ub
Method m = introspector.getMethod(obj.getClass(), methodName, args);
if (m != null)
{
- return new VelMethodImpl(m);
+ return new VelMethodImpl(m, false,
getNeededConverters(m.getParameterTypes(), args));
}
Class cls = obj.getClass();
@@ -202,7 +202,7 @@ public class UberspectImpl implements Ub
{
// and create a method that knows to wrap the value
// before invoking the method
- return new VelMethodImpl(m, true);
+ return new VelMethodImpl(m, true,
getNeededConverters(m.getParameterTypes(), args));
}
}
// watch for classes, to allow calling their static methods
(VELOCITY-102)
@@ -211,13 +211,39 @@ public class UberspectImpl implements Ub
m = introspector.getMethod((Class)obj, methodName, args);
if (m != null)
{
- return new VelMethodImpl(m);
+ return new VelMethodImpl(m, false,
getNeededConverters(m.getParameterTypes(), args));
}
}
return null;
}
/**
+ * get the list of needed converters to adapt passed argument types to
method types
+ * @return null if not conversion needed, otherwise an array containing
needed converters
+ */
+ private Converter[] getNeededConverters(Class[] expected, Object[]
provided)
+ {
+ // var args are not handled here
+ int n = Math.min(expected.length, provided.length);
+ Converter[] converters = null;
+ for (int i = 0; i < n; ++i)
+ {
+ Object arg = provided[i];
+ if (arg == null) continue;
+ Converter converter =
IntrospectionUtils.getNeededConverter(expected[i], arg.getClass());
+ if (converter != null)
+ {
+ if (converters == null)
+ {
+ converters = new Converter[expected.length];
+ }
+ converters[i] = converter;
+ }
+ }
+ return converters;
+ }
+
+ /**
* Property getter
* @param obj
* @param identifier
@@ -320,13 +346,14 @@ public class UberspectImpl implements Ub
final Method method;
Boolean isVarArg;
boolean wrapArray;
+ Converter converters[];
/**
* @param m
*/
public VelMethodImpl(Method m)
{
- this(m, false);
+ this(m, false, null);
}
/**
@@ -334,8 +361,17 @@ public class UberspectImpl implements Ub
*/
public VelMethodImpl(Method method, boolean wrapArray)
{
+ this(method, wrapArray, null);
+ }
+
+ /**
+ * @since 2.0
+ */
+ public VelMethodImpl(Method method, boolean wrapArray, Converter[]
converters)
+ {
this.method = method;
this.wrapArray = wrapArray;
+ this.converters = converters;
}
private VelMethodImpl()
@@ -366,6 +402,14 @@ public class UberspectImpl implements Ub
}
}
+ if (converters != null)
+ {
+ for (int i = 0; i < actual.length; ++i)
+ {
+ actual[i] = converters[i].convert(actual[i]);
+ }
+ }
+
// call extension point invocation
return doInvoke(o, actual);
}
Added:
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/EnumConstantConversionTestCase.java
URL:
http://svn.apache.org/viewvc/velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/EnumConstantConversionTestCase.java?rev=1753490&view=auto
==============================================================================
---
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/EnumConstantConversionTestCase.java
(added)
+++
velocity/engine/trunk/velocity-engine-core/src/test/java/org/apache/velocity/test/util/introspection/EnumConstantConversionTestCase.java
Wed Jul 20 12:03:01 2016
@@ -0,0 +1,80 @@
+package org.apache.velocity.test.util.introspection;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.exception.MethodInvocationException;
+import org.apache.velocity.test.BaseTestCase;
+import org.apache.velocity.test.misc.TestLogger;
+
+import java.io.StringWriter;
+
+/**
+ * Tests DeprecatedCheckUberspector
+ */
+public class EnumConstantConversionTestCase extends BaseTestCase {
+
+ public EnumConstantConversionTestCase(String name)
+ throws Exception
+ {
+ super(name);
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite(EnumConstantConversionTestCase.class);
+ }
+
+ public static class Obj
+ {
+ public enum Color { RED, GREEN };
+ public String getAction(Color color)
+ {
+ switch (color)
+ {
+ case RED: return "Stop";
+ case GREEN: return "Go";
+ default: return "???";
+ }
+ }
+ }
+
+ protected void setUpContext(VelocityContext context)
+ {
+ context.put("obj", new Obj());
+ }
+
+ public void testStringToEnumConversion()
+ throws Exception
+ {
+ assertEvalEquals("Stop", "$obj.getAction('RED')");
+ assertEvalEquals("Go", "$obj.getAction('GREEN')");
+ try
+ {
+ String result = evaluate("$obj.getAction('BLUE')");
+ fail();
+ }
+ catch(MethodInvocationException mie) {}
+ }
+}