Package xdoclet.modules.ejb.env

Source Code of xdoclet.modules.ejb.env.EnvTagsHandler

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

import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;
import xjavadoc.XClass;
import xjavadoc.XField;
import xjavadoc.XMember;
import xjavadoc.XMethod;
import xjavadoc.XTag;

import xdoclet.XDocletException;
import xdoclet.XDocletTagSupport;
import xdoclet.util.TypeConversionUtil;

/**
* Handles field level tag's for configuring a bean's environment.
*
* @author               <a href="mailto:matthias@germann.com">Matthias Germann</a>
* @created              March 31, 2005
* @xdoclet.taghandler   namespace="EjbEnv"
* @version              $Revision: 1.3 $
*/
public class EnvTagsHandler extends XDocletTagSupport
{
    /**
     * Maps primitive types to their wrapper classes
     */
    private final static Map wrappers;

    protected XTag  currentTag;
    protected XMember currentMember;
    protected int   currentTagType;
    static {
        Map wps = new HashMap();

        wps.put("boolean", "java.lang.Boolean");
        wps.put("byte", "java.lang.Byte");
        wps.put("char", "java.lang.Character");
        wps.put("short", "java.lang.Short");
        wps.put("int", "java.lang.Integer");
        wps.put("float", "java.lang.Float");
        wps.put("long", "java.lang.Long");
        wps.put("double", "java.lang.Double");
        wrappers = Collections.unmodifiableMap(wps);
    }

    /**
     * Executes the template for all class-, method- and field-level tags with the passed name
     *
     * @param template           the template
     * @param attributes         the attributes
     * @throws XDocletException  if an error occures
     * @doc.param                name="tagName" optional="false" description="the tag name"
     * @doc.param                name="paramName" optional="true" description="the required parameter"
     * @doc.param                name="paramValue" optional="true" description="the value for the required parameter"
     * @doc.tag                  type="block"
     */
    public void forAllTags(String template, Properties attributes) throws XDocletException
    {
        forTags(template, attributes, true, true, true);
    }

    /**
     * Executes the template for all method- and field-level tags with the passed name
     *
     * @param template           the template
     * @param attributes         the attributes
     * @throws XDocletException  if an error occures
     * @doc.param                name="tagName" optional="false" description="the tag name"
     * @doc.param                name="paramName" optional="true" description="the required parameter"
     * @doc.param                name="paramValue" optional="true" description="the value for the required parameter"
     * @doc.tag                  type="block"
     */
    public void forAllMemberTags(String template, Properties attributes) throws XDocletException
    {
        forTags(template, attributes, false, true, true);

    }

    /**
     * Executes the template for all method-level tags with the passed name
     *
     * @param template           the template
     * @param attributes         the attributes
     * @throws XDocletException  if an error occures
     * @doc.param                name="tagName" optional="false" description="the tag name"
     * @doc.param                name="paramName" optional="true" description="the required parameter"
     * @doc.param                name="paramValue" optional="true" description="the value for the required parameter"
     * @doc.tag                  type="block"
     */
    public void forAllMethodTags(String template, Properties attributes) throws XDocletException
    {
        forTags(template, attributes, false, true, false);
    }

    /**
     * Returns the name parameter value for the current tag. If the name parameter is not specified for a method- or
     * field-level tag, the member's name is returned. If the name parameter is not specified for a class level tag, an
     * error is generated.
     *
     * @param attributes            the attributes
     * @return                      the name
     * @exception XDocletException  if an error occures
     * @doc.param                   name="paramName" optional="false" description="the name of the name parameter"
     * @doc.tag                     type="content"
     */
    public String name(Properties attributes) throws XDocletException
    {
        String paramName = attributes.getProperty("paramName");

        if (paramName == null) {
            throw new XDocletException("paramName attribute is mandatory");
        }

        String name = null;
        StringTokenizer st = new StringTokenizer(paramName, ",");

        while (name == null && st.hasMoreTokens()) {
            name = currentTag.getAttributeValue(st.nextToken());
        }

        if (name == null) {
            if (currentMember == null) {
                // class level
                mandatoryParamNotFound(currentTag.getDoc(), paramName, currentTag.getName());
            }
            else {
                // method or field level
                name = currentMember.getName();
            }
        }
        return name;
    }

    /**
     * Returns the type parameter value for the current tag. Returns the field type for field-level tags and the return
     * value for method-level tags. For class-level tags, the value of the type parameter is returned. The wrapper class
     * is returned for primitive fields an methods with primitive return values.
     *
     * @param attributes            the attributes
     * @return                      the type
     * @exception XDocletException  if an error occures
     * @doc.param                   name="paramName" optional="false" description="the name of the type parameter"
     * @doc.param                   name="values" description="The valid values for the parameter, comma separated. An
     *      error message is printed if the parameter value is not one of the values."
     * @doc.param                   name="default" description="The default value is returned if parameter not specified
     *      by user for the tag."
     * @doc.param                   name="mandatory" values="true,false" description="Generate an error if parameter not
     * @doc.tag                     type="content"
     */
    public String type(Properties attributes) throws XDocletException
    {
        if (currentMember == null) {
            // class level tags
            return paramValue(attributes);
        }
        else {
            // method and field level tags
            String type = currentMemberType();
            String wrapper = (String) wrappers.get(type);

            return wrapper == null ? type : wrapper;
        }
    }

    /**
     * Executes the body only if the current tag is either a method- or fiel-level tag or has a type parameter.
     *
     * @param template              the template
     * @param attributes            the attributes
     * @exception XDocletException  if an error occures
     * @doc.param                   name="paramName" optional="false" description="the name of the name parameter"
     * @doc.tag                     type="block"
     */
    public void ifHasType(String template, Properties attributes) throws XDocletException
    {
        String paramName = attributes.getProperty("paramName");

        if (paramName == null) {
            throw new XDocletException("paramName attribute is mandatory");
        }

        if (currentMember == null) {
            // class level tags
            String type = currentTag.getAttributeValue(paramName);

            if (type != null) {
                generate(template);
            }
        }
        else {
            // method and field level tags
            generate(template);
        }
    }

    /**
     * Returns the method or field name. Can only be used inside <code>forAllMemberTags</code> or <code>forAllMethodTags</code>
     * .
     *
     * @param attributes            the attributes
     * @return                      the memeber's name
     * @exception XDocletException  if an error occures
     * @doc.param                   name="prefix" optional="true" description="the prefix for the name"
     * @doc.tag                     type="content"
     */
    public String memberName(Properties attributes) throws XDocletException
    {
        if (currentMember == null) {
            throw new XDocletException("XDtEjbEnv:memberName can only be used inside forAllMemberTags or forAllMethodTags");
        }

        String name = currentMember.getName();
        String prefix = attributes.getProperty("prefix");

        if (prefix != null) {
            name = prefix + "/" + name;
        }
        return name;
    }

    /**
     * Returns the method's return type or the field's type. Can only be used inside <code>forAllMemberTags</code> or
     * <code>forAllMethodTags</code>.
     *
     * @return                      the member's type
     * @exception XDocletException  if an error occures
     * @doc.tag                     type="content"
     */
    public String memberType() throws XDocletException
    {
        if (currentMember == null) {
            throw new XDocletException("XDtEjbEnv:memberType can only be used inside forAllMemberTags or forAllMethodTags");
        }
        return currentMemberType();
    }

    /**
     * Returns the method signature for the current method. Can only be used inside <code>forAllMethodTags</code>.
     *
     * @return                      the current method's signature
     * @exception XDocletException  if an error occures
     * @doc.tag                     type="content"
     */
    public String methodSignature() throws XDocletException
    {
        if (currentMember == null || !(currentMember instanceof XMethod)) {
            throw new XDocletException("XDtEjbEnv:methodSignature can only be used inside forAllMemberTags or forAllMethodTags");
        }

        XMethod method = (XMethod) currentMember;
        StringBuffer sb = new StringBuffer();

        if (Modifier.isProtected(method.getModifierSpecifier())) {
            sb.append("protected ");
        }
        if (Modifier.isPublic(method.getModifierSpecifier())) {
            sb.append("public ");
        }
        sb.append(method.getReturnType().getType().getQualifiedName());
        sb.append(' ');
        sb.append(method.getNameWithSignature(true));

        List exceptions = method.getThrownExceptions();

        if (exceptions.size() > 0) {
            sb.append(" throws ");
            for (Iterator it = exceptions.iterator(); it.hasNext(); ) {
                XClass exception = (XClass) it.next();

                sb.append(exception.getQualifiedName());
                if (it.hasNext()) {
                    sb.append(", ");
                }
            }
        }

        return sb.toString();
    }

    /**
     * Returns the value of a parameter.
     *
     * @param attributes            the attributes
     * @return                      the value
     * @exception XDocletException  if an error occures
     * @doc.param                   name="paramName" optional="false" description="the name of the parameter"
     * @doc.param                   name="values" description="The valid values for the parameter, comma separated. An
     *      error message is printed if the parameter value is not one of the values."
     * @doc.param                   name="default" description="The default value is returned if parameter not specified
     *      by user for the tag."
     * @doc.param                   name="mandatory" values="true,false" description="Generate an error if parameter not
     * @doc.tag                     type="content"
     */
    public String paramValue(Properties attributes) throws XDocletException
    {
        attributes.setProperty("tagName", currentTag.getName());
        return getTagValue(attributes, currentTagType);
    }

    /**
     * Executes the body only if the current tag has a specified parameter
     *
     * @param template              the template
     * @param attributes            the attributes
     * @exception XDocletException  if an error occures
     * @doc.param                   name="paramName" optional="false" description="the name of the parameter"
     * @doc.tag                     type="body"
     */
    public void ifHasParam(String template, Properties attributes) throws XDocletException
    {
        if (paramValue(attributes) != null) {
            generate(template);
        }
    }

    /**
     * Executes the body only if the specified tag's value is equal to the specified value
     *
     * @param template              the template
     * @param attributes            the attributes
     * @exception XDocletException  if an error occures
     * @doc.param                   name="paramName" optional="false" description="the name of the parameter"
     * @doc.param                   name="value" optional="false" description="the value of the parameter"
     * @doc.tag                     type="body"
     */
    public void ifParamValueEquals(String template, Properties attributes) throws XDocletException
    {
        if (isParamValueEqual(attributes)) {
            generate(template);
        }
    }

    /**
     * Executes the body only if the specified tag's value is equal to the specified value
     *
     * @param template              the template
     * @param attributes            the attributes
     * @exception XDocletException  if an error occures
     * @doc.param                   name="paramName" optional="false" description="the name of the parameter"
     * @doc.param                   name="value" optional="false" description="the value of the parameter"
     * @doc.tag                     type="body"
     */
    public void ifParamValueNotEquals(String template, Properties attributes) throws XDocletException
    {
        if (!isParamValueEqual(attributes)) {
            generate(template);
        }
    }


    /**
     * Executes the body only if the current field type or method return type is primitive.
     *
     * @param template              the template
     * @param attributes            the attributes
     * @exception XDocletException  if an error occures
     * @doc.tag                     type="block"
     */
    public void ifPrimitiveMember(String template, Properties attributes) throws XDocletException
    {
        if (isPrimitiveMember()) {
            generate(template);
        }
    }

    /**
     * Executes the body only if the current field type or method return type is not a primitive.
     *
     * @param template              the template
     * @param attributes            the attributes
     * @exception XDocletException  if an error occures
     * @doc.tag                     type="block"
     */
    public void ifNotPrimitiveMember(String template, Properties attributes) throws XDocletException
    {
        if (!isPrimitiveMember()) {
            generate(template);
        }
    }

    /**
     * Executes the body only if the current class has at least one ot the passed tags at field- or method-level
     *
     * @param template              the template
     * @param attributes            the attributes
     * @exception XDocletException  if an error occures
     * @doc.tag                     type="block"
     * @doc.param                   name="tagName" optional="false" description="the tag names (comma separated)"
     * @doc.param                   name="paramName" optional="true" description="tags must have this parameter"
     * @doc.param                   name="paramValue" optional="true" description="tags must have this value for the
     *      parameter with 'paramName'"
     */
    public void ifHasTag(String template, Properties attributes) throws XDocletException
    {
        String tags = attributes.getProperty("tagName");

        if (tags == null) {
            throw new XDocletException("tagName is mandatory");
        }

        String paramName = attributes.getProperty("paramName");
        String paramValue = attributes.getProperty("paramValue");

        if (hasMemberWithTag(getCurrentClass().getMethods(true), tags, paramName, paramValue)) {
            generate(template);
        }
        else {
            if (hasMemberWithTag(getCurrentClass().getFields(true), tags, paramName, paramValue)) {
                generate(template);
            }
        }
    }


    /**
     * Executes the passed template for the passed
     *
     * @param template           the template
     * @param attributes         the parameters
     * @param forClass           indicates whether the template should be excuted for class level tags
     * @param forMethod          indicates whether the template should be excuted for method level tags
     * @param forField           indicates whether the template should be excuted for field level tags
     * @throws XDocletException  if an error occures
     */
    protected void forTags(String template, Properties attributes, boolean forClass, boolean forMethod, boolean forField) throws XDocletException
    {
        boolean superclasses = TypeConversionUtil.stringToBoolean(attributes.getProperty("superclasses"), true);

        String tagName = attributes.getProperty("tagName");

        if (tagName == null) {
            throw new XDocletException("tagName is mandatory");
        }

        StringTokenizer st = new StringTokenizer(tagName, ",");

        while (st.hasMoreTokens()) {
            attributes.setProperty("tagName", st.nextToken());
            forTagsInternal(template, attributes, superclasses, forClass, forMethod, forField);
        }
    }

    /**
     * Called for each tag in the <code>forTags</code> loop. The default behaviour is to call <code>generate(template)</code>
     *
     * @param template           the template
     * @throws XDocletException  if an error occures
     */
    protected void doGenerate(String template) throws XDocletException
    {
        generate(template);
    }


    /**
     * Returns whether the current field type or method return type is primitive.
     *
     * @return   <code>true</code> it the current member is primitive
     */
    private boolean isPrimitiveMember()
    {
        if (currentMember != null) {
            String type = currentMemberType();
            String wrapper = (String) wrappers.get(type);

            if (wrapper != null) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns whether the parameter's value is equal to the specfied value
     *
     * @param attributes         the attributes
     * @return                   <code>true</code> if it is equal
     * @throws XDocletException  if an error occures
     */
    private boolean isParamValueEqual(Properties attributes) throws XDocletException
    {
        String value = attributes.getProperty("value");

        if (value == null) {
            throw new XDocletException("value is mandatory");
        }
        return value.equals(paramValue(attributes));
    }

    /**
     * Executes the passed template for the passed
     *
     * @param template           the template
     * @param attributes         the attriubtes
     * @param superclasses       indicates whether the superclasses of the current class should also be searched
     * @param forClass           indicates whether the template should be excuted for class level tags
     * @param forMethod          indicates whether the template should be excuted for method level tags
     * @param forField           indicates whether the template should be excuted for field level tags
     * @throws XDocletException  if an error occures
     */
    private void forTagsInternal(String template, Properties attributes, boolean superclasses, boolean forClass, boolean forMethod, boolean forField) throws XDocletException
    {

        String tagName = attributes.getProperty("tagName");
        String paramName = attributes.getProperty("paramName");
        String paramValue = attributes.getProperty("paramValue");

        // class level tags
        if (forClass) {
            currentTagType = FOR_CLASS;

            Collection tags = getCurrentClass().getDoc().getTags(tagName, superclasses);

            for (Iterator it = tags.iterator(); it.hasNext(); ) {
                currentTag = (XTag) it.next();
                if (tagMatches(currentTag, paramName, paramValue)) {
                    setCurrentClassTag(currentTag);
                    currentMember = null;
                    doGenerate(template);
                    setCurrentClassTag(null);
                }
            }
        }

        // method level tags
        if (forMethod) {
            currentTagType = FOR_METHOD;

            Collection methods = getCurrentClass().getMethods(superclasses);

            for (Iterator it = methods.iterator(); it.hasNext(); ) {
                XMethod method = (XMethod) it.next();

                setCurrentMethod(method);

                Collection tags = method.getDoc().getTags(tagName);

                for (Iterator it2 = tags.iterator(); it2.hasNext(); ) {
                    currentTag = (XTag) it2.next();
                    if (tagMatches(currentTag, paramName, paramValue)) {
                        setCurrentMethodTag(currentTag);
                        currentMember = method;
                        doGenerate(template);
                        setCurrentMethodTag(null);
                    }
                }
                setCurrentMethod(null);
            }
        }

        // field level tags
        if (forField) {
            currentTagType = FOR_FIELD;

            Collection fields = getCurrentClass().getFields(superclasses);

            for (Iterator it = fields.iterator(); it.hasNext(); ) {
                XField field = (XField) it.next();

                setCurrentField(field);

                Collection tags = field.getDoc().getTags(tagName);

                for (Iterator it2 = tags.iterator(); it2.hasNext(); ) {
                    currentTag = (XTag) it2.next();
                    if (tagMatches(currentTag, paramName, paramValue)) {
                        setCurrentFieldTag(currentTag);
                        currentMember = field;
                        doGenerate(template);
                        setCurrentFieldTag(null);
                    }
                }
                setCurrentField(null);
            }
        }

        currentTagType = 0;
    }

    /**
     * Returns whether the passed tag matches for the passed parameter name and value
     *
     * @param tag         the tag
     * @param paramName   the parameter name or <code>null</code> for no parameter restriction
     * @param paramValue  the value for the parameter <code>paramName</code> or <code>null</code> for no parameter value
     *      restriction
     * @return            <code>true</code> it the tag matches
     */
    private boolean tagMatches(XTag tag, String paramName, String paramValue)
    {
        if (paramName == null) {
            return true;
        }

        String value = tag.getAttributeValue(paramName);

        return value != null && (paramValue == null || value.equals(paramValue));
    }

    /**
     * Returns whether the passed Collection of Members has at least one the passed tags for which a value is bound in
     * the java componenet environement jndi namespace
     *
     * @param members     a <code>Collection</code> o {@link XMember}
     * @param tagNames    the tag names
     * @param paramName   the required parameter or <code>null</code>
     * @param paramValue  the required value of the parameter <code>paramName</code> or <code>null</code>
     * @return            <code>true</code> if the passed Collection of Members has at least one of the tags for which a
     *      value is bound in the java componenet environement jndi namespace
     */
    private boolean hasMemberWithTag(Collection members, String tagNames, String paramName, String paramValue)
    {

        for (Iterator it = members.iterator(); it.hasNext(); ) {
            XMember member = (XMember) it.next();

            StringTokenizer st = new StringTokenizer(tagNames, ",");

            while (st.hasMoreTokens()) {
                Collection tags = member.getDoc().getTags(st.nextToken());

                if (tags.size() > 0) {
                    if (paramName == null) {
                        return true;
                    }
                    else {
                        for (Iterator it2 = tags.iterator(); it2.hasNext(); ) {
                            XTag tag = (XTag) it2.next();
                            String value = tag.getAttributeValue(paramName);

                            if (value != null && (paramValue == null || paramValue.equals(value))) {
                                return true;
                            }
                        }
                    }
                }
            }
        }
        return false;
    }

    /**
     * Returns the type of the current member
     *
     * @return   the type
     */
    private String currentMemberType()
    {
        if (currentMember instanceof XField) {
            return ((XField) currentMember).getType().getQualifiedName();
        }
        else {
            return ((XMethod) currentMember).getReturnType().getType().getQualifiedName();
        }

    }

}
TOP

Related Classes of xdoclet.modules.ejb.env.EnvTagsHandler

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.