1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.websocket.jsr356.metadata;
20
21 import java.util.ArrayList;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.concurrent.ConcurrentHashMap;
26
27
28
29
30
31
32
33
34
35
36
37 public abstract class CoderMetadataSet<T, M extends CoderMetadata<T>> implements Iterable<M>
38 {
39
40
41
42 private final List<M> metadatas;
43
44
45
46 private final List<Class<? extends T>> coders;
47
48
49
50 private final Map<Class<?>, Integer> typeMap;
51
52
53
54 private final Map<Class<? extends T>, List<Integer>> implMap;
55
56 protected CoderMetadataSet()
57 {
58 metadatas = new ArrayList<>();
59 coders = new ArrayList<>();
60 typeMap = new ConcurrentHashMap<>();
61 implMap = new ConcurrentHashMap<>();
62 }
63
64 public void add(Class<? extends T> coder)
65 {
66 List<M> metadatas = discover(coder);
67 trackMetadata(metadatas);
68 }
69
70 public List<M> addAll(Class<? extends T>[] coders)
71 {
72 List<M> metadatas = new ArrayList<>();
73
74 for (Class<? extends T> coder : coders)
75 {
76 metadatas.addAll(discover(coder));
77 }
78
79 trackMetadata(metadatas);
80 return metadatas;
81 }
82
83 public List<M> addAll(List<Class<? extends T>> coders)
84 {
85 List<M> metadatas = new ArrayList<>();
86
87 for (Class<? extends T> coder : coders)
88 {
89 metadatas.addAll(discover(coder));
90 }
91
92 trackMetadata(metadatas);
93 return metadatas;
94 }
95
96
97
98
99
100
101
102
103
104
105
106 protected abstract List<M> discover(Class<? extends T> coder);
107
108 public Class<? extends T> getCoder(Class<?> type)
109 {
110 M metadata = getMetadataByType(type);
111 if (metadata == null)
112 {
113 return null;
114 }
115 return metadata.getCoderClass();
116 }
117
118 public List<Class<? extends T>> getList()
119 {
120 return coders;
121 }
122
123 public List<M> getMetadataByImplementation(Class<? extends T> clazz)
124 {
125 List<Integer> indexes = implMap.get(clazz);
126 if (indexes == null)
127 {
128 return null;
129 }
130 List<M> ret = new ArrayList<>();
131 for (Integer idx : indexes)
132 {
133 ret.add(metadatas.get(idx));
134 }
135 return ret;
136 }
137
138 public M getMetadataByType(Class<?> type)
139 {
140 Integer idx = typeMap.get(type);
141 if (idx == null)
142 {
143
144 idx = getMetadataByAssignableType(type);
145 if (idx != null)
146 {
147
148 typeMap.put(type,idx);
149 }
150 }
151
152
153 if (idx == null)
154 {
155 return null;
156 }
157 return metadatas.get(idx);
158 }
159
160 private Integer getMetadataByAssignableType(Class<?> type)
161 {
162 for (Map.Entry<Class<?>, Integer> entry : typeMap.entrySet())
163 {
164 if (entry.getKey().isAssignableFrom(type))
165 {
166 return entry.getValue();
167 }
168 }
169
170 return null;
171 }
172
173 @Override
174 public Iterator<M> iterator()
175 {
176 return metadatas.iterator();
177 }
178
179 @Override
180 public String toString()
181 {
182 StringBuilder builder = new StringBuilder();
183 builder.append(this.getClass().getSimpleName());
184 builder.append("[metadatas=");
185 builder.append(metadatas.size());
186 builder.append(",coders=");
187 builder.append(coders.size());
188 builder.append("]");
189 return builder.toString();
190 }
191
192 protected void trackMetadata(List<M> metadatas)
193 {
194 for (M metadata : metadatas)
195 {
196 trackMetadata(metadata);
197 }
198 }
199
200 protected void trackMetadata(M metadata)
201 {
202 synchronized (metadatas)
203 {
204
205 boolean duplicate = false;
206
207
208 if (metadatas.contains(metadata))
209 {
210 duplicate = true;
211 }
212
213
214 Class<?> type = metadata.getObjectType();
215 if (typeMap.containsKey(type))
216 {
217 duplicate = true;
218 }
219
220 if (duplicate)
221 {
222 StringBuilder err = new StringBuilder();
223 err.append("Duplicate decoder for type: ");
224 err.append(type);
225 err.append(" (class ").append(metadata.getCoderClass().getName());
226
227
228 M dup = getMetadataByType(type);
229 err.append(" duplicates ");
230 err.append(dup.getCoderClass().getName());
231 err.append(")");
232 throw new IllegalStateException(err.toString());
233 }
234
235
236 Class<? extends T> coderClass = metadata.getCoderClass();
237 int newidx = metadatas.size();
238 metadatas.add(metadata);
239 coders.add(coderClass);
240 typeMap.put(type,newidx);
241
242 List<Integer> indexes = implMap.get(coderClass);
243 if (indexes == null)
244 {
245 indexes = new ArrayList<>();
246 }
247 if (indexes.contains(newidx))
248 {
249
250 }
251 indexes.add(newidx);
252 implMap.put(coderClass,indexes);
253 }
254 }
255 }