Hi.
I've written a simple class which may help others writing Actions with
lesser code. Feel free to use it (and expand it) if you like it.
An example:
public class TestAction extends AbstractAnnotationAction {
@ActionMethod
protected void doMyAction (@SitemapParam("my-param")
@DefaultValue("true") boolean myParam,
@QueryParam("login") String
login,
@QueryParam("counter")
@DefaultValue("0") int counter;
Session session) {
System.out.println ("Login: "+login);
}
}
You can use @QueryParam, @SitemapParam, @ConfParam, @HeaderParam,
@CookieParam, @FileParam. In the signature of the method you can just
add variables if you need them: Request, Session, Redirector, Response,
ResultHashMap, Conext, SourceResolver. All of them will be set
automatically.
All parameters are casted when needed.
The method to be invoked must have a @ActionMethod annotation or you can
define the method using "_method" request or sitemap parameter.
Cheers,
Jörn
import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
import org.apache.avalon.framework.parameters.Parameters;
import org.apache.avalon.framework.thread.ThreadSafe;
import org.apache.cocoon.acting.AbstractConfigurableAction;
import org.apache.cocoon.environment.Context;
import org.apache.cocoon.environment.ObjectModelHelper;
import org.apache.cocoon.environment.Redirector;
import org.apache.cocoon.environment.Request;
import org.apache.cocoon.environment.Response;
import org.apache.cocoon.environment.Session;
import org.apache.cocoon.environment.SourceResolver;
public abstract class AbstractAnnotationAction extends AbstractConfigurableAction implements ThreadSafe {
public final static String STATE = "state";
public final static String SUCCESS = "success";
public final static String FAILURE = "failure";
public final static String MESSAGE = "message";
public final static String METHOD_CALL_NAME = "_method";
protected class ResultHashMap extends HashMap<String, String> {
private static final long serialVersionUID = -4191539718741319953L;
}
@Target(ElementType.PARAMETER)
@Retention (RetentionPolicy.RUNTIME)
public @interface QueryParam {
String value();
}
@Target(ElementType.PARAMETER)
@Retention (RetentionPolicy.RUNTIME)
public @interface SitemapParam {
String value();
}
@Target(ElementType.PARAMETER)
@Retention (RetentionPolicy.RUNTIME)
public @interface ConfParam {
String value();
}
@Target(ElementType.PARAMETER)
@Retention (RetentionPolicy.RUNTIME)
public @interface DefaultValue {
String value();
}
@Target(ElementType.PARAMETER)
@Retention (RetentionPolicy.RUNTIME)
public @interface Format {
String value ();
}
// TODO
@Target(ElementType.PARAMETER)
@Retention (RetentionPolicy.RUNTIME)
public @interface HeaderParam {
String value ();
}
// TODO
@Target(ElementType.PARAMETER)
@Retention (RetentionPolicy.RUNTIME)
public @interface CookieParam {
String value ();
}
//TODO
@Target(ElementType.PARAMETER)
@Retention (RetentionPolicy.RUNTIME)
public @interface FileParam {
String value ();
}
@Target(ElementType.METHOD)
@Retention (RetentionPolicy.RUNTIME)
public @interface ActionMethod {}
@SuppressWarnings("unchecked")
public Map act (Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters params) throws Exception {
ResultHashMap hashMap = new ResultHashMap ();
Request request = ObjectModelHelper.getRequest (objectModel);
try {
Method[] methods = this.getClass ().getDeclaredMethods ();
for (Method m : methods) {
if (m.isAnnotationPresent (ActionMethod.class)
|| m.getName ().equals (request.getParameter (METHOD_CALL_NAME))
|| m.getName ().equals (params.getParameter (METHOD_CALL_NAME, ""))) {
callMethod (m, hashMap, redirector, resolver, objectModel, source, params);
}
}
} catch (Throwable t) { t.printStackTrace (); if (t instanceof Exception) throw (Exception) t; else throw new Exception (t); }
return hashMap;
}
protected void callMethod (Method m, ResultHashMap hashMap, Redirector redirector, SourceResolver resolver, Map<String,String> objectModel, String source, Parameters params) throws Exception {
Request request = ObjectModelHelper.getRequest (objectModel);
//de.agentsinaction.webalarm.Session session = (de.agentsinaction.webalarm.Session) request.getSession (true).getAttribute ("session");
Context context = ObjectModelHelper.getContext (objectModel);
Response response = ObjectModelHelper.getResponse (objectModel);
Class<?>[] methodParams = m.getParameterTypes ();
Object[] objects = new Object[methodParams.length];
Annotation[][] annotations = m.getParameterAnnotations ();
for (int i = 0; i < methodParams.length; i++) {
if (methodParams[i] == ResultHashMap.class)
objects[i] = hashMap;
else
if (methodParams[i] == Request.class)
objects[i] = request;
else
if (methodParams[i] == Context.class)
objects[i] = context;
else
if (methodParams[i] == Response.class)
objects[i] = response;
else
if (methodParams[i] == com.agentsinaction.foomondo.Session.class)
objects[i] = com.agentsinaction.foomondo.Session.getSession (request);
else
if (methodParams[i] == Session.class)
objects[i] = request.getSession (true);
else
if (methodParams[i] == Redirector.class)
objects[i] = redirector;
else
if (methodParams[i] == SourceResolver.class)
objects[i] = resolver;
else
if (methodParams[i] == Parameters.class)
objects[i] = params;
else {
String queryParam = null;
String sitemapParam = null;
String confParam = null;
String defaultValue = null;
String format = null;
for (Annotation a : annotations[i])
if (a.annotationType () == QueryParam.class)
queryParam = ((QueryParam) a).value ();
else
if (a.annotationType () == SitemapParam.class)
sitemapParam = ((SitemapParam) a).value ();
else
if (a.annotationType () == ConfParam.class)
confParam = ((ConfParam) a).value ();
else
if (a.annotationType () == DefaultValue.class)
defaultValue = ((DefaultValue) a).value ();
else
if (a.annotationType () == Format.class)
format = ((Format) a).value ();
try {
if (queryParam != null && m.getParameterTypes ()[i].isArray ())
objects[i] = getValue (m.getParameterTypes ()[i].getComponentType (), request.getParameterValues (queryParam), defaultValue, format);
else
if (queryParam != null)
objects[i] = getValue (m.getParameterTypes ()[i], request.getParameter (queryParam), defaultValue, format);
else
if (sitemapParam != null)
objects[i] = getValue (m.getParameterTypes ()[i], params.getParameter (sitemapParam, null), defaultValue, format);
else
if (confParam != null)
objects[i] = getValue (m.getParameterTypes ()[i], (String) settings.get (confParam), defaultValue, format);
else {
System.err.println ("Warning: Problem with argument #"+i);
objects[i] = null;
}
} catch (ParseException ex) {
ex.printStackTrace ();
objects[i] = null;
}
}
}
/*
System.out.print ("Calling "+m.getName ()+" with ");
for (Object o : objects)
System.out.print (o+",");
System.out.println ();
*/
m.invoke (this, objects);
}
protected Object getValue (Class<?> paramClass, String values[], String defaultValue, String format) throws ParseException {
Object array = Array.newInstance (paramClass, values == null ? 0 : values.length);
for (int i = 0; i < (values == null ? 0 : values.length); i++)
Array.set (array, i, getValue (paramClass, values[i], defaultValue, format));
return array;
}
protected Object getValue (Class<?> paramClass, String value, String defaultValue, String format) throws ParseException {
if (paramClass == String.class)
return value != null ? value : defaultValue;
if (paramClass == Long.TYPE)
return value != null ? getFormattedNumber (paramClass, value, format).longValue () : defaultValue != null ? getFormattedNumber (paramClass, defaultValue, format).longValue () : 0;
if (paramClass == Integer.TYPE)
return value != null ? getFormattedNumber (paramClass, value, format).intValue () : defaultValue != null ? getFormattedNumber (paramClass, defaultValue, format).intValue () : 0;
if (paramClass == Double.TYPE)
return value != null ? getFormattedNumber (paramClass, value, format).doubleValue () : defaultValue != null ? getFormattedNumber (paramClass, defaultValue, format).doubleValue () : 0.0;
if (paramClass == Boolean.TYPE)
return value != null ? getBoolean (value) : defaultValue != null ? getBoolean (defaultValue) : false;
if (paramClass == Calendar.class) {
Calendar c = Calendar.getInstance ();
if (format != null) {
if (value != null)
c.setTime (new SimpleDateFormat (format).parse (value));
else
if (defaultValue != null)
c.setTime (new SimpleDateFormat (format).parse (defaultValue));
}
return c;
}
return null;
}
protected boolean getBoolean (String text) {
return text.equalsIgnoreCase ("on")
|| text.equalsIgnoreCase ("true")
|| text.equalsIgnoreCase ("yes")
|| text.equalsIgnoreCase ("ja")
|| text.equalsIgnoreCase ("1");
}
protected Number getFormattedNumber (Class<?> paramClass, String value, String format) throws ParseException {
if (format != null)
return new DecimalFormat (format).parse (value);
return paramClass == Long.TYPE ? new Long (value) : paramClass == Integer.TYPE ? new Integer (value) : new Double (value);
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]