package org.g4studio.core.mvc.xstruts.chain.commands.generic;
import org.g4studio.core.mvc.xstruts.action.ActionForm;
import org.g4studio.core.mvc.xstruts.chain.commands.ActionCommandBase;
import org.g4studio.core.mvc.xstruts.chain.contexts.ActionContext;
import org.g4studio.core.mvc.xstruts.chain.contexts.ActionContextBase;
import org.g4studio.core.mvc.xstruts.config.ActionConfig;
/**
* <p>
* Subclass this command and configure it as part of a per-forward chain to
* perform any necessary pre-population or other preparation for a form before
* control is dispatched to the view layer.
* </p>
*
* @version $Id: CopyFormToContext.java 376862 2006-02-10 21:14:54Z husted $
*/
public class CopyFormToContext extends ActionCommandBase {
// ------------------------------------------------------ Instance Variables
/**
* <p>
* The name of a form bean as configured in a struts-config.xml file for
* this module.
* </p>
*
* <p>
* Either actionPath or both this and scope are required configuration
* properties.
* </p>
*/
private String formName = null;
/**
* <p>
* The name of a scope, such as "request" or "session" in which the form to
* be prepared will be placed for reference by the view and other parts of
* Struts.
* </p>
*
* <p>
* Either <code>actionPath</code> or both this and <code>formName</code> are
* required configuration properties.
* </p>
*/
private String scope = null;
/**
* <p>
* The path of an <code><action></code> mapping as configured in a
* <code>struts-config.xml</code> file for this module. This action will be
* looked up, and its <code>name</code> and <code>scope</code> values will
* be used as if those values were configured directly in this instance's
* <code>formName</code> and <code>scope</code> properties.
* </p>
*
* <p>
* Either <code>this</code> or both <code>scope</code> and
* <code>formName</code> are required configuration properties.
* </p>
*/
private String actionPath = null;
/**
* The context key under which the form which was looked up will be stored.
* Defaults to "actionForm" but may be overridden in cases where the
* "request" ActionForm must be preserved.
*/
private String toKey = ActionContextBase.ACTION_FORM_KEY;
// ------------------------------------------------------ Properties
/**
* <p>
* Return ActionPath property.
* </p>
*
* @return ActionPath property
*/
public String getActionPath() {
return this.actionPath;
}
/**
* <p>
* Set ActionPath property.
* </p>
*
* @param actionPath
* New valuefor ActionPath
*/
public void setActionPath(String actionPath) {
this.actionPath = actionPath;
}
/**
* <p>
* Return FormName property.
* </p>
*
* @return FormName property
*/
public String getFormName() {
return this.formName;
}
/**
* <p>
* Set FormName property.
* </p>
*
* @param formName
* New valuefor FormName
*/
public void setFormName(String formName) {
this.formName = formName;
}
/**
* <p>
* Return Scope property.
* </p>
*
* @return Scope property
*/
public String getScope() {
return this.scope;
}
/**
* <p>
* Set Scope property.
* </p>
*
* @param scope
* New valuefor Scope
*/
public void setScope(String scope) {
this.scope = scope;
}
/**
* <p>
* Return ToKey property.
* </p>
*
* @return ToKey property
*/
public String getToKey() {
return this.toKey;
}
/**
* <p>
* Set ToKey property.
* </p>
*
* @param toKey
* New valuefor FormName
*/
public void setToKey(String toKey) {
this.toKey = toKey;
}
// ------------------------------------------------------
/**
* <p>
* Look up an ActionForm instance based on the configured properties of this
* command and copy it into the <code>Context</code>. After this command
* successfully executes, an ActionForm instance will exist in the specified
* scope and will be available, for example for backing fields in an HTML
* form. It will also be in the <code>ActionContext</code> available for
* another command to do prepopulation of values or other preparation.
* </p>
*
* @param actionContext
* Our ActionContext
* @return TRUE if processing should halt
* @throws Exception
* on any error
*/
public boolean execute(ActionContext actionContext) throws Exception {
ActionForm form = findOrCreateForm(actionContext);
if (isEmpty(getToKey())) {
throw new IllegalStateException("Property 'toKey' must be defined.");
}
actionContext.put(getToKey(), form);
return false;
}
/**
* <p>
* Based on the properties of this command and the given
* <code>ActionContext</code>, find or create an ActionForm instance for
* preparation.
* </p>
*
* @param context
* ActionContextBase class that we are processing
* @return ActionForm instance
* @throws IllegalArgumentException
* On ActionConfig not found
* @throws IllegalStateException
* On undefined scope and formbean
* @throws IllegalAccessException
* On failed instantiation
* @throws InstantiationException
* If ActionContext is not subsclass of ActionContextBase
*/
protected ActionForm findOrCreateForm(ActionContext context) throws IllegalAccessException, InstantiationException {
String effectiveFormName;
String effectiveScope;
if (!(isEmpty(this.getActionPath()))) {
ActionConfig actionConfig = context.getModuleConfig().findActionConfig(this.getActionPath());
if (actionConfig == null) {
throw new IllegalArgumentException("No ActionConfig found for path " + this.getActionPath());
}
effectiveFormName = actionConfig.getName();
effectiveScope = actionConfig.getScope();
} else {
effectiveFormName = this.getFormName();
effectiveScope = this.getScope();
}
if (isEmpty(effectiveScope) || isEmpty(effectiveFormName)) {
throw new IllegalStateException("Both scope [" + effectiveScope + "] and formName [" + effectiveFormName
+ "] must be defined.");
}
return findOrCreateForm(context, effectiveFormName, effectiveScope);
}
/**
* <p>
* Actually find or create an instance of ActionForm configured under the
* form-bean-name <code>effectiveFormName</code>, looking in in the
* <code>ActionContext's</code> scope as identified by
* <code>effectiveScope</code>. If a form is created, it will also be stored
* in that scope.
* </p>
*
* <p>
* <b>NOTE:</b> This specific method depends on the instance of
* <code>ActionContext</code> which is passed being a subclass of
* <code>ActionContextBase</code>, which implements the utility method
* <code>findOrCreateActionForm</code>.
* </p>
*
* @param ctx
* The ActionContext we are processing
* @param effectiveFormName
* the target form name
* @param effectiveScope
* The target scope
* @return ActionForm instnace, storing in scope if created
* @throws InstantiationException
* If ActionContext is not subsclass of ActionContextBase
* @throws InstantiationException
* If object cannot be created
* @throws IllegalArgumentException
* On form not found in/ scope
* @throws IllegalAccessException
* On failed instantiation
* @throws IllegalStateException
* If ActionContext is not a subclass of ActionBase
*/
protected ActionForm findOrCreateForm(ActionContext ctx, String effectiveFormName, String effectiveScope)
throws IllegalAccessException, InstantiationException {
ActionContextBase context;
try {
context = (ActionContextBase) ctx;
} catch (ClassCastException e) {
throw new IllegalStateException("ActionContext [" + ctx + "]" + " must be subclass of ActionContextBase");
}
ActionForm form = context.findOrCreateActionForm(effectiveFormName, effectiveScope);
if (form == null) {
throw new IllegalArgumentException("No form found under scope [" + effectiveScope + "] and formName ["
+ effectiveFormName + "]");
}
return form;
}
/**
* <p>
* Convenience method to test for an empty string.
* </p>
*
* @param test
* String to test
* @return TRUE if test is null or zero-length
*/
private boolean isEmpty(String test) {
return (test == null) || (test.trim().length() == 0);
}
}