/*
* Copyright (c) 2001, 2002 The XDoclet team
* All rights reserved.
*/
package xdoclet.modules.apache.struts;
import java.beans.Introspector;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.logging.Log;
import xjavadoc.XClass;
import xjavadoc.XMethod;
import xjavadoc.XTag;
import xdoclet.DocletContext;
import xdoclet.DocletTask;
import xdoclet.XDocletException;
import xdoclet.XDocletTagSupport;
import xdoclet.tagshandler.MethodTagsHandler;
import xdoclet.tagshandler.PackageTagsHandler;
import xdoclet.util.LogUtil;
/**
* @author Matt Raible (matt@raibledesigns.com)
* @created April 26, 2004
* @xdoclet.taghandler namespace="ActionForm"
* @version $Revision: 1.2 $
*/
public class ActionFormTagsHandler extends XDocletTagSupport
{
/**
* Gets the ActionFormClassFor attribute of the ActionFormTagsHandler class.
*
* @param clazz Describe what the parameter does
* @return The ActionFormClassFor value
* @exception XDocletException Describe the exception
*/
public static String getActionFormClassFor(XClass clazz) throws XDocletException
{
String packageName = clazz.getContainingPackage().getName();
packageName = PackageTagsHandler.getPackageNameFor(packageName, true);
return packageName + '.' + getActionFormClassName(clazz);
}
/**
* Gets the ActionFormClassName attribute of the ActionFormTagsHandler class
*
* @param clazz Describe what the parameter does
* @return The ActionFormClassName value
* @exception XDocletException Describe the exception
*/
public static String getActionFormClassName(XClass clazz) throws XDocletException
{
XTag currentTag = ((ActionFormSubTask) DocletContext.getInstance().getSubTaskBy(DocletTask.getSubTaskName(ActionFormSubTask.class))).getCurrentFormTag();
// check if there is a name parameter
String name = currentTag.getAttributeValue("name");
if (name == null) {
return clazz.getTransformedName() + "Form";
}
else {
if (Character.isLowerCase(name.charAt(0))) {
char chars[] = name.toCharArray();
chars[0] = Character.toUpperCase(chars[0]);
return new String(chars);
}
else {
return name;
}
}
}
/**
* Return true if at least one struts:form tag is defined.
*
* @param clazz Class to check
* @return whether class has struts:form tag defined
* @exception XDocletException Description of Exception
*/
public static boolean hasFormDefinition(XClass clazz) throws XDocletException
{
return clazz.getDoc().hasTag("struts.form", false);
}
/**
* Gets the ActionFormClassPattern attribute of the ActionFormTagsHandler class
*
* @return The ActionFormClassPattern value
*/
protected static String getActionFormClassPattern()
{
return ((ActionFormSubTask) DocletContext.getInstance().getSubTaskBy(DocletTask.getSubTaskName(ActionFormSubTask.class))).getActionFormClassPattern();
}
/**
* Return the class name for the current class.
*
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc.tag type="content"
*/
public String actionFormClass() throws XDocletException
{
return getActionFormClassFor(getCurrentClass());
}
/**
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
* @doc.tag type="content"
*/
public String actionFormName() throws XDocletException
{
XTag currentTag = ((ActionFormSubTask) getDocletContext().getSubTaskBy(DocletTask.getSubTaskName(ActionFormSubTask.class))).getCurrentFormTag();
String formName = currentTag.getAttributeValue("name");
if (formName == null || formName.trim().length() == 0) {
return Introspector.decapitalize(getCurrentClass().getTransformedName() + "Form");
}
else {
return Introspector.decapitalize(formName);
}
}
/**
* Evaluates body for all fields included in form generation
*
* @param template The body of the block tag
* @exception XDocletException Description of Exception
* @doc.tag type="block"
*/
public void forAllFormFields(String template) throws XDocletException
{
// all fields carrying @struts:form-field form-name="<bla>" where <bla> is current
// form name, or all persistent fields if include-all="true" is set
Log log = LogUtil.getLog(ActionFormTagsHandler.class, "forAllFormFields");
XClass currentClass = getCurrentClass();
Map foundFields = new HashMap();
if (log.isDebugEnabled()) {
log.debug("BEGIN-----------------------------------------");
}
do {
pushCurrentClass(currentClass);
if (log.isDebugEnabled()) {
log.debug("-----CLASS=" + getCurrentClass().getName() + "----------------");
}
Collection methods = getCurrentClass().getMethods();
for (Iterator j = methods.iterator(); j.hasNext(); ) {
setCurrentMethod((XMethod) j.next());
// We are interested in persistent fields and fields marked as a form-field.
if (MethodTagsHandler.isGetter(getCurrentMethod().getName()) &&
!foundFields.containsKey(getCurrentMethod().getName()) &&
useMethodInForm(getCurrentMethod())) {
if (useMethodInForm(getCurrentMethod())) {
if (log.isDebugEnabled()) {
log.debug("METHOD(I=" + getCurrentMethod().getName());
}
// Store that we found this field so we don't add it twice
foundFields.put(getCurrentMethod().getName(), getCurrentMethod().getName());
generate(template);
}
}
}
// Add super class info
if (getCurrentClass().getSuperclass().getQualifiedName().equals("java.lang.Object")) {
popCurrentClass();
break;
}
popCurrentClass();
currentClass = currentClass.getSuperclass();
} while (true);
if (log.isDebugEnabled()) {
log.debug("END-------------------------------------------");
}
}
/**
* Evaluates the body if the method belongs in a given form.
*
* @param template The body of the block tag
* @exception XDocletException
* @doc.tag type="block"
*/
public void ifUseMethodInForm(String template) throws XDocletException
{
if (useMethodInForm(getCurrentMethod()))
generate(template);
}
/**
* Check that method has struts:form-field tag with valid name, or is pk field (and pk fields are included) or
* include-all="true".
*
* @param method Description of Parameter
* @return Description of the Returned Value
* @exception XDocletException Description of Exception
*/
protected boolean useMethodInForm(XMethod method) throws XDocletException
{
// check for include-all
XTag currentTag = ((ActionFormSubTask) getDocletContext().getSubTaskBy(DocletTask.getSubTaskName(ActionFormSubTask.class))).getCurrentFormTag();
String value = currentTag.getAttributeValue("include-all");
// by default, include all is false
if (value != null && value.equals("true")) {
return true;
}
// check for explicit inclusion
Collection mTags = method.getDoc().getTags("struts:form-field");
// if there's a name on the form, then user must specify a form-name attribute
// on the method. This is so multiple forms can be generated from the same POJO.
String fname = currentTag.getAttributeValue("name");
if (fname == null && !mTags.isEmpty()) {
return true;
}
else {
for (Iterator i = mTags.iterator(); i.hasNext(); ) {
XTag mTag = (XTag) i.next();
String pname = mTag.getAttributeValue("form-name");
if (pname != null && fname != null && fname.equals(pname)) {
return true;
}
}
}
// no need in such field...
return false;
}
}