aboutsummaryrefslogtreecommitdiffstats
path: root/javaparser-core/src/main/java/com/github/javaparser/resolution/declarations/ResolvedTypeParameterDeclaration.java
blob: 14326db1f99224ab3c843bfbb26eb28c408ee7b3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/*
 * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
 * Copyright (C) 2011, 2013-2016 The JavaParser Team.
 *
 * This file is part of JavaParser.
 *
 * JavaParser can be used either under the terms of
 * a) the GNU Lesser General Public License as published by
 *     the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 * b) the terms of the Apache License
 *
 * You should have received a copy of both licenses in LICENCE.LGPL and
 * LICENCE.APACHE. Please refer to those files for details.
 *
 * JavaParser is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 */

package com.github.javaparser.resolution.declarations;


import com.github.javaparser.resolution.types.ResolvedType;

import java.util.List;
import java.util.Optional;

/**
 * Declaration of a type parameter.
 * For example:
 * <p>
 * class A&lt;E extends String&gt;{}
 * </p>
 * <p>
 * In this case <b>E</b> would be a type parameter.
 *
 * @author Federico Tomassetti
 */
public interface ResolvedTypeParameterDeclaration extends ResolvedTypeDeclaration {

    /**
     * Instantiate a TypeParameter defined on a Type with the given data.
     */
    static ResolvedTypeParameterDeclaration onType(final String name, String classQName, List<Bound> bounds) {
        return new ResolvedTypeParameterDeclaration() {
            @Override
            public String getName() {
                return name;
            }

            @Override
            public boolean declaredOnType() {
                return true;
            }

            @Override
            public boolean declaredOnMethod() {
                return false;
            }

            @Override
            public boolean declaredOnConstructor() {
                return false;
            }

            @Override
            public String getContainerQualifiedName() {
                return classQName;
            }

            @Override
            public String getContainerId() {
                return classQName;
            }
            
            @Override
            public ResolvedTypeParametrizable getContainer() {
                return null;
            }

            @Override
            public List<Bound> getBounds() {
                return bounds;
            }

            @Override
            public String toString() {
                return "TypeParameter onType " + name;
            }

            @Override
            public Optional<ResolvedReferenceTypeDeclaration> containerType() {
                throw new UnsupportedOperationException();
            }
        };
    }

    /**
     * Name of the type parameter.
     */
    String getName();

    /**
     * Is the type parameter been defined on a type?
     */
    default boolean declaredOnType() {
        return (getContainer() instanceof ResolvedReferenceTypeDeclaration);
    }

    /**
     * Is the type parameter been defined on a method?
     */
    default boolean declaredOnMethod() {
        return (getContainer() instanceof ResolvedMethodDeclaration);
    }

    /**
     * Is the type parameter been defined on a constructor?
     */
    default boolean declaredOnConstructor() {
        return (getContainer() instanceof ResolvedConstructorDeclaration);
    }

    /**
     * The package name of the type bound(s).
     * This is unsupported because there is no package for a Type Parameter, only for its container.
     */
    default String getPackageName() {
        throw new UnsupportedOperationException();
    }

    /**
     * The class(es) wrapping the type bound(s).
     * This is unsupported because there is no class for a Type Parameter, only for its container.
     */
    default String getClassName() {
        throw new UnsupportedOperationException();
    }

    /**
     * The qualified name of the Type Parameter.
     * It is composed by the qualified name of the container followed by a dot and the name of the Type Parameter.
     * The qualified name of a method is its qualified signature.
     */
    default String getQualifiedName() {
        return String.format("%s.%s", getContainerId(), getName());
    }

    /**
     * The qualified name of the container.
     */
    String getContainerQualifiedName();

    /**
     * The ID of the container. See TypeContainer.getId
     */
    String getContainerId();
    
    /**
     * The TypeParametrizable of the container. Can be either a ReferenceTypeDeclaration or a MethodLikeDeclaration
     */
    ResolvedTypeParametrizable getContainer();

    /**
     * The bounds specified for the type parameter.
     * For example:
     * "extends A" or "super B"
     */
    List<Bound> getBounds();

    /**
     * Has the type parameter a lower bound?
     */
    default boolean hasLowerBound() {
        for (Bound b : getBounds()) {
            if (b.isExtends()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Has the type parameter an upper bound?
     */
    default boolean hasUpperBound() {
        for (Bound b : getBounds()) {
            if (b.isSuper()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Get the type used as lower bound.
     *
     * @throws IllegalStateException if there is no lower bound
     */
    default ResolvedType getLowerBound() {
        for (Bound b : getBounds()) {
            if (b.isExtends()) {
                return b.getType();
            }
        }
        throw new IllegalStateException();
    }

    /**
     * Get the type used as upper bound.
     *
     * @throws IllegalStateException if there is no upper bound
     */
    default ResolvedType getUpperBound() {
        for (Bound b : getBounds()) {
            if (b.isSuper()) {
                return b.getType();
            }
        }
        throw new IllegalStateException();
    }

    /**
     * A Bound on a Type Parameter.
     */
    class Bound {
        private boolean extendsBound;
        private ResolvedType type;

        private Bound(boolean extendsBound, ResolvedType type) {
            this.extendsBound = extendsBound;
            this.type = type;
        }

        /**
         * Create an extends bound with the given type:
         * <p>
         * extends "given type"
         * </p>
         */
        public static Bound extendsBound(ResolvedType type) {
            return new Bound(true, type);
        }

        /**
         * Create a super bound with the given type:
         * <p>
         * super "given type"
         * </p>
         */
        public static Bound superBound(ResolvedType type) {
            return new Bound(false, type);
        }

        /**
         * Get the type used in the Bound.
         */
        public ResolvedType getType() {
            return type;
        }

        /**
         * Is this an extends bound?
         */
        public boolean isExtends() {
            return extendsBound;
        }

        /**
         * Is this a super bound?
         */
        public boolean isSuper() {
            return !isExtends();
        }

        @Override
        public String toString() {
            return "Bound{" +
                    "extendsBound=" + extendsBound +
                    ", type=" + type +
                    '}';
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Bound bound = (Bound) o;

            if (extendsBound != bound.extendsBound) return false;
            return type != null ? type.equals(bound.type) : bound.type == null;
        }

        @Override
        public int hashCode() {
            int result = (extendsBound ? 1 : 0);
            result = 31 * result + (type != null ? type.hashCode() : 0);
            return result;
        }
    }

}