/* * 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$ * $Date$ * $Author$ * */ package de.unihalle.informatik.Alida.helpers; import de.unihalle.informatik.Alida.annotations.ALDAOperator; import de.unihalle.informatik.Alida.annotations.ALDDerivedClass; import de.unihalle.informatik.Alida.annotations.ALDAOperator.Level; import de.unihalle.informatik.Alida.annotations.indexing.SezPozAdapter; import de.unihalle.informatik.Alida.operator.ALDOperator; import de.unihalle.informatik.Alida.operator.ALDOperatorLocation; import java.io.IOException; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; import net.java.sezpoz.Index; import net.java.sezpoz.IndexItem; /** * Supplies helper methods to, e.g., lookup classes with annotations. * * @author posch */ /** * @author posch * */ public class ALDClassInfo { /** * Debug flag for internal usage only. */ private static boolean debug = false; /** * Collects all derived class of given class. * <p> * The method searches for all derived classes of the given class * among all classes annotated with @ALDDerivedClass that are found * in the classpath. In this context derived classes are classes which * either implement the specified interface or extend the given class. * * @param cl Class for which derived classes are requested. * @return Set of extending classes including class itself. */ @SuppressWarnings({ "rawtypes", "unchecked" }) public static Set<Class> lookupExtendingClasses( Class cl) { // init result list HashSet<Class> extendingClasses = new HashSet<Class>(); if ( debug ) System.out.println("ALDDataIOManager::lookupExtendingClasses class "+cl); // run through all classes annotated as Alida derived class Index<ALDDerivedClass,Object> indexItems = SezPozAdapter.load(ALDDerivedClass.class, Object.class); for( final IndexItem<ALDDerivedClass,Object> item : indexItems) { if ( debug ) { System.out.println( "ALDDataIOManager::lookupExtendingClasses looking up <"+ item.className() + ">"); } try { if ( cl.isAssignableFrom( Class.forName( item.className())) ) { extendingClasses.add( Class.forName( item.className())); if ( debug ) System.out.println("ALDDataIOManager::lookupExtendingClasses found " + item.className()); } } catch (Exception e) { //e.printStackTrace(); } } for ( String opPackes : getOperatorSearchPaths()) { try { for ( Class<?> clazz : SubclassFinder.findInstantiableSubclasses(cl, opPackes) ) { extendingClasses.add( clazz); if ( debug ) System.out.println("ALDDataIOManager::lookupExtendingClasses found via package " + clazz.getName()); } } catch (ClassNotFoundException e) { } catch (IOException e) { } } return extendingClasses; } /** * Collects all ALDOperators annotated with the requested level and execution mode * and all ALDOperators found in a package specified by a JVM property alida_oprunner_favoriteops or * the environment variable ALIDA_OPRUNNER_OPERATORPATH as a colon separated list of package names. * <p> * If <code>level</code> is <code>Level.APPLICATION</code> then * only operators with this level will be return. * If <code>level</code> is <code>Level.STANDARD</code> all operator levels are accepted. * * @param level Class for which derived classes are requested. * @return List of operator names with requested level and execution mode */ public static Collection<ALDOperatorLocation> lookupOperators( ALDAOperator.Level level, ALDAOperator.ExecutionMode executionMode) { // init result list LinkedList<ALDOperatorLocation> allClasses = new LinkedList<ALDOperatorLocation>(); if ( debug ) System.out.println("ALDDataIOManager::lookupOperators class, level = " + level + ", execution mode = " + executionMode); for ( String classname : lookupOperatorClassnames( level, executionMode)) { allClasses.add( ALDOperatorLocation.createClassLocation( classname)); if ( debug ) System.out.println("ALDDataIOManager::lookupOperators found " + classname); } return allClasses; } /** * Collects all ALDOperators annotated with the requested level and execution mode * and all ALDOperators found in a package specified by a JVM property alida_oprunner_favoriteops or * the environment variable ALIDA_OPRUNNER_OPERATORPATH as a colon separated list of package names. * <p> * If <code>level</code> is <code>Level.APPLICATION</code> then * only operators with this level will be return. * If <code>level</code> is <code>Level.STANDARD</code> all operator levels are accepted. * @param level * @param executionMode * @return Set of operator names. */ public static Set<String> lookupOperatorClassnames( ALDAOperator.Level level, ALDAOperator.ExecutionMode executionMode) { HashSet<String> opClassnames = new HashSet<String>(); if ( debug ) System.out.println("ALDDataIOManager::lookupOperatorClassnames class, level = " + level + ", execution mode = " + executionMode); // first find all annotated ALDOperators Index<ALDAOperator, ALDOperator> indexItems = SezPozAdapter.load( ALDAOperator.class, ALDOperator.class); for (final IndexItem<ALDAOperator, ALDOperator> item : indexItems) { try { if ( (item.annotation().genericExecutionMode() == ALDAOperator.ExecutionMode.ALL || item.annotation().genericExecutionMode() == executionMode) && (level != Level.APPLICATION || item.annotation().level() == level) ) { opClassnames.add( item.className()); if ( debug ) System.out.println("ALDDataIOManager::lookupOperatorClassnames found " + item.className()); } } catch (Exception e) { e.printStackTrace(); } } // now add classes found as class files for ( String opPackage : getOperatorSearchPaths()) { try { for ( Class<?> clazz : SubclassFinder.findInstantiableSubclasses(ALDOperator.class, opPackage) ) { opClassnames.add( clazz.getName()); if ( debug ) System.out.println("ALDDataIOManager::lookupOperatorClassnames found via package " + clazz.getName()); } } catch (ClassNotFoundException e) { } catch (IOException e) { } } return opClassnames; } private static Collection<String> getOperatorSearchPaths() { LinkedList<String> pathes = new LinkedList<String>(); String operatorPath = ALDEnvironmentConfig.getConfigValue( "OPRUNNER", "OPERATORPATH"); if ( operatorPath != null ) { String[] pathesArray = operatorPath.split(":"); for ( int i = 0 ; i < pathesArray.length ; i++) { pathes.add( pathesArray[i]); } } return new LinkedList<String>( pathes); } }