001// Copyright 2010 The Apache Software Foundation
002//
003// Licensed under the Apache License, Version 2.0 (the "License");
004// you may not use this file except in compliance with the License.
005// You may obtain a copy of the License at
006//
007//     http://www.apache.org/licenses/LICENSE-2.0
008//
009// Unless required by applicable law or agreed to in writing, software
010// distributed under the License is distributed on an "AS IS" BASIS,
011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012// See the License for the specific language governing permissions and
013// limitations under the License.
014package org.apache.tapestry5.ioc.internal.services;
015
016import java.lang.reflect.Method;
017import java.util.List;
018
019import javassist.bytecode.ConstPool;
020import javassist.bytecode.annotation.Annotation;
021import javassist.bytecode.annotation.AnnotationMemberValue;
022import javassist.bytecode.annotation.ArrayMemberValue;
023import javassist.bytecode.annotation.BooleanMemberValue;
024import javassist.bytecode.annotation.ByteMemberValue;
025import javassist.bytecode.annotation.CharMemberValue;
026import javassist.bytecode.annotation.ClassMemberValue;
027import javassist.bytecode.annotation.DoubleMemberValue;
028import javassist.bytecode.annotation.EnumMemberValue;
029import javassist.bytecode.annotation.FloatMemberValue;
030import javassist.bytecode.annotation.IntegerMemberValue;
031import javassist.bytecode.annotation.LongMemberValue;
032import javassist.bytecode.annotation.MemberValue;
033import javassist.bytecode.annotation.MemberValueVisitor;
034import javassist.bytecode.annotation.ShortMemberValue;
035import javassist.bytecode.annotation.StringMemberValue;
036
037import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
038
039public class AnnotationMemberValueVisitor implements MemberValueVisitor
040{
041    private final ConstPool constPool;
042
043    private final CtClassSource classSource;
044
045    private final Object value;
046
047    public AnnotationMemberValueVisitor(final ConstPool constPool, final CtClassSource classSource, final Object value)
048    {
049        this.constPool = constPool;
050        this.classSource = classSource;
051        this.value = value;
052    }
053
054    public void visitAnnotationMemberValue(final AnnotationMemberValue mb)
055    {
056        Class annotationType = getClass(value);
057        
058        final Method[] methods = annotationType.getDeclaredMethods();
059
060        for (final Method method : methods)
061        {
062            try
063            {
064                final Object result = method.invoke(value);
065
066                final MemberValue memberValue = Annotation.createMemberValue(
067                        this.constPool,
068                        this.classSource.toCtClass(result.getClass()));
069
070                memberValue.accept(new AnnotationMemberValueVisitor(this.constPool, this.classSource, result));
071                
072                mb.getValue().addMemberValue(method.getName(), memberValue);
073            }
074            catch (Exception e)
075            {
076                throw new RuntimeException(e);
077            }
078        }
079        
080    }
081
082    public void visitArrayMemberValue(final ArrayMemberValue mb)
083    {
084        final Object[] array = (Object[]) this.value;
085
086        final List<MemberValue> members = CollectionFactory.newList();
087        
088        for (final Object object : array)
089        {
090            try
091            {
092                final MemberValue memberValue = Annotation.createMemberValue(
093                        this.constPool,
094                        this.classSource.toCtClass(getClass(object)));
095
096                memberValue.accept(new AnnotationMemberValueVisitor(this.constPool, this.classSource, object));
097
098                members.add(memberValue);
099            }
100            catch (final Exception e)
101            {
102                throw new RuntimeException(e);
103            }
104        }
105
106        mb.setValue(members.toArray(new MemberValue[] {}));
107    }
108    
109    private Class getClass(Object object)
110    {
111        if(object instanceof java.lang.annotation.Annotation)
112        {
113            return ((java.lang.annotation.Annotation)object).annotationType();
114        }
115        
116        return object.getClass();
117    }
118
119    public void visitBooleanMemberValue(final BooleanMemberValue mb)
120    {
121        mb.setValue((Boolean) this.value);
122    }
123
124    public void visitByteMemberValue(final ByteMemberValue mb)
125    {
126        mb.setValue((Byte) this.value);
127    }
128
129    public void visitCharMemberValue(final CharMemberValue mb)
130    {
131        mb.setValue((Character) this.value);
132    }
133
134    public void visitDoubleMemberValue(final DoubleMemberValue mb)
135    {
136        mb.setValue((Double) this.value);
137    }
138
139    public void visitEnumMemberValue(final EnumMemberValue mb)
140    {
141        final Enum enumeration = (Enum) this.value;
142        
143        final Class type = enumeration.getDeclaringClass();
144        mb.setType(type.getName());
145        mb.setValue(enumeration.name());
146    }
147
148    public void visitFloatMemberValue(final FloatMemberValue mb)
149    {
150        mb.setValue((Float) this.value);
151    }
152
153    public void visitIntegerMemberValue(final IntegerMemberValue mb)
154    {
155        mb.setValue((Integer) this.value);
156    }
157
158    public void visitLongMemberValue(final LongMemberValue mb)
159    {
160        mb.setValue((Long) this.value);
161    }
162
163    public void visitShortMemberValue(final ShortMemberValue mb)
164    {
165        mb.setValue((Short) this.value);
166    }
167
168    public void visitStringMemberValue(final StringMemberValue mb)
169    {
170        mb.setValue((String) this.value);
171    }
172
173    public void visitClassMemberValue(final ClassMemberValue mb)
174    {
175        mb.setValue(((Class) this.value).getName());
176    }
177
178}