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