Home | History | Annotate | Download | only in declarations
      1 /*
      2  * Copyright (C) 2007-2010 Jlio Vilmar Gesser.
      3  * Copyright (C) 2011, 2013-2016 The JavaParser Team.
      4  *
      5  * This file is part of JavaParser.
      6  *
      7  * JavaParser can be used either under the terms of
      8  * a) the GNU Lesser General Public License as published by
      9  *     the Free Software Foundation, either version 3 of the License, or
     10  *     (at your option) any later version.
     11  * b) the terms of the Apache License
     12  *
     13  * You should have received a copy of both licenses in LICENCE.LGPL and
     14  * LICENCE.APACHE. Please refer to those files for details.
     15  *
     16  * JavaParser is distributed in the hope that it will be useful,
     17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     19  * GNU Lesser General Public License for more details.
     20  */
     21 
     22 package com.github.javaparser.resolution.declarations;
     23 
     24 
     25 import com.github.javaparser.resolution.types.ResolvedType;
     26 
     27 import java.util.List;
     28 import java.util.Optional;
     29 
     30 /**
     31  * Declaration of a type parameter.
     32  * For example:
     33  * <p>
     34  * class A&lt;E extends String&gt;{}
     35  * </p>
     36  * <p>
     37  * In this case <b>E</b> would be a type parameter.
     38  *
     39  * @author Federico Tomassetti
     40  */
     41 public interface ResolvedTypeParameterDeclaration extends ResolvedTypeDeclaration {
     42 
     43     /**
     44      * Instantiate a TypeParameter defined on a Type with the given data.
     45      */
     46     static ResolvedTypeParameterDeclaration onType(final String name, String classQName, List<Bound> bounds) {
     47         return new ResolvedTypeParameterDeclaration() {
     48             @Override
     49             public String getName() {
     50                 return name;
     51             }
     52 
     53             @Override
     54             public boolean declaredOnType() {
     55                 return true;
     56             }
     57 
     58             @Override
     59             public boolean declaredOnMethod() {
     60                 return false;
     61             }
     62 
     63             @Override
     64             public boolean declaredOnConstructor() {
     65                 return false;
     66             }
     67 
     68             @Override
     69             public String getContainerQualifiedName() {
     70                 return classQName;
     71             }
     72 
     73             @Override
     74             public String getContainerId() {
     75                 return classQName;
     76             }
     77 
     78             @Override
     79             public ResolvedTypeParametrizable getContainer() {
     80                 return null;
     81             }
     82 
     83             @Override
     84             public List<Bound> getBounds() {
     85                 return bounds;
     86             }
     87 
     88             @Override
     89             public String toString() {
     90                 return "TypeParameter onType " + name;
     91             }
     92 
     93             @Override
     94             public Optional<ResolvedReferenceTypeDeclaration> containerType() {
     95                 throw new UnsupportedOperationException();
     96             }
     97         };
     98     }
     99 
    100     /**
    101      * Name of the type parameter.
    102      */
    103     String getName();
    104 
    105     /**
    106      * Is the type parameter been defined on a type?
    107      */
    108     default boolean declaredOnType() {
    109         return (getContainer() instanceof ResolvedReferenceTypeDeclaration);
    110     }
    111 
    112     /**
    113      * Is the type parameter been defined on a method?
    114      */
    115     default boolean declaredOnMethod() {
    116         return (getContainer() instanceof ResolvedMethodDeclaration);
    117     }
    118 
    119     /**
    120      * Is the type parameter been defined on a constructor?
    121      */
    122     default boolean declaredOnConstructor() {
    123         return (getContainer() instanceof ResolvedConstructorDeclaration);
    124     }
    125 
    126     /**
    127      * The package name of the type bound(s).
    128      * This is unsupported because there is no package for a Type Parameter, only for its container.
    129      */
    130     default String getPackageName() {
    131         throw new UnsupportedOperationException();
    132     }
    133 
    134     /**
    135      * The class(es) wrapping the type bound(s).
    136      * This is unsupported because there is no class for a Type Parameter, only for its container.
    137      */
    138     default String getClassName() {
    139         throw new UnsupportedOperationException();
    140     }
    141 
    142     /**
    143      * The qualified name of the Type Parameter.
    144      * It is composed by the qualified name of the container followed by a dot and the name of the Type Parameter.
    145      * The qualified name of a method is its qualified signature.
    146      */
    147     default String getQualifiedName() {
    148         return String.format("%s.%s", getContainerId(), getName());
    149     }
    150 
    151     /**
    152      * The qualified name of the container.
    153      */
    154     String getContainerQualifiedName();
    155 
    156     /**
    157      * The ID of the container. See TypeContainer.getId
    158      */
    159     String getContainerId();
    160 
    161     /**
    162      * The TypeParametrizable of the container. Can be either a ReferenceTypeDeclaration or a MethodLikeDeclaration
    163      */
    164     ResolvedTypeParametrizable getContainer();
    165 
    166     /**
    167      * The bounds specified for the type parameter.
    168      * For example:
    169      * "extends A" or "super B"
    170      */
    171     List<Bound> getBounds();
    172 
    173     /**
    174      * Has the type parameter a lower bound?
    175      */
    176     default boolean hasLowerBound() {
    177         for (Bound b : getBounds()) {
    178             if (b.isExtends()) {
    179                 return true;
    180             }
    181         }
    182         return false;
    183     }
    184 
    185     /**
    186      * Has the type parameter an upper bound?
    187      */
    188     default boolean hasUpperBound() {
    189         for (Bound b : getBounds()) {
    190             if (b.isSuper()) {
    191                 return true;
    192             }
    193         }
    194         return false;
    195     }
    196 
    197     /**
    198      * Get the type used as lower bound.
    199      *
    200      * @throws IllegalStateException if there is no lower bound
    201      */
    202     default ResolvedType getLowerBound() {
    203         for (Bound b : getBounds()) {
    204             if (b.isExtends()) {
    205                 return b.getType();
    206             }
    207         }
    208         throw new IllegalStateException();
    209     }
    210 
    211     /**
    212      * Get the type used as upper bound.
    213      *
    214      * @throws IllegalStateException if there is no upper bound
    215      */
    216     default ResolvedType getUpperBound() {
    217         for (Bound b : getBounds()) {
    218             if (b.isSuper()) {
    219                 return b.getType();
    220             }
    221         }
    222         throw new IllegalStateException();
    223     }
    224 
    225     /**
    226      * A Bound on a Type Parameter.
    227      */
    228     class Bound {
    229         private boolean extendsBound;
    230         private ResolvedType type;
    231 
    232         private Bound(boolean extendsBound, ResolvedType type) {
    233             this.extendsBound = extendsBound;
    234             this.type = type;
    235         }
    236 
    237         /**
    238          * Create an extends bound with the given type:
    239          * <p>
    240          * extends "given type"
    241          * </p>
    242          */
    243         public static Bound extendsBound(ResolvedType type) {
    244             return new Bound(true, type);
    245         }
    246 
    247         /**
    248          * Create a super bound with the given type:
    249          * <p>
    250          * super "given type"
    251          * </p>
    252          */
    253         public static Bound superBound(ResolvedType type) {
    254             return new Bound(false, type);
    255         }
    256 
    257         /**
    258          * Get the type used in the Bound.
    259          */
    260         public ResolvedType getType() {
    261             return type;
    262         }
    263 
    264         /**
    265          * Is this an extends bound?
    266          */
    267         public boolean isExtends() {
    268             return extendsBound;
    269         }
    270 
    271         /**
    272          * Is this a super bound?
    273          */
    274         public boolean isSuper() {
    275             return !isExtends();
    276         }
    277 
    278         @Override
    279         public String toString() {
    280             return "Bound{" +
    281                     "extendsBound=" + extendsBound +
    282                     ", type=" + type +
    283                     '}';
    284         }
    285 
    286         @Override
    287         public boolean equals(Object o) {
    288             if (this == o) return true;
    289             if (o == null || getClass() != o.getClass()) return false;
    290 
    291             Bound bound = (Bound) o;
    292 
    293             if (extendsBound != bound.extendsBound) return false;
    294             return type != null ? type.equals(bound.type) : bound.type == null;
    295         }
    296 
    297         @Override
    298         public int hashCode() {
    299             int result = (extendsBound ? 1 : 0);
    300             result = 31 * result + (type != null ? type.hashCode() : 0);
    301             return result;
    302         }
    303     }
    304 
    305 }
    306