|
31 | 31 |
|
32 | 32 | package org.scijava.object;
|
33 | 33 |
|
| 34 | +import java.lang.reflect.Method; |
| 35 | +import java.lang.reflect.ParameterizedType; |
| 36 | +import java.lang.reflect.Type; |
34 | 37 | import java.util.ArrayList;
|
35 | 38 | import java.util.Collection;
|
36 | 39 | import java.util.Collections;
|
|
45 | 48 | import java.util.concurrent.ConcurrentHashMap;
|
46 | 49 |
|
47 | 50 | import org.scijava.util.ClassUtils;
|
| 51 | +import org.scijava.util.ConversionUtils; |
48 | 52 |
|
49 | 53 | /**
|
50 | 54 | * Data structure for managing lists of registered objects.
|
@@ -129,7 +133,7 @@ public List<E> getAll() {
|
129 | 133 | */
|
130 | 134 | public List<E> get(final Class<?> type) {
|
131 | 135 | // lazily register any pending objects
|
132 |
| - if (!pending.isEmpty()) resolvePending(); |
| 136 | + if (!pending.isEmpty()) resolvePending(type); |
133 | 137 |
|
134 | 138 | List<E> list = retrieveList(type);
|
135 | 139 | // NB: Return a copy of the data, to facilitate thread safety.
|
@@ -380,15 +384,51 @@ protected List<E> retrieveList(final Class<?> type) {
|
380 | 384 | return list;
|
381 | 385 | }
|
382 | 386 |
|
383 |
| - private void resolvePending() { |
| 387 | + private void resolvePending(final Class<?> type) { |
384 | 388 | synchronized (pending) {
|
385 |
| - while (!pending.isEmpty()) { |
386 |
| - final LazyObjects<? extends E> c = pending.remove(0); |
| 389 | + for (int p = pending.size() - 1; p >= 0; p--) { |
| 390 | + final LazyObjects<? extends E> c = pending.get(p); |
| 391 | + |
| 392 | + // NB: If this pending callback returns objects of a different |
| 393 | + // type than the one we are interested in, it can be skipped. |
| 394 | + if (!isCompatibleType(c, type)) continue; |
| 395 | + |
| 396 | + // trigger the callback and add the results |
| 397 | + pending.remove(p); |
387 | 398 | addAll(c.get());
|
388 | 399 | }
|
389 | 400 | }
|
390 | 401 | }
|
391 | 402 |
|
| 403 | + // -- Helper methods -- |
| 404 | + |
| 405 | + private boolean isCompatibleType(final LazyObjects<? extends E> c, |
| 406 | + final Class<?> type) |
| 407 | + { |
| 408 | + if (type == All.class) return true; |
| 409 | + |
| 410 | + // extract the generic type from the LazyObjects#get return type |
| 411 | + final Method getMethod; |
| 412 | + try { |
| 413 | + getMethod = c.getClass().getMethod("get"); |
| 414 | + } |
| 415 | + catch (final NoSuchMethodException exc) { |
| 416 | + throw new IllegalStateException(exc); |
| 417 | + } |
| 418 | + final Type returnType = getMethod.getGenericReturnType(); |
| 419 | + if (returnType instanceof ParameterizedType) { |
| 420 | + final ParameterizedType pType = (ParameterizedType) returnType; |
| 421 | + final Type[] typeArgs = pType.getActualTypeArguments(); |
| 422 | + if (typeArgs.length > 0 && |
| 423 | + !type.isAssignableFrom(ConversionUtils.getClass(typeArgs[0]))) |
| 424 | + { |
| 425 | + return false; |
| 426 | + } |
| 427 | + } |
| 428 | + |
| 429 | + return true; |
| 430 | + } |
| 431 | + |
392 | 432 | // -- Helper classes --
|
393 | 433 |
|
394 | 434 | private static class All {
|
|
0 commit comments