public Stream<Class<?>> streamCategories() { return registry.streamCategories(); }
/** * Scans for factory plug-ins on the application class path. This method is needed because the * application class path can theoretically change, or additional plug-ins may become available. * Rather than re-scanning the classpath on every invocation of the API, the class path is * scanned automatically only on the first invocation. Clients can call this method to prompt a * re-scan. Thus this method need only be invoked by sophisticated applications which * dynamically make new plug-ins available at runtime. */ public void scanForPlugins() { final Set<ClassLoader> loaders = getClassLoaders(); registry.streamCategories().forEach(category -> scanForPlugins(loaders, category)); }
/** * Returns an arbitrary instance that extends/implements the specified type that is filed under * a category that also extends/implements that type. * * @param type The type to look up. * @return An instance if one was found. */ public <S> Optional<S> getInstanceOfType(Class<S> type) { ensureArgumentNonNull("type", type); return streamCategories() .filter(category -> category.isAssignableFrom(type)) .map(this::instanceRegistry) .flatMap(registry -> stream(registry.getInstanceOfType(type))) .findFirst(); }
/** * Registers the specified instance under all categories that are supertypes of the instance. * * @param instance The instance to register. */ @SuppressWarnings("unchecked") public <T> void registerInstance(final T instance) { ensureArgumentNonNull("instance", instance); streamCategories() .filter(category -> category.isAssignableFrom(instance.getClass())) // the cast is correct because the filter above only leaves categories that are // supertypes of `instance` .map(category -> (InstanceRegistry<? super T>) instanceRegistry(category)) .forEach(registry -> registry.register(instance)); }
/** * Deregisters all instances with the same type as the specified one from all categories. * * @param instance The instance to deregister. */ @SuppressWarnings("unchecked") public <T> void deregisterInstance(final T instance) { ensureArgumentNonNull("instance", instance); streamCategories() .filter(category -> category.isAssignableFrom(instance.getClass())) // the cast is correct because the filter above only leaves categories that are // supertypes of `instance` .map(category -> (InstanceRegistry<? super T>) instanceRegistry(category)) .forEach(registry -> registry.deregister(instance)); }
registry.streamCategories() .filter(category -> !needScanForPlugins.contains(category)) .forEach(
/** * Sets or unsets a pairwise ordering between all factories meeting a criterion. * * <p>For example in the CRS framework ({@link org.geotools.referencing.FactoryFinder}), this is * used for setting ordering between all factories provided by two vendors, or for two * authorities. If one or both factories are not currently registered, or if the desired * ordering is already set/unset, nothing happens and false is returned. * * @param <T> The class represented by the {@code base} argument. * @param base The base category. Only categories {@linkplain Class#isAssignableFrom assignable} * to {@code base} will be processed. * @param set {@code true} for setting the ordering, or {@code false} for unsetting. * @param filter1 Predicate for the preferred factory. * @param filter2 Predicate for the factory to which {@code filter1} is preferred. * @return {@code true} if the ordering changed as a result of this call. */ public <T> boolean setOrdering( final Class<T> base, final boolean set, final Predicate<? super T> filter1, final Predicate<? super T> filter2) { ensureArgumentNonNull("filter1", filter1); ensureArgumentNonNull("filter2", filter2); return registry.streamCategories() .flatMap(category -> streamIfSubtype(category, base)) .map(category -> setOrUnsetOrdering(category, set, filter1, filter2)) .reduce((done1, done2) -> done1 || done2) .orElse(false); }