/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.process; import java.util.Arrays; import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import org.geotools.data.Parameter; import org.geotools.factory.FactoryCreator; import org.geotools.factory.FactoryFinder; import org.geotools.factory.FactoryRegistry; import org.geotools.resources.LazySet; import org.geotools.util.NullProgressListener; import org.opengis.feature.type.Name; /** * Factory and utility methods for {@link ProcessExecutor}, and {@link Process} * classes defined in this package. * <p> * Defines static methods used to access the application's default process factory implementations. * * @author gdavis * * * * @source $URL$ */ public class Processors extends FactoryFinder { /** * The service registry for this manager. Will be initialized only when first needed. */ private static FactoryRegistry registry; /** * Do not allow any instantiation of this class. */ private Processors() { // singleton } /** * Returns the service registry. The registry will be created the first * time this method is invoked. */ private static FactoryRegistry getServiceRegistry() { synchronized (Processors.class) { if (registry == null) { registry = new FactoryCreator(Arrays.asList(new Class<?>[]{ProcessFactory.class})); } } return registry; } /** * Dynamically register a new process factory into SPI * @param factory */ public static void addProcessFactory(ProcessFactory factory) { getServiceRegistry().registerServiceProvider(factory); } /** * Dynamically removes a process factory from SPI. Normally the factory has been * added before via {@link #addProcessFactory(ProcessFactory)} * @param factory */ public static void removeProcessFactory(ProcessFactory factory) { if(lastFactory == factory) { lastFactory = null; } getServiceRegistry().deregisterServiceProvider(factory); } /** * Set of available ProcessFactory; each of which is responsible for one or more processes. * * @return Set of ProcessFactory */ public static Set<ProcessFactory> getProcessFactories() { return new LazySet<ProcessFactory>(getServiceRegistry().getServiceProviders( ProcessFactory.class, null, null)); } /** Cache of last factory found */ static ProcessFactory lastFactory; /** * Look up a Factory by name of a process it supports. * * @param name Name of the Process you wish to work with * @return ProcessFactory capable of creating an instanceof the named process */ public static synchronized ProcessFactory createProcessFactory(Name name){ if( lastFactory != null && lastFactory.getNames().contains(name)){ return lastFactory; } for( ProcessFactory factory : getProcessFactories() ) { if(factory.getNames().contains(name)) { lastFactory = factory; return factory; } } return null; // go fish } /** * Look up an implementation of the named process on the classpath. * @param name Name of the Process to create * @return created process */ public static synchronized Process createProcess(Name name){ ProcessFactory factory = createProcessFactory( name ); if( factory == null ) return null; return factory.create(name); } /** * Look up an implementation of the named process on the classpath and describe the input * parameter required. * * @param name Name of the Process * @return Description of the parameters required */ public static synchronized Map<String, Parameter<?>> getParameterInfo(Name name){ ProcessFactory factory = createProcessFactory( name ); if( factory == null ) return null; return factory.getParameterInfo(name); } /** * Look up an implementation of the named process on the classpath and describe the expected * results. * <p> * Note the expected results are generated in part by the input parameters provided; this is to * allow for processes where the output is controlled by the parameters (such as choosing a * greyscale or color raster product; or choosing the version of GML produced etc...). * * @param name Name of the Process * @param parameters * @return Description of the parameters required */ public static synchronized Map<String, Parameter<?>> getResultInfo(Name name, Map<String, Object> parameters){ ProcessFactory factory = createProcessFactory( name ); if( factory == null ) return null; return factory.getResultInfo(name, parameters); } /** * Used to wrap a Process up as a Callable for use with an existing ExecutorService */ public static Callable<Map<String,Object>> createCallable( final Process process, final Map<String,Object> input ){ return new Callable<Map<String,Object>>(){ public Map<String, Object> call() throws Exception { return process.execute( input, new CallableProgressListener() ); } }; } public static ProcessExecutor newProcessExecutor( int nThreads, ThreadFactory threadFactory ){ if( threadFactory == null ) threadFactory = Executors.defaultThreadFactory(); return new ThreadPoolProcessExecutor( nThreads, threadFactory); } /** * This progress listener checks if the current Thread is interrupted, it * acts as a bridge between Future and ProgressListener code. * * @author Jody */ static class CallableProgressListener extends NullProgressListener { @Override public boolean isCanceled() { return Thread.currentThread().isInterrupted(); } } }