001package org.apache.commons.digester3.annotations.reflect;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import static java.lang.System.arraycopy;
023
024import java.lang.annotation.Annotation;
025import java.lang.reflect.AnnotatedElement;
026
027/**
028 * Class to supply the missing Java {@code AnnotatedElement} for method arguments.
029 * 
030 * @since 2.1
031 */
032public final class MethodArgument
033    implements AnnotatedElement
034{
035
036    /**
037     * The method argument index.
038     */
039    private final int index;
040
041    /**
042     * The method argument type.
043     */
044    private final Class<?> parameterType;
045
046    /**
047     * The method argument annotations.
048     */
049    private final Annotation[] annotations;
050
051    /**
052     * Creates a new method argument as {@code AnnotatedElement}.
053     * 
054     * @param index the method argument index.
055     * @param parameterType the method argument type.
056     * @param annotations the method argument annotations.
057     */
058    public MethodArgument( int index, Class<?> parameterType, Annotation[] annotations )
059    {
060        if ( parameterType == null )
061        {
062            throw new IllegalArgumentException( "Argument 'parameterType' must be not null" );
063        }
064        if ( annotations == null )
065        {
066            throw new IllegalArgumentException( "Argument 'annotations' must be not null" );
067        }
068
069        this.index = index;
070        this.parameterType = parameterType;
071        this.annotations = new Annotation[annotations.length];
072
073        arraycopy( annotations, 0, this.annotations, 0, annotations.length );
074    }
075
076    /**
077     * Returns the method argument index.
078     * 
079     * @return the method argument index.
080     */
081    public int getIndex()
082    {
083        return this.index;
084    }
085
086    /**
087     * Returns the method argument type.
088     * 
089     * @return the method argument type.
090     */
091    public Class<?> getParameterType()
092    {
093        return this.parameterType;
094    }
095
096    /**
097     * {@inheritDoc}
098     */
099    public <T extends Annotation> T getAnnotation( Class<T> annotationType )
100    {
101        for ( Annotation annotation : this.annotations )
102        {
103            if ( annotationType == annotation.annotationType() )
104            {
105                return annotationType.cast( annotation );
106            }
107        }
108        return null;
109    }
110
111    /**
112     * {@inheritDoc}
113     */
114    public Annotation[] getAnnotations()
115    {
116        return this.getAnnotationsArrayCopy();
117    }
118
119    /**
120     * {@inheritDoc}
121     */
122    public Annotation[] getDeclaredAnnotations()
123    {
124        return this.getAnnotationsArrayCopy();
125    }
126
127    /**
128     * Returns an annotations array, copy of the declared annotations in this method argument.
129     * 
130     * @return an annotations array, copy of the declared annotations in this method argument.
131     */
132    private Annotation[] getAnnotationsArrayCopy()
133    {
134        Annotation[] annotations = new Annotation[this.annotations.length];
135        System.arraycopy( this.annotations, 0, annotations, 0, annotations.length );
136        return annotations;
137    }
138
139    /**
140     * {@inheritDoc}
141     */
142    public boolean isAnnotationPresent( Class<? extends Annotation> annotationType )
143    {
144        for ( Annotation annotation : this.annotations )
145        {
146            if ( annotationType == annotation.annotationType() )
147            {
148                return true;
149            }
150        }
151        return false;
152    }
153
154}