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 ? Utils.getDisplayString(qualifier) + " " : "")
132 + ReflectionUtils.getDisplayName(type);
133 }
134
135 @Override
136 public boolean equals(Object o) {
137 if (this == o) {
138 return true;
139 }
140 if (!(o instanceof Key<?>)) {
141 return false;
142 }
143 Key<?> that = (Key<?>) o;
144 return type.equals(that.type) && Objects.equals(qualifier, that.qualifier);
145 }
146
147 @Override
148 public int hashCode() {
149 int hashCode = hash;
150 if (hashCode == 0) {
151 hash = 31 * type.hashCode() + (qualifier == null ? 0 : qualifier.hashCode());
152 }
153 return hash;
154 }
155
156 @Override
157 public String toString() {
158 return (qualifier != null ? qualifier + " " : "") + type.getTypeName();
159 }
160 }