Package xdoclet.modules.apache.struts

Source Code of xdoclet.modules.apache.struts.StrutsValidatorTagsHandler

/*
* Copyright (c) 2001, 2002 The XDoclet team
* All rights reserved.
*/
package xdoclet.modules.apache.struts;

import java.util.ArrayList;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.collections.SequencedHashMap;

import xjavadoc.XClass;
import xjavadoc.XMethod;
import xjavadoc.XParameter;
import xjavadoc.XTag;

import xdoclet.DocletSupport;
import xdoclet.XDocletException;
import xdoclet.tagshandler.AbstractProgramElementTagsHandler;
import xdoclet.tagshandler.MethodTagsHandler;
import xdoclet.tagshandler.TypeTagsHandler;
import xdoclet.util.Translator;

/**
* Struts Validator tag handler tags
*
* @author               Erik Hatcher (ehatcher@apache.org)
* @created              August 23, 2002
* @xdoclet.taghandler   namespace="Validator"
* @version              $Revision: 1.12 $
*/
public class StrutsValidatorTagsHandler extends AbstractProgramElementTagsHandler
{
    protected final static List supportedTypes = new ArrayList();
    protected String curFieldName;
    protected String currentArgKey;
    protected Map   args;

    static {
        supportedTypes.add("java.lang.String");
        supportedTypes.add("java.lang.Integer");
        supportedTypes.add("int");
        supportedTypes.add("java.lang.Float");
        supportedTypes.add("float");
        supportedTypes.add("java.lang.Long");
        supportedTypes.add("long");
        supportedTypes.add("java.lang.Double");
        supportedTypes.add("double");
        supportedTypes.add("java.lang.Boolean");
        supportedTypes.add("boolean");
    }

    /**
     * Iterates over all Struts Form beans and evaluates the body of the tag for each class.
     *
     * @param template              The body of the block tag
     * @param attributes            The attributes of the template tag
     * @exception XDocletException
     * @doc.tag                     type="block"
     */
    public void forAllForms(String template, Properties attributes) throws XDocletException
    {
        Collection classes = getAllClasses();

        for (Iterator i = classes.iterator(); i.hasNext(); ) {
            XClass currentClass = (XClass) i.next();

            setCurrentClass(currentClass);
            if (DocletSupport.isDocletGenerated(getCurrentClass()) || (getCurrentClass().isAbstract())) {
                continue;
            }
            if (TypeTagsHandler.isOfType(currentClass, "org.apache.struts.validator.ValidatorForm", TypeTagsHandler.TYPE_HIERARCHY)) {
                generate(template);
            }
        }
    }

    /**
     * Gets the "name" attribute for the <form> element in the xml descriptor. This should be the "path" form
     * attribute if this is a ValidatorActiorForm or the "name" attribute otherwise.
     *
     * @param attributes         The content tag attributes.
     * @return                   form name
     * @throws XDocletException  if anything goes awry.
     * @doc.tag                  type="content"
     */
    public String formName(Properties attributes) throws XDocletException
    {
        if (getCurrentClass().isA("org.apache.struts.validator.ValidatorActionForm"))
            return getTagValue(FOR_CLASS, "struts.form", "path", null, null, false, true);
        else
            return getTagValue(FOR_CLASS, "struts.form", "name", null, null, false, true);
    }

    /**
     * Iterates over all arguments for the current field.
     *
     * @param template           The body of the block tag
     * @param attributes         The attributes of the template tag
     * @throws XDocletException
     * @doc.tag                  type="block"
     */
    public void forAllFieldArgs(String template, Properties attributes) throws XDocletException
    {
        for (Iterator iterator = args.keySet().iterator(); iterator.hasNext(); ) {
            currentArgKey = (String) iterator.next();
            generate(template);
        }
    }

    /**
     * Current argument index number (0 to 3).
     *
     * @param props  The content tag attributes.
     * @return       current argument index
     * @doc.tag      type="content"
     */
    public String argIndex(Properties props)
    {
        return currentArgKey.charAt(3) + "";
    }

    /**
     * Current argument name - only valid if argument is for a specific validator type.
     *
     * @param props  The content tag attributes.
     * @return       current argument name
     * @doc.tag      type="content"
     */
    public String argName(Properties props)
    {
        String name = currentArgKey.substring(currentArgKey.indexOf('_') + 1);

        return name;
    }

    /**
     * Current argument value, which is either an inline value or resource key.
     *
     * @param props  The content tag attributes.
     * @return       current argument value
     * @doc.tag      type="content"
     */
    public String argValue(Properties props)
    {
        return (String) args.get(currentArgKey);
    }

    /**
     * Evaluates body if current argument is a resource key.
     *
     * @param template           The body of the block tag
     * @param attributes         The attributes of the template tag
     * @throws XDocletException
     * @doc.tag                  type="block"
     */
    public void ifArgIsResource(String template, Properties attributes) throws XDocletException
    {
        if (currentArgKey.indexOf("resource") > 0) {
            generate(template);
        }
    }

    /**
     * Evaluates the body if the current argument is an inline value rather than a resource key.
     *
     * @param template           The body of the block tag
     * @param attributes         The attributes of the template tag
     * @throws XDocletException
     * @doc.tag                  type="block"
     */
    public void ifArgIsValue(String template, Properties attributes) throws XDocletException
    {
        if (currentArgKey.indexOf("value") > 0) {
            generate(template);
        }
    }

    /**
     * Evaluates the body if the current argument is a validator-specific argument.
     *
     * @param template           The body of the block tag
     * @param attributes         The attributes of the template tag
     * @throws XDocletException
     * @doc.tag                  type="block"
     */
    public void ifArgIsForType(String template, Properties attributes) throws XDocletException
    {
        if (currentArgKey.indexOf('_') > 0) {
            generate(template);
        }
    }

    /**
     * Evaluates the body if there is no arg0 specified.
     *
     * @param template           The body of the block tag
     * @param attributes         The attributes of the template tag
     * @throws XDocletException
     * @doc.tag                  type="block"
     */
    public void ifNoArg0(String template, Properties attributes) throws XDocletException
    {
        if (args.get("arg0resource") == null && args.get("arg0value") == null) {
            generate(template);
        }
    }

    /**
     * Evaluates the body if form has fields requiring validation.
     *
     * @param template           The body of the block tag
     * @param attributes         The attributes of the template tag
     * @throws XDocletException
     * @doc.tag                  type="block"
     */
    public void ifFormHasFields(String template, Properties attributes) throws XDocletException
    {
        if (getFields(getCurrentClass()).size() > 0) {
            generate(template);
        }
    }

    /**
     * Evaluates the body if the current field has an indexed component.
     *
     * @param template           The body of the block tag
     * @param attributes         The attributes of the template tag
     * @throws XDocletException
     * @doc.tag                  type="block"
     */
    public void ifFieldIsIndexed(String template, Properties attributes) throws XDocletException
    {
        if (curFieldName.indexOf("[]") >= 0) {
            generate(template);
        }
    }

    /**
     * Iterates the body for each field of the current form requiring validation.
     *
     * @param template           The body of the block tag
     * @param attributes         The attributes of the template tag
     * @throws XDocletException
     * @doc.tag                  type="block"
     */
    public void forAllFields(String template, Properties attributes) throws XDocletException
    {
        XClass clazz = getCurrentClass();
        Map setters = getFields(clazz);

        for (Iterator iterator = setters.keySet().iterator(); iterator.hasNext(); ) {
            curFieldName = (String) iterator.next();

            XMethod field = (XMethod) setters.get(curFieldName);

            setCurrentMethod(field);
            loadFieldArguments();
            generate(template);
        }
    }

    /**
     * Returns the current field's name, local to the indexed property if there is one.
     *
     * @param props  The content tag attributes.
     * @return       current field name
     * @doc.tag      type="content"
     */
    public String fieldName(Properties props)
    {
        int listIdx = curFieldName.indexOf("[]");

        if (listIdx == -1)
            return curFieldName;

        String result = curFieldName.substring(listIdx + 3);

        if (result.length() == 0)
            return curFieldName.substring(0, listIdx);

        return result;
    }

    /**
     * Returns the current field's indexedListProperty attribute, if any.
     *
     * @param props  The content tag attributes.
     * @return       current field's indexedListProperty
     * @doc.tag      type="content"
     */
    public String indexedListProperty(Properties props)
    {
        int listIdx = curFieldName.indexOf("[]");

        if (listIdx == -1)
            return "";

        return curFieldName.substring(0, listIdx);
    }

    /**
     * Returns a comma-separated list of the specified validator types.
     *
     * @param props  The content tag attributes.
     * @return       validator types list
     * @doc.tag      type="content"
     */
    public String validatorList(Properties props)
    {
        XMethod method = getCurrentMethod();
        Collection tags = method.getDoc().getTags("struts.validator");
        StringBuffer buffer = new StringBuffer();

        for (Iterator iterator = tags.iterator(); iterator.hasNext(); ) {
            XTag tag = (XTag) iterator.next();

            buffer.append(tag.getAttributeValue("type"));
            if (iterator.hasNext()) {
                buffer.append(",");
            }
        }
        return buffer.toString();
    }

    protected Map getFields(XClass clazz) throws XDocletException
    {
        return getFields(clazz, "");
    }

    protected Map getFields(XClass clazz, String prefix) throws XDocletException
    {
        Map fields = new SequencedHashMap();

        Collection curFields = clazz.getMethods(true);

        // TODO: nested forms currently won't work unless
        // there is a setter for it, but that is not needed
        // as only the sub-forms must have setters.  The top-level
        // only requires a getter.
        for (Iterator iterator = curFields.iterator(); iterator.hasNext(); ) {
            XMethod method = (XMethod) iterator.next();
            XTag tag = method.getDoc().getTag("struts.validator");
            String override = null;

            if (tag != null) {
                override = tag.getAttributeValue("override");
            }

            if (tag != null) {
                List params = method.getParameters();
                String name = method.getPropertyName();
                XParameter param = null;

                if (MethodTagsHandler.isSetterMethod(method)) {
                    param = (XParameter) params.get(0);
                }
                else if (params.size() == 2) {
                    // Check for indexed setter setBlah(int index, <type> value)
                    if (!MethodTagsHandler.isSetter(method.getName()))
                        continue;

                    Iterator paramIter = params.iterator();

                    if (!((XParameter) paramIter.next()).getType().isA("int"))
                        continue;

                    if (name.indexOf("[]") >= 0) {
                        throw new XDocletException(Translator.getString(StrutsValidatorMessages.class,
                            StrutsValidatorMessages.ONLY_ONE_LEVEL_LIST_PROPS,
                            new String[]{clazz.getName() + '.' + name + "[]"}));
                    }

                    name = name + "[]";
                    param = (XParameter) paramIter.next();
                }
                else
                    continue;

                String type = param.getType().getQualifiedName();

                if (supportedTypes.contains(type)) {
                    fields.put(prefix + name, method);
                }
                else if ((override != null) && (override.equals("true"))) {
                    fields.put(prefix + name, method);
                }
                else {

                    boolean preDot = (prefix.length() > 0 && prefix.charAt(prefix.length() - 1) != '.');

                    fields.putAll(getFields(param.getType(), prefix + (preDot ? "." : "") + name + "."));
                }
            }
        }

        return fields;
    }

    protected void loadFieldArguments()
    {
        /*
         * A bit of explanation is due here.  Rather than come up with
         * some fancy data structure to keep validator arguments stored into,
         * I simply store them into a Map with the value being the value
         * from the parameter.  The name, however, represents the argument
         * index, whether it's a resource or an inline value, and whether it
         * is attached to a particular validator type.  The name format is:
         * argN[resource|value][_TYPE]
         * the argN[resource|value] piece is the actual parameter name.
         * N is the argument index.
         * TYPE is added only if the parameter appears on struts.validator tag
         * which indicates it's only associated with a specific validator type.
         */
        args = new SequencedHashMap();

        XMethod method = getCurrentMethod();

        // Collect all general args
        Collection argTags = method.getDoc().getTags("struts.validator-args");

        for (Iterator argsIterator = argTags.iterator(); argsIterator.hasNext(); ) {
            XTag tag = (XTag) argsIterator.next();
            Collection attributeNames = tag.getAttributeNames();

            for (Iterator attributesIterator = attributeNames.iterator(); attributesIterator.hasNext(); ) {
                String name = (String) attributesIterator.next();

                if (name.startsWith("arg")) {
                    args.put(name, tag.getAttributeValue(name));
                }
            }
        }

        // Collect all type-specific args
        Collection argTypeTags = method.getDoc().getTags("struts.validator");

        for (Iterator typeTagsIterator = argTypeTags.iterator(); typeTagsIterator.hasNext(); ) {
            XTag tag = (XTag) typeTagsIterator.next();
            Collection attributeNames = tag.getAttributeNames();
            String type = tag.getAttributeValue("type");

            for (Iterator attributesIterator = attributeNames.iterator(); attributesIterator.hasNext(); ) {
                String name = (String) attributesIterator.next();

                if (name.startsWith("arg")) {
                    args.put(name + "_" + type, tag.getAttributeValue(name));
                }
            }
        }
    }
}
TOP

Related Classes of xdoclet.modules.apache.struts.StrutsValidatorTagsHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.