1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  package org.apache.maven.di;
20  
21  import java.lang.reflect.ParameterizedType;
22  import java.lang.reflect.Type;
23  import java.util.Objects;
24  
25  import org.apache.maven.api.annotations.Nullable;
26  import org.apache.maven.di.impl.ReflectionUtils;
27  import org.apache.maven.di.impl.Types;
28  import org.apache.maven.di.impl.Utils;
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  public abstract class Key<T> {
46      private final Type type;
47      private final @Nullable Object qualifier;
48  
49      private int hash;
50  
51      protected Key() {
52          this(null);
53      }
54  
55      protected Key(@Nullable Object qualifier) {
56          this.type = Types.simplifyType(getTypeParameter());
57          this.qualifier = qualifier;
58      }
59  
60      protected Key(Type type, @Nullable Object qualifier) {
61          this.type = Types.simplifyType(type);
62          this.qualifier = qualifier;
63      }
64  
65      static final class KeyImpl<T> extends Key<T> {
66          KeyImpl(Type type, Object qualifier) {
67              super(type, qualifier);
68          }
69      }
70  
71      public static <T> Key<T> of(Class<T> type) {
72          return new KeyImpl<>(type, null);
73      }
74  
75      public static <T> Key<T> of(Class<T> type, @Nullable Object qualifier) {
76          return new KeyImpl<>(type, qualifier);
77      }
78  
79      public static <T> Key<T> ofType(Type type) {
80          return new KeyImpl<>(type, null);
81      }
82  
83      public static <T> Key<T> ofType(Type type, @Nullable Object qualifier) {
84          return new KeyImpl<>(type, qualifier);
85      }
86  
87      private Type getTypeParameter() {
88          
89          Type typeArgument = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
90          Object outerInstance = ReflectionUtils.getOuterClassInstance(this);
91          
92          return outerInstance != null
93                  ? Types.bind(typeArgument, Types.getAllTypeBindings(outerInstance.getClass()))
94                  : typeArgument;
95      }
96  
97      public Type getType() {
98          return type;
99      }
100 
101     
102 
103 
104 
105     @SuppressWarnings("unchecked")
106     public Class<T> getRawType() {
107         return (Class<T>) Types.getRawType(type);
108     }
109 
110     
111 
112 
113 
114 
115     public <U> Key<U> getTypeParameter(int index) {
116         if (type instanceof ParameterizedType) {
117             return new KeyImpl<>(((ParameterizedType) type).getActualTypeArguments()[index], null);
118         }
119         throw new IllegalStateException("Expected type from key " + getDisplayString() + " to be parameterized");
120     }
121 
122     public @Nullable Object getQualifier() {
123         return qualifier;
124     }
125 
126     
127 
128 
129 
130     public String getDisplayString() {
131         return (qualifier != null ? getQualifierDisplayString() + " " : "") + ReflectionUtils.getDisplayName(type);
132     }
133 
134     private String getQualifierDisplayString() {
135         if (qualifier instanceof String s) {
136             return s.isEmpty() ? "@Named" : "@Named(\"" + s + "\")";
137         }
138         String s = Utils.getDisplayString(qualifier);
139         return s;
140     }
141 
142     @Override
143     public boolean equals(Object o) {
144         if (this == o) {
145             return true;
146         }
147         if (!(o instanceof Key<?>)) {
148             return false;
149         }
150         Key<?> that = (Key<?>) o;
151         return type.equals(that.type) && Objects.equals(qualifier, that.qualifier);
152     }
153 
154     @Override
155     public int hashCode() {
156         int hashCode = hash;
157         if (hashCode == 0) {
158             hash = 31 * type.hashCode() + (qualifier == null ? 0 : qualifier.hashCode());
159         }
160         return hash;
161     }
162 
163     @Override
164     public String toString() {
165         return getDisplayString();
166     }
167 }