Package org.apache.beehive.netui.compiler.xdoclet.typesystem.impl.declaration

Source Code of org.apache.beehive.netui.compiler.xdoclet.typesystem.impl.declaration.DeclarationImpl

/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Header:$
*/
package org.apache.beehive.netui.compiler.xdoclet.typesystem.impl.declaration;

import org.apache.beehive.netui.compiler.JpfLanguageConstants;
import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationInstance;
import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationTypeDeclaration;
import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationTypeElementDeclaration;
import org.apache.beehive.netui.compiler.typesystem.declaration.AnnotationValue;
import org.apache.beehive.netui.compiler.typesystem.declaration.Declaration;
import org.apache.beehive.netui.compiler.typesystem.declaration.Modifier;
import org.apache.beehive.netui.compiler.typesystem.type.AnnotationType;
import org.apache.beehive.netui.compiler.typesystem.type.ClassType;
import org.apache.beehive.netui.compiler.typesystem.type.PrimitiveType;
import org.apache.beehive.netui.compiler.typesystem.type.TypeInstance;
import org.apache.beehive.netui.compiler.typesystem.type.ArrayType;
import org.apache.beehive.netui.compiler.typesystem.type.DeclaredType;
import org.apache.beehive.netui.compiler.typesystem.util.SourcePosition;
import org.apache.beehive.netui.compiler.xdoclet.typesystem.impl.DelegatingImpl;
import org.apache.beehive.netui.compiler.xdoclet.typesystem.impl.env.SourcePositionImpl;
import org.apache.beehive.netui.compiler.xdoclet.typesystem.impl.type.AnnotationTypeImpl;
import org.apache.beehive.netui.xdoclet.XDocletCompilerUtils;
import xjavadoc.XDoc;
import xjavadoc.XProgramElement;
import xjavadoc.XTag;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;

public class DeclarationImpl
        extends DelegatingImpl
        implements Declaration, JpfLanguageConstants
{
    private static final String VALIDATION_ERROR_FORWARD_TAG_NAME = "ValidationErrorForward";
    private static final HashMap MODIFIERS = new HashMap();
    private static AnnotationInterfaceParser _annotationInterfaceParser =
            new AnnotationInterfaceParser(ANNOTATION_INTERFACE_PREFIX);
   
    static
    {
        MODIFIERS.put( "abstract", Modifier.ABSTRACT );
        MODIFIERS.put( "private", Modifier.PRIVATE );
        MODIFIERS.put( "protected", Modifier.PROTECTED );
        MODIFIERS.put( "public", Modifier.PUBLIC );
        MODIFIERS.put( "static", Modifier.STATIC );
        MODIFIERS.put( "transient", Modifier.TRANSIENT );
        MODIFIERS.put( "final", Modifier.FINAL );
        MODIFIERS.put( "synchronized", Modifier.SYNCHRONIZED );
        MODIFIERS.put( "native", Modifier.NATIVE );
       
        _annotationInterfaceParser.addMemberArrayAnnotation(FORWARD_TAG_NAME, FORWARDS_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(CATCH_TAG_NAME, CATCHES_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(SIMPLE_ACTION_TAG_NAME, SIMPLE_ACTIONS_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(ACTION_OUTPUT_TAG_NAME, ACTION_OUTPUTS_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(CONDITIONAL_FORWARD_TAG_NAME, CONDITIONAL_FORWARDS_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(MESSAGE_BUNDLE_TAG_NAME, MESSAGE_BUNDLES_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(MESSAGE_ARG_TAG_NAME, MESSAGE_ARGS_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(VALIDATE_CUSTOM_RULE_TAG_NAME, VALIDATE_CUSTOM_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(VALIDATE_CUSTOM_VARIABLE_TAG_NAME, VARIABLES_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(VALIDATION_LOCALE_RULES_TAG_NAME, LOCALE_RULES_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(VALIDATABLE_PROPERTY_TAG_NAME, VALIDATABLE_PROPERTIES_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(VALIDATABLE_BEAN_TAG_NAME, VALIDATABLE_BEANS_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(RAISE_ACTION_TAG_NAME, RAISE_ACTIONS_ATTR );
        _annotationInterfaceParser.addMemberArrayAnnotation(SHARED_FLOW_REF_TAG_NAME, SHARED_FLOW_REFS_ATTR );
       
        _annotationInterfaceParser.addMemberAnnotation(VALIDATION_ERROR_FORWARD_TAG_NAME, VALIDATION_ERROR_FORWARD_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_REQUIRED_TAG_NAME, VALIDATE_REQUIRED_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_MIN_LENGTH_TAG_NAME, VALIDATE_MIN_LENGTH_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_MAX_LENGTH_TAG_NAME, VALIDATE_MAX_LENGTH_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_MASK_TAG_NAME, VALIDATE_MASK_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_TYPE_TAG_NAME, VALIDATE_TYPE_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_DATE_TAG_NAME, VALIDATE_DATE_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_RANGE_TAG_NAME, VALIDATE_RANGE_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_CREDIT_CARD_TAG_NAME, VALIDATE_CREDIT_CARD_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_EMAIL_TAG_NAME, VALIDATE_EMAIL_ATTR );
        _annotationInterfaceParser.addMemberAnnotation(VALIDATE_VALID_WHEN_TAG_NAME, VALIDATE_VALID_WHEN_ATTR );
       
        _annotationInterfaceParser.addMemberOrTopLevelAnnotation( VALIDATABLE_PROPERTY_TAG_NAME );
    }
   
    private HashSet _modifiers;
    private AnnotationInstance[] _annotations;
   
    public DeclarationImpl( XProgramElement delegate )
    {
        super( delegate );
        ArrayList annotations = getAnnotations( delegate );
        _annotations = ( AnnotationInstance[] ) annotations.toArray( new AnnotationInstance[ annotations.size() ] );
    }

    public static AnnotationTypeDeclaration[] getAllAnnotations()
    {
        return _annotationInterfaceParser.getAllAnnotations();
    }
   
    public String getDocComment()
    {
        return getDelegateXProgramElement().getDoc().getCommentText();
    }

    public AnnotationInstance[] getAnnotationInstances()
    {
        return _annotations;
    }

    public Set getModifiers()
    {
        if ( _modifiers == null )
        {
            HashSet modifiers = new HashSet();
            StringTokenizer tok = new StringTokenizer( getDelegateXProgramElement().getModifiers() );
           
            while ( tok.hasMoreTokens() )
            {
                String modifierString = tok.nextToken();
                Modifier modifier = ( Modifier ) MODIFIERS.get( modifierString );
                assert modifier != null : "unrecognized modifier: " + modifierString;
                modifiers.add( modifier );
            }
           
            _modifiers = modifiers;
        }
       
        return _modifiers;
    }

    public String getSimpleName()
    {
        String name = getDelegateXProgramElement().getName();
        int lastDot = name.lastIndexOf( '.' );
        return lastDot != -1 ? name.substring( lastDot + 1 ) : name;
    }

    public SourcePosition getPosition()
    {
        return SourcePositionImpl.get( getDelegateXProgramElement() );
    }

    public boolean hasModifier( Modifier modifier )
    {
        return getModifiers().contains( modifier );
    }

    protected XProgramElement getDelegateXProgramElement()
    {
        return ( XProgramElement ) super.getDelegate();
    }
   
    /**
     * Get all the annotations for the given element.
     * @param element the element (class, method, etc.) to examine
     * @return an ArrayList of AnnotationInstances.
     */
    private static ArrayList getAnnotations( XProgramElement element )
    {
        XDoc doc = element.getDoc();
        ArrayList annotations = new ArrayList();
        List tags = doc != null ? doc.getTags() : null;
        ArrayList parentAnnotations = new ArrayList()// hierarchy of parent annotations, e.g., Action -> Forward -> ...
       
        if ( tags == null ) return annotations;
       
        for ( Iterator i = tags.iterator(); i.hasNext(); )
        {
            XTag tag = ( XTag ) i.next();
            String tagName = tag.getName();
            AnnotationTypeDeclaration decl = _annotationInterfaceParser.getAnnotationTypeDecl(tagName);
           
            if ( decl != null )
            {
                AnnotationType type = new AnnotationTypeImpl( decl );
                Collection attrNames = tag.getAttributeNames();           
                HashMap elementValues = new HashMap();
               
                for ( Iterator j = attrNames.iterator(); j.hasNext(); )
                {
                    String attrName = ( String ) j.next();
                    AnnotationTypeElementDeclaration memberDecl = decl.getMember( attrName );
                    SourcePositionImpl pos = SourcePositionImpl.get( tag, attrName, element );
                    Object val = parseValue( memberDecl, tag.getAttributeValue( attrName ), pos );
                    AnnotationValue value = new AnnotationValueImpl( val, pos, memberDecl );
                    elementValues.put( memberDecl, value );
                }
               
                AnnotationInstanceImpl ann = new AnnotationInstanceImpl( tag, element, type, elementValues );
               
                String memberName = _annotationInterfaceParser.getParentMemberArrayName(tagName);
               
                if ( memberName != null )
                {
                    if ( ! addAnnotationToParent( annotations, ann, memberName, true, parentAnnotations ) )
                    {
                        annotations.add( ann );
                    }
                }
                else if ( ( memberName = _annotationInterfaceParser.getParentMemberName(tagName) ) != null )
                {
                    if ( ! addAnnotationToParent( annotations, ann, memberName, false, parentAnnotations ) )
                    {
                        annotations.add( ann );
                    }
                }
                else
                {
                    annotations.add( ann );
                }
               
                for ( int j = 0, len = parentAnnotations.size(); j < len; ++j )
                {
                    AnnotationInstanceImpl parentAnn = ( AnnotationInstanceImpl ) parentAnnotations.get( j );
                   
                    if ( parentAnn.getAnnotationType().equals( ann.getAnnotationType() ) )
                    {
                        // We found an annotation of this type in the hierarchy of parent annotations.
                        // Replace it and blow away everything after it.
                        for ( int k = j; k < len; ++k )
                        {
                            parentAnnotations.remove( j );
                        }
                        break;
                    }
                }
               
                parentAnnotations.add( ann );
            }
        }
       
        return annotations;
    }
   
    private static boolean addAnnotationToParent( ArrayList annotations, AnnotationInstanceImpl ann, String memberArrayName,
                                                  boolean memberIsArray, ArrayList parentAnnotations )
    {
        if ( annotations.size() == 0 )
        {
            String annName = ann.getDelegateXTag().getName();
            if ( _annotationInterfaceParser.isMemberOrTopLevelAnnotation(annName) ){
                return false;
            }
           
            XDocletCompilerUtils.addError( ann.getPosition(), "error.no-parent-annotation",
                                           new String[]{ ann.getAnnotationType().getAnnotationTypeDeclaration().getQualifiedName() } );
        }
        else
        {
            AnnotationInstanceImpl foundTheRightParent = null;
           
            //
            // Look through the hierarchy of parent annotations, for the first one that can accept the given annotation
            // as a child.
            //
            for ( int i = parentAnnotations.size() - 1; i >= 0; --i )
            {
                AnnotationInstanceImpl parentAnnotation = ( AnnotationInstanceImpl ) parentAnnotations.get( i );
                AnnotationTypeElementDeclaration elementDecl =
                        parentAnnotation.getAnnotationType().getAnnotationTypeDeclaration().getMember( memberArrayName );
               
                if ( elementDecl != null )
                {
                    foundTheRightParent = parentAnnotation;
                   
                    //
                    // Blow away everything past the found parent annotation in the hierarchy.
                    //
                    for ( int j = i + 1, len = parentAnnotations.size(); j < len; ++j )
                    {
                        parentAnnotations.remove( i + 1 );
                    }
                   
                    break;
                }
            }
           
            if ( foundTheRightParent != null )
            {
                foundTheRightParent.addElementValue( memberArrayName, memberIsArray, ann, ann.getPosition() );
            }
            else
            {
                String annName = ann.getDelegateXTag().getName();
                if ( _annotationInterfaceParser.isMemberOrTopLevelAnnotation(annName) ) {
                    return false;
                }
               
                XDocletCompilerUtils.addError( ann.getPosition(), "error.no-parent-annotation",
                                               new String[]{ ann.getAnnotationType().getAnnotationTypeDeclaration().getQualifiedName() } );
            }
        }
       
        return true;
    }
   
    private static Object parseValue( AnnotationTypeElementDeclaration memberDecl, String strValue, SourcePositionImpl pos )
    {
        TypeInstance type = memberDecl.getReturnType();
   
        if ( type instanceof ClassType )
        {
            ClassType classType = ( ClassType ) type;
            String typeName = classType.getClassTypeDeclaration().getQualifiedName();
           
            if ( typeName.equals( "java.lang.String" ) )
            {
                return strValue;
            }
            else if ( typeName.equals( "java.lang.Class" ) )
            {
                TypeInstance retVal = XDocletCompilerUtils.resolveType( strValue, false, pos.getOuterClass() );
               
                if ( retVal == null )
                {
                    XDocletCompilerUtils.addError( pos, "error.unknown-class",
                                                   new String[]{ strValue, memberDecl.getSimpleName() } );
                }
               
                return XDocletCompilerUtils.resolveType( strValue, true, pos.getOuterClass() );
            }
            else
            {
                assert false : "unexpected type in annotation declaration: " + typeName;
            }
        }
        else if ( type instanceof ArrayType )
        {
            ArrayType arrayType = ( ArrayType ) type;
            TypeInstance componentType = arrayType.getComponentType();
           
            // We only handle an array of strings -- nothing else at this point.
            assert componentType instanceof DeclaredType : componentType.getClass().getName();
            assert ( ( DeclaredType ) componentType ).getDeclaration().getQualifiedName().equals( String.class.getName() )
                    : ( ( DeclaredType ) componentType ).getDeclaration().getQualifiedName();
            StringTokenizer tok = new StringTokenizer( strValue, "," );
            ArrayList arrayValues = new ArrayList();
            while ( tok.hasMoreTokens() )
            {
                arrayValues.add( new AnnotationValueImpl( tok.nextToken().trim(), pos, memberDecl ) );
            }
            return arrayValues;
        }
       
        assert type instanceof PrimitiveType : type.getClass().getName();
        switch ( ( ( PrimitiveType ) type ).getKind().asInt() )
        {
            case PrimitiveType.Kind.INT_BOOLEAN:
                return Boolean.valueOf( strValue );
               
            case PrimitiveType.Kind.INT_BYTE:
                return new Byte( strValue );
               
            case PrimitiveType.Kind.INT_SHORT:
                return new Short( strValue );
               
            case PrimitiveType.Kind.INT_INT:
                return new Integer( strValue );
               
            case PrimitiveType.Kind.INT_LONG:
                return new Long( strValue );
               
            case PrimitiveType.Kind.INT_FLOAT:
                return new Float( strValue );
               
            case PrimitiveType.Kind.INT_DOUBLE:
                return new Double( strValue );
        }
   
        assert false : "unrecognized type: " + type.toString();
        return null;
    }
}
TOP

Related Classes of org.apache.beehive.netui.compiler.xdoclet.typesystem.impl.declaration.DeclarationImpl

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.