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<E extends String>{} 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