|
33 | 33 | package org.scijava.plugin;
|
34 | 34 |
|
35 | 35 | import java.net.URL;
|
| 36 | +import java.util.Collection; |
| 37 | +import java.util.Optional; |
36 | 38 |
|
37 | 39 | import org.scijava.AbstractUIDetails;
|
38 | 40 | import org.scijava.Identifiable;
|
|
45 | 47 | import org.scijava.UIDetails;
|
46 | 48 | import org.scijava.Versioned;
|
47 | 49 | import org.scijava.input.Accelerator;
|
48 |
| -import org.scijava.util.ClassUtils; |
49 | 50 | import org.scijava.util.StringMaker;
|
50 | 51 | import org.scijava.util.Types;
|
51 | 52 | import org.scijava.util.VersionUtils;
|
@@ -352,6 +353,143 @@ public String getVersion() {
|
352 | 353 | }
|
353 | 354 | }
|
354 | 355 |
|
| 356 | + // -- Utility methods -- |
| 357 | + |
| 358 | + /** |
| 359 | + * Finds a {@link PluginInfo} of the given plugin class in the specified |
| 360 | + * {@link PluginIndex}. <em>Note that to avoid loading plugin classes, class |
| 361 | + * identity is determined by class name equality only.</em> |
| 362 | + * |
| 363 | + * @param pluginClass The concrete class of the plugin whose |
| 364 | + * {@link PluginInfo} is desired. |
| 365 | + * @param pluginIndex The {@link PluginIndex} to search for a matching |
| 366 | + * {@link PluginInfo}. |
| 367 | + * @return The matching {@link PluginInfo}, or null if none found. |
| 368 | + */ |
| 369 | + @SuppressWarnings({ "rawtypes", "unchecked" }) |
| 370 | + public static <P extends SciJavaPlugin> PluginInfo<?> get( |
| 371 | + final Class<P> pluginClass, final PluginIndex pluginIndex) |
| 372 | + { |
| 373 | + return get(pluginClass, (Collection) pluginIndex.getAll()); |
| 374 | + } |
| 375 | + |
| 376 | + /** |
| 377 | + * Finds a {@link PluginInfo} of the given plugin class and plugin type in the |
| 378 | + * specified {@link PluginIndex}. <em>Note that to avoid loading plugin |
| 379 | + * classes, class identity is determined by class name equality only.</em> |
| 380 | + * |
| 381 | + * @param pluginClass The concrete class of the plugin whose |
| 382 | + * {@link PluginInfo} is desired. |
| 383 | + * @param pluginType The type of the plugin; see {@link #getPluginType()}. |
| 384 | + * @param pluginIndex The {@link PluginIndex} to search for a matching |
| 385 | + * {@link PluginInfo}. |
| 386 | + * @return The matching {@link PluginInfo}, or null if none found. |
| 387 | + */ |
| 388 | + public static <P extends PT, PT extends SciJavaPlugin> PluginInfo<PT> get( |
| 389 | + final Class<P> pluginClass, final Class<PT> pluginType, |
| 390 | + final PluginIndex pluginIndex) |
| 391 | + { |
| 392 | + return get(pluginClass, pluginIndex.getPlugins(pluginType)); |
| 393 | + } |
| 394 | + |
| 395 | + /** |
| 396 | + * Finds a {@link PluginInfo} of the given plugin class in the specified list |
| 397 | + * of plugins. <em>Note that to avoid loading plugin classes, class identity |
| 398 | + * is determined by class name equality only.</em> |
| 399 | + * |
| 400 | + * @param pluginClass The concrete class of the plugin whose |
| 401 | + * {@link PluginInfo} is desired. |
| 402 | + * @param plugins The list of plugins to search for a match. |
| 403 | + * @return The matching {@link PluginInfo}, or null if none found. |
| 404 | + */ |
| 405 | + public static <P extends PT, PT extends SciJavaPlugin> PluginInfo<PT> get( |
| 406 | + final Class<P> pluginClass, |
| 407 | + final Collection<? extends PluginInfo<PT>> plugins) |
| 408 | + { |
| 409 | + final String className = pluginClass.getName(); |
| 410 | + final Optional<? extends PluginInfo<PT>> result = plugins.stream() // |
| 411 | + .filter(info -> info.getClassName().equals(className)) // |
| 412 | + .findFirst(); |
| 413 | + return result.isPresent() ? result.get() : null; |
| 414 | + } |
| 415 | + |
| 416 | + /** |
| 417 | + * Creates a {@link PluginInfo} for the given plugin class. The class must be |
| 418 | + * a concrete class annotated with the @{@link Plugin} annotation, from which |
| 419 | + * the plugin type will be inferred. |
| 420 | + * |
| 421 | + * @param pluginClass The concrete class of the plugin for which a new |
| 422 | + * {@link PluginInfo} is desired. |
| 423 | + * @return A newly created {@link PluginInfo} for the given plugin class. |
| 424 | + * @throws IllegalArgumentException if the given class is not annotated |
| 425 | + * with @{@link Plugin}, or its annotated {@link Plugin#type() |
| 426 | + * type()} is not a supertype of the plugin class. |
| 427 | + */ |
| 428 | + public static PluginInfo<?> create( |
| 429 | + final Class<? extends SciJavaPlugin> pluginClass) |
| 430 | + { |
| 431 | + @SuppressWarnings({ "rawtypes", "unchecked" }) |
| 432 | + final PluginInfo<?> info = new PluginInfo(pluginClass, // |
| 433 | + pluginType(pluginClass)); |
| 434 | + return info; |
| 435 | + } |
| 436 | + |
| 437 | + /** |
| 438 | + * Creates a {@link PluginInfo} for the given plugin class of the specified |
| 439 | + * plugin type. |
| 440 | + * |
| 441 | + * @param pluginClass The concrete class of the plugin for which a new |
| 442 | + * {@link PluginInfo} is desired. |
| 443 | + * @param pluginType The type of the plugin; see {@link #getPluginType()}. |
| 444 | + * @return A newly created {@link PluginInfo} for the given plugin class. |
| 445 | + */ |
| 446 | + public static <P extends PT, PT extends SciJavaPlugin> PluginInfo<PT> create( |
| 447 | + final Class<P> pluginClass, final Class<PT> pluginType) |
| 448 | + { |
| 449 | + return new PluginInfo<>(pluginClass, pluginType); |
| 450 | + } |
| 451 | + |
| 452 | + /** |
| 453 | + * Obtains a {@link PluginInfo} for the given plugin class. If one already |
| 454 | + * exists in the specified {@link PluginIndex}, it is retrieved (see |
| 455 | + * {@link #get(Class, PluginIndex)}); otherwise, a new one is created (see |
| 456 | + * {@link #create(Class)}) but not added to the index. |
| 457 | + * |
| 458 | + * @param pluginClass The concrete class of the plugin whose |
| 459 | + * {@link PluginInfo} is desired. |
| 460 | + * @param pluginIndex The {@link PluginIndex} to search for a matching |
| 461 | + * {@link PluginInfo}. |
| 462 | + * @throws IllegalArgumentException when creating a new {@link PluginInfo} if |
| 463 | + * the associated plugin type cannot be inferred; see |
| 464 | + * {@link #create(Class)}. |
| 465 | + */ |
| 466 | + public static <P extends SciJavaPlugin> PluginInfo<?> getOrCreate( |
| 467 | + final Class<P> pluginClass, final PluginIndex pluginIndex) |
| 468 | + { |
| 469 | + final PluginInfo<?> existing = get(pluginClass, pluginIndex); |
| 470 | + return existing == null ? create(pluginClass) : existing; |
| 471 | + } |
| 472 | + |
| 473 | + /** |
| 474 | + * Obtains a {@link PluginInfo} for the given plugin class. If one already |
| 475 | + * exists in the specified {@link PluginIndex}, it is retrieved (see |
| 476 | + * {@link #get(Class, PluginIndex)}); otherwise, a new one is created (see |
| 477 | + * {@link #create(Class)}) but not added to the index. |
| 478 | + * |
| 479 | + * @param pluginClass The concrete class of the plugin whose |
| 480 | + * {@link PluginInfo} is desired. |
| 481 | + * @param pluginType The type of the plugin; see {@link #getPluginType()}. |
| 482 | + * @param pluginIndex The {@link PluginIndex} to search for a matching |
| 483 | + * {@link PluginInfo}. |
| 484 | + */ |
| 485 | + public static <P extends PT, PT extends SciJavaPlugin> PluginInfo<PT> |
| 486 | + getOrCreate(final Class<P> pluginClass, final Class<PT> pluginType, |
| 487 | + final PluginIndex pluginIndex) |
| 488 | + { |
| 489 | + final PluginInfo<PT> existing = get(pluginClass, pluginType, pluginIndex); |
| 490 | + return existing == null ? create(pluginClass, pluginType) : existing; |
| 491 | + } |
| 492 | + |
355 | 493 | // -- Helper methods --
|
356 | 494 |
|
357 | 495 | /** Populates the entry to match the associated @{@link Plugin} annotation. */
|
@@ -413,4 +551,23 @@ private MenuPath parseMenuPath(final Menu[] menu) {
|
413 | 551 | return menuPath;
|
414 | 552 | }
|
415 | 553 |
|
| 554 | + /** Extracts the plugin type from a class's @{@link Plugin} annotation. */ |
| 555 | + private static <P extends SciJavaPlugin> Class<? super P> pluginType( |
| 556 | + final Class<P> pluginClass) |
| 557 | + { |
| 558 | + final Plugin annotation = pluginClass.getAnnotation(Plugin.class); |
| 559 | + if (annotation == null) { |
| 560 | + throw new IllegalArgumentException( |
| 561 | + "Cannot infer plugin type from class '" + pluginClass.getName() + |
| 562 | + "' with no @Plugin annotation."); |
| 563 | + } |
| 564 | + final Class<?> type = annotation.type(); |
| 565 | + if (!type.isAssignableFrom(pluginClass)) { |
| 566 | + throw new IllegalArgumentException("Invalid plugin type '" + // |
| 567 | + type.getName() + "' for class '" + pluginClass.getName() + "'"); |
| 568 | + } |
| 569 | + @SuppressWarnings("unchecked") |
| 570 | + final Class<? super P> pluginType = (Class<? super P>) type; |
| 571 | + return pluginType; |
| 572 | + } |
416 | 573 | }
|
0 commit comments