"Fossies" - the Fresh Open Source Software Archive

Member "apidocs/src-html/org/apache/tapestry5/internal/plastic/AbstractAnnotationBuilder.html" (9 Sep 2020, 13514 Bytes) of package /linux/www/apache-tapestry-5.6.1-apidocs.zip:


Caution: In this restricted "Fossies" environment the current HTML page may not be correctly presentated and may have some non-functional links. You can here alternatively try to browse the pure source code or just view or download the uninterpreted raw source code. If the rendering is insufficient you may try to find and view the page on the project site itself.

001// Copyright 2011, 2012 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
015package org.apache.tapestry5.internal.plastic;
016
017import org.apache.tapestry5.internal.plastic.asm.AnnotationVisitor;
018import org.apache.tapestry5.internal.plastic.asm.Opcodes;
019import org.apache.tapestry5.internal.plastic.asm.Type;
020
021import java.lang.reflect.Array;
022import java.util.ArrayList;
023import java.util.List;
024
025@SuppressWarnings(
026{ "rawtypes", "unchecked" })
027public abstract class AbstractAnnotationBuilder extends AnnotationVisitor
028{
029    protected final PlasticClassPool pool;
030
031    public AbstractAnnotationBuilder(PlasticClassPool pool)
032    {
033        super(Opcodes.ASM4);
034
035        this.pool = pool;
036    }
037
038    protected abstract void store(String name, Object value);
039
040    protected Class elementTypeForArrayAttribute(String name)
041    {
042        throw new IllegalStateException("elementTypeForArrayAttribute() may not be invoked here.");
043    }
044
045    @Override
046    public void visit(String name, Object value)
047    {
048        if (value instanceof Type)
049        {
050            Type type = (Type) value;
051
052            Class valueType = pool.loadClass(type.getClassName());
053            store(name, valueType);
054            return;
055        }
056
057        store(name, value);
058    }
059
060    @Override
061    public void visitEnum(String name, String desc, String value)
062    {
063
064        try
065        {
066            String enumClassName = PlasticInternalUtils.objectDescriptorToClassName(desc);
067
068            Class enumClass = pool.loader.loadClass(enumClassName);
069
070            Object enumValue = Enum.valueOf(enumClass, value);
071
072            store(name, enumValue);
073        }
074        catch (Exception ex)
075        {
076            throw new IllegalArgumentException(String.format("Unable to convert enum annotation attribute %s %s: %s",
077                    value, desc, PlasticInternalUtils.toMessage(ex)), ex);
078        }
079    }
080
081    @Override
082    public AnnotationVisitor visitAnnotation(final String name, String desc)
083    {
084        final AbstractAnnotationBuilder outerBuilder = this;
085
086        final Class nestedAnnotationType = pool.loadClass(PlasticInternalUtils.objectDescriptorToClassName(desc));
087
088        // Return a nested builder that constructs the inner annotation and, at the end of
089        // construction, pushes the final Annotation object into this builder's attributes.
090
091        return new AnnotationBuilder(nestedAnnotationType, pool)
092        {
093            @Override
094            public void visitEnd()
095            {
096                outerBuilder.store(name, createAnnotation());
097            };
098        };
099    }
100
101    @Override
102    public AnnotationVisitor visitArray(final String name)
103    {
104        final List<Object> values = new ArrayList<Object>();
105
106        final Class componentType = elementTypeForArrayAttribute(name);
107
108        final AbstractAnnotationBuilder outerBuilder = this;
109
110        return new AbstractAnnotationBuilder(pool)
111        {
112            @Override
113            protected void store(String name, Object value)
114            {
115                values.add(value);
116            }
117
118            @Override
119            public void visitEnd()
120            {
121                Object array = Array.newInstance(componentType, values.size());
122
123                // Now, empty arrays may be primitive types and will not cast to Object[], but
124                // non empty arrays indicate that it was a Class/Enum/Annotation, which can cast
125                // to Object[]
126
127                if (values.size() != 0)
128                {
129                    for (int i = 0; i<values.size(); i++)
130                    {
131                        Array.set(array, i, values.get(i));
132                    }
133                }
134                outerBuilder.store(name, array);
135            }
136        };
137    }
138
139    @Override
140    public void visitEnd()
141    {
142        // Nothing to do here. Subclasses use this as a chance to store a value into an outer
143        // builder.
144    }
145
146}