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.
014    package org.apache.tapestry5.ioc.internal.services;
015    
016    import java.lang.reflect.Method;
017    import java.util.List;
018    
019    import javassist.bytecode.ConstPool;
020    import javassist.bytecode.annotation.Annotation;
021    import javassist.bytecode.annotation.AnnotationMemberValue;
022    import javassist.bytecode.annotation.ArrayMemberValue;
023    import javassist.bytecode.annotation.BooleanMemberValue;
024    import javassist.bytecode.annotation.ByteMemberValue;
025    import javassist.bytecode.annotation.CharMemberValue;
026    import javassist.bytecode.annotation.ClassMemberValue;
027    import javassist.bytecode.annotation.DoubleMemberValue;
028    import javassist.bytecode.annotation.EnumMemberValue;
029    import javassist.bytecode.annotation.FloatMemberValue;
030    import javassist.bytecode.annotation.IntegerMemberValue;
031    import javassist.bytecode.annotation.LongMemberValue;
032    import javassist.bytecode.annotation.MemberValue;
033    import javassist.bytecode.annotation.MemberValueVisitor;
034    import javassist.bytecode.annotation.ShortMemberValue;
035    import javassist.bytecode.annotation.StringMemberValue;
036    
037    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
038    
039    public 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    }