/* * This file is part of Alida, a Java library for * Advanced Library for Integrated Development of Data Analysis Applications. * * Copyright (C) 2010 - @YEAR@ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Fore more information on Alida, visit * * http://www.informatik.uni-halle.de/alida/ * */ /* * Most recent change(s): * * $Rev: 4370 $ * $Date: 2011/11/20 20:18:51 $ * $Author: posch $ * */ package de.unihalle.informatik.Alida.batch; import de.unihalle.informatik.Alida.exceptions.ALDBatchIOManagerException; import de.unihalle.informatik.Alida.exceptions.ALDBatchIOManagerException.ALDBatchIOManagerExceptionType; import de.unihalle.informatik.Alida.annotations.ALDBatchOutputProvider; import de.unihalle.informatik.Alida.annotations.indexing.SezPozAdapter; import de.unihalle.informatik.Alida.batch.provider.output.ALDBatchOutputSummarizer; import java.util.HashMap; import java.util.Collection; import java.lang.reflect.Method; import net.java.sezpoz.Index; import net.java.sezpoz.IndexItem; /** * Class to manage data outputs in batch processing with operators. * * @author moeller */ public abstract class ALDBatchOutputManager { /** * For internal debugging purposes */ protected static boolean debug = false; /** * Name of the method which returns all classes supported. */ private static String providedOutputClassesMethodName = "providedClasses"; /** * Hashtable containing mappings of datatypes to provider classes. */ protected HashMap<Class<?>, String> mapTable = null; /** * Default constructor. */ protected ALDBatchOutputManager() { //nothing to do here to be overridden in extending classes } /** * Method to initialize the hashmap which registers batch output providers. * @param interfaceRequired Interface of which providers are registered. */ protected static HashMap<Class<?>, String> initMapTable( Class<?> interfaceRequired ) { HashMap<Class<?>, String> mapTable = new HashMap<Class<?>, String>(); // this a parallel map to mapTable, which represents the priority of the // provider class as defined by the annotation of the batch provider; // for use only during initialization of the mapTable HashMap<Class<?>, Integer> priorityMap = new HashMap<Class<?>, Integer>(); Index<ALDBatchOutputProvider,ALDBatchOutputSummarizer> indexItems = SezPozAdapter.load(ALDBatchOutputProvider.class, ALDBatchOutputSummarizer.class); for (final IndexItem<ALDBatchOutputProvider,ALDBatchOutputSummarizer> item : indexItems ) { // class name of provider String className = item.className(); // and its priority int priority = item.annotation().priority(); if ( debug ) System.out.println( "found: " + className); try { if (!interfaceRequired.isAssignableFrom( Class.forName( className))) { if ( debug ) System.out.println( " is not assignable from " + interfaceRequired); } else { Class<?> params[] = {}; Method method = Class.forName(className).getDeclaredMethod( providedOutputClassesMethodName, params); ALDBatchOutputSummarizer provider = (ALDBatchOutputSummarizer)(Class.forName( className).newInstance()); Object paramsObj[] = {}; @SuppressWarnings("unchecked") Collection<Class<?>> supportedClasses = (Collection<Class<?>>)(method.invoke( provider, paramsObj)); for ( Class<?> supportedClass : supportedClasses ) { if ( !(mapTable.containsKey( supportedClass)) || priority > priorityMap.get( supportedClass).intValue() ) { if ( debug ) System.out.println( " supported class (priority = " + priority + "):" + supportedClass.getName()); mapTable.put( supportedClass, className); priorityMap.put( supportedClass, new Integer(priority)); } } } } catch (Exception e) { System.err.println( "ALDBatchOutputManager::initMapTable cannot create an instance for " + className); } } return mapTable; } /** * Check if a provider has registered for the given class. * <p> * Note that this function does not try to instantiate a provider, thus, * just a flat check is done and on lateron requesting a provider object * errors are still possible. * @param cl Requested class. * @return True, if a provider has registered. */ public boolean providerAvailable(Class<?> cl) { if (this.mapTable.get(cl) != null) { return true; } return false; } /** * Method to return an instance of the batch output provider of the * requested class. * <p> * The provider is required to implement the requested interface * <code>interfaceRequired</code> (which by itself has to implement * {@link ALDBatchOutputSummarizer}). * * @param cl Class to get a provider for. * @param interfaceRequired Interface provider should implement. * @return Provider instance or null if no provider found. * @throws ALDBatchIOManagerException */ public ALDBatchOutputSummarizer getProvider( Class<?> cl, Class<?> interfaceRequired) throws ALDBatchIOManagerException { // first look up a provider name String providerName; providerName = this.mapTable.get(cl); // if ( providerName == null) { // // try other means to find a provider // // enum or ALDOperator or Collection or ALDParametrizedClass // if ( ! ( ( cl.getEnumConstants() != null && // (providerName = this.mapTable.get( Enum.class)) != null ) || // ( ALDOperator.class.isAssignableFrom( cl) && // (providerName = this.mapTable.get( ALDOperator.class)) != null ) || // ( Collection.class.isAssignableFrom( cl) && // (providerName = this.mapTable.get( Collection.class)) != null ) || // ( cl.getAnnotation( ALDParametrizedClass.class) != null && // (providerName = this.mapTable.get( ALDParametrizedClassDummy.class)) != null ) ) ) { // // nothing found // throw new ALDDataIOManagerException( // ALDDataIOManagerExceptionType.NO_PROVIDER_FOUND, // "ALDDataIOManager: no provider found for class " + cl.getName()); // } // } if (providerName == null) { return null; } // try to intantiate an instance of the provider try { Class<?> providerClass = Class.forName( providerName); Object providerObj = providerClass.newInstance(); // check if provider is of correct type if ( ! interfaceRequired.isAssignableFrom( providerClass ) ) { System.err.println("ALDBatchOutputManager::getProvider " + "ALDBatchOutputManager: Provider class does not implement " + interfaceRequired.getName() + " , invalid class!"); return null; } return (ALDBatchOutputSummarizer)providerObj; } catch (ClassNotFoundException e) { throw new ALDBatchIOManagerException( ALDBatchIOManagerExceptionType.PROVIDER_INSTANTIATION_ERROR, "ALDBatchOutputManager: " + "Provider class not found, instantiation failed!"); } catch (InstantiationException e) { throw new ALDBatchIOManagerException( ALDBatchIOManagerExceptionType.PROVIDER_INSTANTIATION_ERROR, "ALDBatchOutputManager: Provider instantiation failed!"); } catch (IllegalAccessException e) { throw new ALDBatchIOManagerException( ALDBatchIOManagerExceptionType.UNSPECIFIED_ERROR, "ALDBatchOutputManager: Illegal access noticed!"); } } }