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.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StreamTokenizer;
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 final HashMap MEMBER_ARRAY_ANNOTATIONS = new HashMap();
    private static final HashMap MEMBER_ANNOTATIONS = new HashMap();
    private static final HashSet MEMBER_OR_TOPLEVEL_ANNOTATIONS = new HashSet();
   
    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 );
       
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + FORWARD_TAG_NAME, FORWARDS_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + CATCH_TAG_NAME, CATCHES_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + SIMPLE_ACTION_TAG_NAME, SIMPLE_ACTIONS_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + ACTION_OUTPUT_TAG_NAME, ACTION_OUTPUTS_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + CONDITIONAL_FORWARD_TAG_NAME, CONDITIONAL_FORWARDS_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + MESSAGE_BUNDLE_TAG_NAME, MESSAGE_BUNDLES_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + MESSAGE_ARG_TAG_NAME, MESSAGE_ARGS_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_CUSTOM_RULE_TAG_NAME, VALIDATE_CUSTOM_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_CUSTOM_VARIABLE_TAG_NAME, VARIABLES_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATION_LOCALE_RULES_TAG_NAME, LOCALE_RULES_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATABLE_PROPERTY_TAG_NAME, VALIDATABLE_PROPERTIES_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATABLE_BEAN_TAG_NAME, VALIDATABLE_BEANS_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + RAISE_ACTION_TAG_NAME, RAISE_ACTIONS_ATTR );
        MEMBER_ARRAY_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + SHARED_FLOW_REF_TAG_NAME, SHARED_FLOW_REFS_ATTR );
       
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATION_ERROR_FORWARD_TAG_NAME, VALIDATION_ERROR_FORWARD_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_REQUIRED_TAG_NAME, VALIDATE_REQUIRED_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_MIN_LENGTH_TAG_NAME, VALIDATE_MIN_LENGTH_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_MAX_LENGTH_TAG_NAME, VALIDATE_MAX_LENGTH_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_MASK_TAG_NAME, VALIDATE_MASK_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_TYPE_TAG_NAME, VALIDATE_TYPE_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_DATE_TAG_NAME, VALIDATE_DATE_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_RANGE_TAG_NAME, VALIDATE_RANGE_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_CREDIT_CARD_TAG_NAME, VALIDATE_CREDIT_CARD_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_EMAIL_TAG_NAME, VALIDATE_EMAIL_ATTR );
        MEMBER_ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATE_VALID_WHEN_TAG_NAME, VALIDATE_VALID_WHEN_ATTR );
       
        MEMBER_OR_TOPLEVEL_ANNOTATIONS.add( ANNOTATION_INTERFACE_PREFIX + 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 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();
    }
   
    /** Map of String intermediate-name (e.g., "Jpf.Action") to AnnotationTypeDeclaration */
    private static HashMap ANNOTATIONS = new HashMap();
    private static AnnotationTypeDeclaration[] ALL_ANNOTATIONS;
   
    static
    {
        parseAnnotations();
        ALL_ANNOTATIONS = ( AnnotationTypeDeclaration[] )
                ANNOTATIONS.values().toArray( new AnnotationTypeDeclaration[ ANNOTATIONS.size() ] );
    }
   
    public static AnnotationTypeDeclaration[] getAllAnnotations()
    {
        return ALL_ANNOTATIONS;
    }
   
    private static StreamTokenizer getJavaTokenizer( Reader reader )
    {
        StreamTokenizer tok = new StreamTokenizer( reader );
        tok.eolIsSignificant( false );
        tok.lowerCaseMode( false );
        tok.parseNumbers();
        tok.slashSlashComments( true );
        tok.slashStarComments( true );
        tok.wordChars( '_', '_' );
        tok.wordChars( '@', '@' );
        tok.wordChars( '[', '[' );
        tok.wordChars( ']', ']' );
        tok.wordChars( '.', '.' );
        tok.wordChars( '"', '"' );
        tok.wordChars( '-', '-' );
        return tok;
    }
   
    private static void parseAnnotations()
    {
        try
        {
            String annotationsSource = ANNOTATIONS_CLASSNAME.replace( '.', '/' ) + ".java";
            InputStream in = DeclarationImpl.class.getClassLoader().getResourceAsStream( annotationsSource );
            assert in != null : "annotations source not found: " + annotationsSource;
            BufferedReader reader = new BufferedReader( new InputStreamReader( in ) );
            HashMap enums = new HashMap()// String enumTypeName -> HashSet values
            StreamTokenizer tok = getJavaTokenizer( reader );
           
           
            String interfaceQualifier = null;
            String packageName = null;
           
            while ( tok.nextToken() != StreamTokenizer.TT_EOF )
            {
                switch ( tok.ttype )
                {
                    case StreamTokenizer.TT_WORD:
                        String str = tok.sval;
                       
                        if ( packageName == null && str.equals( "package" ) )
                        {
                            packageName = assertWord( tok );
                        }
                        else if ( str.equals( "public" ) )
                        {
                            str = assertWord( tok );
                           
                            if ( str.equals( "interface" ) )
                            {
                                interfaceQualifier = assertWord( tok ) + '.';
                                assertChar( tok, '{' );
                            }
                            else if ( str.equals( "@interface" ) )
                            {
                                AnnotationTypeDeclarationImpl ann =
                                        readAnnotation( tok, interfaceQualifier, packageName, enums );
                                ANNOTATIONS.put( ann.getIntermediateName(), ann );
                               
                                //
                                // Special case:
                                //     validationErrorForward=@Jpf.Forward(...)
                                // looks like this in our world:
                                //     @Jpf.ValidationErrorForward(...)
                                // Here we dynamically create a new ValidationErrorForward annotation based on Forward.
                                //
                                if ( ann.getSimpleName().equals( FORWARD_TAG_NAME ) )
                                {
                                    AnnotationTypeDeclarationImpl validationErrorForwardAnn =
                                        new AnnotationTypeDeclarationImpl( ann, VALIDATION_ERROR_FORWARD_TAG_NAME,
                                                                           interfaceQualifier );
                                    ANNOTATIONS.put( ANNOTATION_INTERFACE_PREFIX + VALIDATION_ERROR_FORWARD_TAG_NAME,
                                                     validationErrorForwardAnn );
                                }
                            }
                            else if ( str.equals( "enum" ) )
                            {
                                readEnum( tok, enums );
                            }
                        }
                        else if ( str.charAt( 0 ) == '@' )
                        {
                            ignoreAnnotation( tok );
                        }
                        break;
                   
                    case StreamTokenizer.TT_NUMBER:
                        break;
                       
                    default:
                        char c = ( char ) tok.ttype;
                       
                        if ( c == '}' )
                        {
                            assert interfaceQualifier != null;
                            interfaceQualifier = null;
                        }
                }
            }
           
            reader.close();
        }
        catch ( IOException e )
        {
            assert false : e;
        }
    }
   
    private static String assertWord( StreamTokenizer tok )
            throws IOException
    {
        tok.nextToken();
        assert tok.ttype == StreamTokenizer.TT_WORD : tok.ttype;
        return tok.sval;
    }
   
    private static void assertChar( StreamTokenizer tok, char c )
        throws IOException
    {
        tok.nextToken();
        assert tok.ttype == c : tok.ttype;
    }
   
    private static AnnotationTypeDeclarationImpl readAnnotation( StreamTokenizer tok, String interfaceQualifier,
                                                                 String packageName, HashMap enums )
        throws IOException
    {
        String annotationName = assertWord( tok );
        ArrayList memberDecls = new ArrayList();
        assertChar( tok, '{' );
       
        while ( tok.nextToken() == StreamTokenizer.TT_WORD )
        {
            String memberType = tok.sval;
            HashSet enumVals = ( HashSet ) enums.get( memberType );
           
            tok.nextToken();
            if ( tok.ttype == '<' ) // ignore generics
            {
                while ( tok.nextToken() != '>' )
                {
                    assert tok.ttype != StreamTokenizer.TT_EOF;
                    assert tok.ttype != ';';
                }
                tok.nextToken();
            }
            assert tok.ttype == StreamTokenizer.TT_WORD;
            String memberName = tok.sval;
            assertChar( tok, '(' );
            assertChar( tok, ')' );
           
            Object defaultVal = null;
           
            if ( tok.nextToken() == StreamTokenizer.TT_WORD )
            {
                assert tok.sval.equals( "default" );
               
                tok.nextToken();
                if ( tok.ttype == '{' )
                {
                    assertChar( tok, '}' );
                    defaultVal = new ArrayList();
                }
                else
                {
                    assert tok.ttype == StreamTokenizer.TT_WORD || tok.ttype == StreamTokenizer.TT_NUMBER : tok.ttype;
                   
                    if ( tok.ttype == StreamTokenizer.TT_NUMBER )
                    {
                        defaultVal = getNumericDefaultVal( memberType, tok.nval );
                    }
                    else
                    {
                        String defaultString = tok.sval;
                       
                        if ( defaultString.charAt( 0 ) == '@' )
                        {
                            // It's a default value that is an annotation.  We ignore these for now.
                            ignoreAnnotation( tok );
                        }
                        else
                        {
                            if ( memberType.equals( "String" ) )
                            {
                                assert defaultString.charAt( 0 ) == '"' : defaultString;
                                int len = defaultString.length();
                                assert len > 1 && defaultString.charAt( len - 1 ) == '"' : defaultString;
                                defaultVal = defaultString.substring( 0, len - 1 );
                            }
                            else if ( memberType.equals( "boolean" ) )
                            {
                                defaultVal = Boolean.valueOf( defaultString );
                            }
                            else if ( memberType.equals( "Class") )
                            {
                                assert defaultString.endsWith( ".class" );
                                defaultVal = defaultString.substring( 0, defaultString.indexOf( ".class" ) );
                            }
                            else
                            {
                                defaultVal = readDefaultEnumVal( defaultString, memberType, enumVals );
                            }
                        }
                    }
                }
               
                tok.nextToken();
            }
           
            assert tok.ttype == ';';
           
            if ( enumVals != null ) memberType = "String";
            memberDecls.add( new AnnotationTypeElementDeclarationImpl( memberName, memberType, defaultVal, enumVals ) );
        }
       
        assert tok.ttype == '}';
       
        AnnotationTypeElementDeclaration[] memberArray = ( AnnotationTypeElementDeclaration[] )
                memberDecls.toArray( new AnnotationTypeElementDeclaration[ memberDecls.size() ] );
        return new AnnotationTypeDeclarationImpl( annotationName, interfaceQualifier, packageName, memberArray );
    }
   
    private static String readDefaultEnumVal( String defaultString, String memberType, HashSet enumVals )
    {
        int dot = defaultString.indexOf( '.' );
        assert dot != -1 : "expected an enum value: " + defaultString;
        String type = defaultString.substring( 0, dot );
        assert type.equals( memberType ) : "expected enum " + memberType + ", got " + type;
        assert enumVals != null : "no enum " + memberType
                                  + " defined; currently, enum must be defined before its use";
        String defaultVal = defaultString.substring( dot + 1 );
        assert enumVals.contains( defaultVal ) :
                "invalid enum field " + defaultVal + " on enum " + type;
        return defaultVal;
    }
   
    private static Object getNumericDefaultVal( String expectedType, double defaultNumber )
    {
        if ( expectedType.equals( "int" ) )
        {
            return new Integer( ( int ) defaultNumber );
        }
        else if ( expectedType.equals( "long" ) )
        {
            return new Long( ( long ) defaultNumber );
        }
        else if ( expectedType.equals( "float" ) )
        {
            return new Float( ( float ) defaultNumber );
        }
        else if ( expectedType.equals( "double" ) )
        {
            return new Double( defaultNumber );
        }
       
        assert false : "type " + expectedType + " cannot accept value " + defaultNumber;
        return null;
    }
   
    private static void ignoreAnnotation( StreamTokenizer tok )
        throws IOException
    {
        while ( tok.nextToken() != ')' )
        {
            assert tok.ttype != StreamTokenizer.TT_EOF;
            assert tok.ttype != ';';
        }
    }
   
    private static void readEnum( StreamTokenizer tok, HashMap enums )
            throws IOException
    {
        String enumName = assertWord( tok );
       
        assertChar( tok, '{' );
        HashSet fieldNames = new HashSet();
       
        while ( true )
        {
            fieldNames.add( assertWord( tok ) );
            tok.nextToken();
            if ( tok.ttype == '}' ) break;
            assert tok.ttype == ',' : tok.ttype;    // for now, we only do very simple enums.
        }
       
        enums.put( enumName, fieldNames );
    }
   
    /**
     * 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();
            AnnotationTypeDeclaration decl = ( AnnotationTypeDeclaration ) ANNOTATIONS.get( tag.getName() );
           
            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 = ( String ) MEMBER_ARRAY_ANNOTATIONS.get( tag.getName() );
               
                if ( memberName != null )
                {
                    if ( ! addAnnotationToParent( annotations, ann, memberName, true, parentAnnotations ) )
                    {
                        annotations.add( ann );
                    }
                }
                else if ( ( memberName = ( String ) MEMBER_ANNOTATIONS.get( tag.getName() ) ) != 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 ( MEMBER_OR_TOPLEVEL_ANNOTATIONS.contains( 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 ( MEMBER_OR_TOPLEVEL_ANNOTATIONS.contains( 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.