1 /*
   2  * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.reflect.generics.visitor;
  27 
  28 
  29 import java.lang.reflect.Type;
  30 import java.util.List;
  31 import java.util.Iterator;
  32 import sun.reflect.generics.tree.*;
  33 import sun.reflect.generics.factory.*;
  34 
  35 
  36 
  37 /**
  38  * Visitor that converts AST to reified types.
  39  */
  40 public class Reifier implements TypeTreeVisitor<Type> {
  41     private Type resultType;
  42     private final GenericsFactory factory;
  43 
  44     private Reifier(GenericsFactory f){
  45         factory = f;
  46     }
  47 
  48     private GenericsFactory getFactory(){ return factory;}
  49 
  50     /**
  51      * Factory method. The resulting visitor will convert an AST
  52      * representing generic signatures into corresponding reflective
  53      * objects, using the provided factory, {@code f}.
  54      * @param f - a factory that can be used to manufacture reflective
  55      * objects returned by this visitor
  56      * @return A visitor that can be used to reify ASTs representing
  57      * generic type information into reflective objects
  58      */
  59     public static Reifier make(GenericsFactory f){
  60         return new Reifier(f);
  61     }
  62 
  63     // Helper method. Visits an array of TypeArgument and produces
  64     // reified Type array.
  65     private Type[] reifyTypeArguments(TypeArgument[] tas) {
  66         Type[] ts = new Type[tas.length];
  67         for (int i = 0; i < tas.length; i++) {
  68             tas[i].accept(this);
  69             ts[i] = resultType;
  70         }
  71         return ts;
  72     }
  73 
  74 
  75     /**
  76      * Accessor for the result of the last visit by this visitor,
  77      * @return The type computed by this visitor based on its last
  78      * visit
  79      */
  80     public Type getResult() { assert resultType != null;return resultType;}
  81 
  82     public void visitFormalTypeParameter(FormalTypeParameter ftp){
  83         resultType = getFactory().makeTypeVariable(ftp.getName(),
  84                                                    ftp.getBounds());
  85     }
  86 
  87 
  88     public void visitClassTypeSignature(ClassTypeSignature ct){
  89         // This method examines the pathname stored in ct, which has the form
  90         // n1.n2...nk<targs>....
  91         // where n1 ... nk-1 might not exist OR
  92         // nk might not exist (but not both). It may be that k equals 1.
  93         // The idea is that nk is the simple class type name that has
  94         // any type parameters associated with it.
  95         //  We process this path in two phases.
  96         //  First, we scan until we reach nk (if it exists).
  97         //  If nk does not exist, this identifies a raw class n1 ... nk-1
  98         // which we can return.
  99         // if nk does exist, we begin the 2nd phase.
 100         // Here nk defines a parameterized type. Every further step nj (j > k)
 101         // down the path must also be represented as a parameterized type,
 102         // whose owner is the representation of the previous step in the path,
 103         // n{j-1}.
 104 
 105         // extract iterator on list of simple class type sigs
 106         List<SimpleClassTypeSignature> scts = ct.getPath();
 107         assert(!scts.isEmpty());
 108         Iterator<SimpleClassTypeSignature> iter = scts.iterator();
 109         SimpleClassTypeSignature sc = iter.next();
 110         StringBuilder n = new StringBuilder(sc.getName());
 111         boolean dollar = sc.getDollar();
 112 
 113         // phase 1: iterate over simple class types until
 114         // we are either done or we hit one with non-empty type parameters
 115         while (iter.hasNext() && sc.getTypeArguments().length == 0) {
 116             sc = iter.next();
 117             dollar = sc.getDollar();
 118             n.append(dollar?"$":".").append(sc.getName());
 119         }
 120 
 121         // Now, either sc is the last element of the list, or
 122         // it has type arguments (or both)
 123         assert(!(iter.hasNext()) || (sc.getTypeArguments().length > 0));
 124         // Create the raw type
 125         Type c = getFactory().makeNamedType(n.toString());
 126         // if there are no type arguments
 127         if (sc.getTypeArguments().length == 0) {
 128             //we have surely reached the end of the path
 129             assert(!iter.hasNext());
 130             resultType = c; // the result is the raw type
 131         } else {
 132             assert(sc.getTypeArguments().length > 0);
 133             // otherwise, we have type arguments, so we create a parameterized
 134             // type, whose declaration is the raw type c, and whose owner is
 135             // the declaring class of c (if any). This latter fact is indicated
 136             // by passing null as the owner.
 137             // First, we reify the type arguments
 138             Type[] pts = reifyTypeArguments(sc.getTypeArguments());
 139 
 140             Type owner = getFactory().makeParameterizedType(c, pts, null);
 141             // phase 2: iterate over remaining simple class types
 142             dollar =false;
 143             while (iter.hasNext()) {
 144                 sc = iter.next();
 145                 dollar = sc.getDollar();
 146                 n.append(dollar?"$":".").append(sc.getName()); // build up raw class name
 147                 c = getFactory().makeNamedType(n.toString()); // obtain raw class
 148                 pts = reifyTypeArguments(sc.getTypeArguments());// reify params
 149                 // Create a parameterized type, based on type args, raw type
 150                 // and previous owner
 151                 owner = getFactory().makeParameterizedType(c, pts, owner);
 152             }
 153             resultType = owner;
 154         }
 155     }
 156 
 157     public void visitArrayTypeSignature(ArrayTypeSignature a){
 158         // extract and reify component type
 159         a.getComponentType().accept(this);
 160         Type ct = resultType;
 161         resultType = getFactory().makeArrayType(ct);
 162     }
 163 
 164     public void visitTypeVariableSignature(TypeVariableSignature tv){
 165         resultType = getFactory().findTypeVariable(tv.getIdentifier());
 166     }
 167 
 168     public void visitWildcard(Wildcard w){
 169         resultType = getFactory().makeWildcard(w.getUpperBounds(),
 170                                                w.getLowerBounds());
 171     }
 172 
 173     public void visitSimpleClassTypeSignature(SimpleClassTypeSignature sct){
 174         resultType = getFactory().makeNamedType(sct.getName());
 175     }
 176 
 177     public void visitBottomSignature(BottomSignature b){
 178 
 179     }
 180 
 181     public void visitByteSignature(ByteSignature b){
 182         resultType = getFactory().makeByte();
 183     }
 184 
 185     public void visitBooleanSignature(BooleanSignature b){
 186         resultType = getFactory().makeBool();
 187     }
 188 
 189     public void visitShortSignature(ShortSignature s){
 190         resultType = getFactory().makeShort();
 191     }
 192 
 193     public void visitCharSignature(CharSignature c){
 194         resultType = getFactory().makeChar();
 195     }
 196 
 197     public void visitIntSignature(IntSignature i){
 198         resultType = getFactory().makeInt();
 199     }
 200 
 201     public void visitLongSignature(LongSignature l){
 202         resultType = getFactory().makeLong();
 203     }
 204 
 205     public void visitFloatSignature(FloatSignature f){
 206         resultType = getFactory().makeFloat();
 207     }
 208 
 209     public void visitDoubleSignature(DoubleSignature d){
 210         resultType = getFactory().makeDouble();
 211     }
 212 
 213     public void visitVoidDescriptor(VoidDescriptor v){
 214         resultType = getFactory().makeVoid();
 215     }
 216 
 217 
 218 }