1 package net.florianschoppmann.java.reflect;
2
3 import javax.annotation.Nullable;
4 import javax.lang.model.element.ElementKind;
5 import javax.lang.model.element.ElementVisitor;
6 import javax.lang.model.element.Name;
7 import javax.lang.model.element.TypeParameterElement;
8 import java.lang.reflect.TypeVariable;
9 import java.util.List;
10 import java.util.Objects;
11
12 final class TypeParameterElementImpl extends ElementImpl implements TypeParameterElement {
13 private final TypeVariable<?> reflectionTypeVariable;
14 private final ElementImpl genericElement;
15 private final TypeVariableImpl typeVariable;
16 @Nullable private List<ReflectionTypeMirror> bounds;
17
18 TypeParameterElementImpl(TypeVariable<?> reflectionTypeVariable, ElementImpl genericElement) {
19 this.reflectionTypeVariable = Objects.requireNonNull(reflectionTypeVariable);
20 this.genericElement = Objects.requireNonNull(genericElement);
21 typeVariable = new TypeVariableImpl(this, null);
22 }
23
24 @Override
25 public boolean equals(@Nullable Object otherObject) {
26 if (this == otherObject) {
27 return true;
28 } else if (otherObject == null || getClass() != otherObject.getClass()) {
29 return false;
30 }
31
32 return reflectionTypeVariable.equals(((TypeParameterElementImpl) otherObject).reflectionTypeVariable);
33 }
34
35 @Override
36 public int hashCode() {
37 return reflectionTypeVariable.hashCode();
38 }
39
40 @Override
41 public String toString() {
42 return reflectionTypeVariable.toString();
43 }
44
45 @Override
46 public <R, P> R accept(ElementVisitor<R, P> visitor, @Nullable P parameter) {
47 return visitor.visitTypeParameter(this, parameter);
48 }
49
50 @Override
51 public ElementImpl getGenericElement() {
52 return genericElement;
53 }
54
55 @Override
56 public List<ReflectionTypeMirror> getBounds() {
57 requireFinished();
58 assert bounds != null : "must be non-null when finished";
59 return bounds;
60 }
61
62 @Override
63 public ElementImpl getEnclosingElement() {
64 return genericElement;
65 }
66
67 @Override
68 public TypeVariableImpl asType() {
69 return typeVariable;
70 }
71
72 @Override
73 public ElementKind getKind() {
74 return ElementKind.TYPE_PARAMETER;
75 }
76
77 @Override
78 public Name getSimpleName() {
79 return new NameImpl(reflectionTypeVariable.getName());
80 }
81
82 @Override
83 public ImmutableList<? extends ReflectionElement> getEnclosedElements() {
84 return ImmutableList.emptyList();
85 }
86
87 @Override
88 void finishDerivedFromElement(MirrorContext mirrorContext) {
89 bounds = mirrorContext.mirror(reflectionTypeVariable.getBounds());
90 ReflectionTypeMirror bound = bounds.size() == 1
91 ? bounds.get(0)
92 : new IntersectionTypeImpl(bounds);
93 typeVariable.setUpperAndLowerBounds(bound, NullTypeImpl.INSTANCE);
94 }
95 }