View Javadoc
1   package net.florianschoppmann.java.reflect;
2   
3   import javax.annotation.Nullable;
4   import javax.lang.model.type.TypeKind;
5   import javax.lang.model.type.TypeVariable;
6   import javax.lang.model.type.TypeVisitor;
7   import java.util.Objects;
8   
9   final class TypeVariableImpl extends AnnotatedConstructImpl implements ReflectionTypeMirror, TypeVariable {
10      private boolean frozen = false;
11  
12      private final TypeParameterElementImpl typeParameterElement;
13      @Nullable private final WildcardTypeImpl capturedTypeArgument;
14      @Nullable private ReflectionTypeMirror upperBound;
15      @Nullable private ReflectionTypeMirror lowerBound;
16  
17      TypeVariableImpl(TypeParameterElementImpl typeParameterElement, @Nullable WildcardTypeImpl capturedTypeArgument) {
18          Objects.requireNonNull(typeParameterElement);
19  
20          this.typeParameterElement = typeParameterElement;
21          this.capturedTypeArgument = capturedTypeArgument;
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          requireFrozen();
33          assert upperBound != null && lowerBound != null : "must be non-null when frozen";
34  
35          TypeVariableImpl other = (TypeVariableImpl) otherObject;
36          return typeParameterElement.equals(other.typeParameterElement)
37              && Objects.equals(capturedTypeArgument, other.capturedTypeArgument)
38              && upperBound.equals(other.upperBound)
39              && lowerBound.equals(other.lowerBound);
40      }
41  
42      @Override
43      public int hashCode() {
44          requireFrozen();
45  
46          return Objects.hash(typeParameterElement, capturedTypeArgument, upperBound, lowerBound);
47      }
48  
49      @Override
50      public <R, P> R accept(TypeVisitor<R, P> visitor, @Nullable P parameter) {
51          return visitor.visitTypeVariable(this, parameter);
52      }
53  
54      @Override
55      public String toString() {
56          return ReflectionTypes.getInstance().toString(this);
57      }
58  
59      void requireUnfrozen() {
60          if (frozen) {
61              throw new IllegalStateException(String.format(
62                  "Tried to modify instance of %s after it became effectively immutable.", getClass()
63              ));
64          }
65      }
66  
67      void requireFrozen() {
68          if (!frozen) {
69              throw new IllegalStateException(String.format(
70                  "Instance of %s used before object construction finished.", getClass()
71              ));
72          }
73      }
74  
75      @Override
76      public TypeParameterElementImpl asElement() {
77          return typeParameterElement;
78      }
79  
80      @Override
81      public ReflectionTypeMirror getUpperBound() {
82          requireFrozen();
83          assert upperBound != null : "must be non-null when frozen";
84          return upperBound;
85      }
86  
87      @Override
88      public ReflectionTypeMirror getLowerBound() {
89          requireFrozen();
90          assert lowerBound != null : "must be non-null when frozen";
91          return lowerBound;
92      }
93  
94      void setUpperAndLowerBounds(ReflectionTypeMirror newUpperBound, ReflectionTypeMirror newLowerBound) {
95          requireUnfrozen();
96          Objects.requireNonNull(newUpperBound);
97          Objects.requireNonNull(newLowerBound);
98  
99          upperBound = newUpperBound;
100         lowerBound = newLowerBound;
101         frozen = true;
102     }
103 
104     @Override
105     public TypeKind getKind() {
106         return TypeKind.TYPEVAR;
107     }
108 
109     @Nullable
110     WildcardTypeImpl getCapturedTypeArgument() {
111         return capturedTypeArgument;
112     }
113 }