2009-03-18 07:22:37 +08:00
|
|
|
package org.broadinstitute.sting.gatk;
|
|
|
|
|
|
2009-03-19 01:32:24 +08:00
|
|
|
import net.sf.functionalj.reflect.StdReflect;
|
|
|
|
|
import net.sf.functionalj.reflect.JdkStdReflect;
|
|
|
|
|
import net.sf.functionalj.FunctionN;
|
|
|
|
|
import net.sf.functionalj.Functions;
|
|
|
|
|
|
2009-03-18 07:22:37 +08:00
|
|
|
import java.io.File;
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
2009-05-20 07:26:17 +08:00
|
|
|
import java.util.Arrays;
|
2009-03-18 07:22:37 +08:00
|
|
|
|
|
|
|
|
import org.broadinstitute.sting.gatk.walkers.Walker;
|
2009-03-27 04:45:27 +08:00
|
|
|
import org.broadinstitute.sting.gatk.walkers.WalkerName;
|
2009-05-16 05:02:12 +08:00
|
|
|
import org.broadinstitute.sting.gatk.walkers.DataSource;
|
|
|
|
|
import org.broadinstitute.sting.gatk.walkers.By;
|
2009-05-20 07:26:17 +08:00
|
|
|
import org.broadinstitute.sting.gatk.walkers.Allows;
|
|
|
|
|
import org.broadinstitute.sting.gatk.walkers.Requires;
|
|
|
|
|
import org.broadinstitute.sting.gatk.walkers.RMD;
|
|
|
|
|
import org.broadinstitute.sting.gatk.refdata.ReferenceOrderedDatum;
|
|
|
|
|
import org.broadinstitute.sting.gatk.refdata.ReferenceOrderedData;
|
2009-03-31 07:20:55 +08:00
|
|
|
import org.broadinstitute.sting.utils.JVMUtils;
|
|
|
|
|
import org.broadinstitute.sting.utils.PathUtils;
|
2009-05-16 05:02:12 +08:00
|
|
|
import org.broadinstitute.sting.utils.StingException;
|
2009-03-27 21:27:04 +08:00
|
|
|
import org.apache.log4j.Logger;
|
2009-03-18 07:22:37 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Created by IntelliJ IDEA.
|
|
|
|
|
* User: hanna
|
|
|
|
|
* Date: Mar 17, 2009
|
|
|
|
|
* Time: 3:14:28 PM
|
|
|
|
|
* To change this template use File | Settings | File Templates.
|
|
|
|
|
*/
|
|
|
|
|
public class WalkerManager {
|
|
|
|
|
|
2009-03-27 21:27:04 +08:00
|
|
|
/**
|
|
|
|
|
* our log, which we want to capture anything from this class
|
|
|
|
|
*/
|
|
|
|
|
private static Logger logger = Logger.getLogger(WalkerManager.class);
|
|
|
|
|
|
|
|
|
|
private Map<String, Class> walkers;
|
|
|
|
|
|
|
|
|
|
public WalkerManager(String pluginDirectory) {
|
2009-03-18 07:22:37 +08:00
|
|
|
try {
|
2009-03-27 04:45:27 +08:00
|
|
|
List<Class> walkerCandidates = new ArrayList<Class>();
|
2009-03-19 01:32:24 +08:00
|
|
|
|
2009-03-20 06:12:25 +08:00
|
|
|
// Load all classes that live in this jar.
|
2009-03-31 07:20:55 +08:00
|
|
|
final File location = JVMUtils.getLocationFor( getClass() );
|
2009-03-27 21:27:04 +08:00
|
|
|
walkerCandidates.addAll(loadClassesFromLocation(location));
|
2009-03-19 01:32:24 +08:00
|
|
|
|
2009-03-20 06:12:25 +08:00
|
|
|
// Load all classes that live in the extension path.
|
2009-03-27 21:27:04 +08:00
|
|
|
if (pluginDirectory == null)
|
2009-03-24 11:56:49 +08:00
|
|
|
pluginDirectory = location.getParent() + File.separator + "walkers";
|
2009-03-27 21:27:04 +08:00
|
|
|
logger.info("plugin directory: " + pluginDirectory);
|
2009-03-24 11:56:49 +08:00
|
|
|
|
2009-03-27 21:27:04 +08:00
|
|
|
File extensionPath = new File(pluginDirectory);
|
|
|
|
|
if (extensionPath.exists()) {
|
2009-03-31 07:20:55 +08:00
|
|
|
List<String> classFilesInPath = PathUtils.findFilesInPath(extensionPath, "", "class", false);
|
|
|
|
|
walkerCandidates.addAll(JVMUtils.loadExternalClasses(extensionPath, classFilesInPath));
|
|
|
|
|
List<String> jarsInPath = PathUtils.findFilesInPath(extensionPath, "", "jar", false);
|
|
|
|
|
for( String jarFileName: jarsInPath ) {
|
|
|
|
|
File jarFile = new File( extensionPath, jarFileName );
|
|
|
|
|
walkerCandidates.addAll(JVMUtils.loadExternalClassesFromJar(jarFile) );
|
|
|
|
|
}
|
2009-03-24 11:56:49 +08:00
|
|
|
}
|
2009-03-19 01:32:24 +08:00
|
|
|
|
2009-03-27 04:45:27 +08:00
|
|
|
walkerCandidates = filterWalkers(walkerCandidates);
|
2009-03-18 07:22:37 +08:00
|
|
|
|
2009-03-27 21:27:04 +08:00
|
|
|
if (walkerCandidates.isEmpty())
|
|
|
|
|
throw new RuntimeException("No walkers were found.");
|
2009-03-18 07:22:37 +08:00
|
|
|
|
2009-03-27 21:27:04 +08:00
|
|
|
walkers = createWalkerDatabase(walkerCandidates);
|
2009-03-18 07:22:37 +08:00
|
|
|
}
|
|
|
|
|
// IOExceptions here are suspect; they indicate that the WalkerManager can't open its containing jar.
|
|
|
|
|
// Wrap in a RuntimeException.
|
2009-03-27 21:27:04 +08:00
|
|
|
catch (IOException ex) {
|
2009-03-18 07:22:37 +08:00
|
|
|
throw new RuntimeException(ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Does a walker with the given name exist?
|
2009-03-27 21:27:04 +08:00
|
|
|
*
|
2009-03-18 07:22:37 +08:00
|
|
|
* @param walkerName Name of the walker for which to search.
|
|
|
|
|
* @return True if the walker exists, false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public boolean doesWalkerExist(String walkerName) {
|
|
|
|
|
return walkers.containsKey(walkerName);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Gets a walker with the given name, or null if no walker exists.
|
2009-03-27 21:27:04 +08:00
|
|
|
*
|
2009-03-18 07:22:37 +08:00
|
|
|
* @param walkerName Name of the walker to retrieve.
|
|
|
|
|
* @return The walker object if found; null otherwise.
|
|
|
|
|
*/
|
2009-03-27 04:45:27 +08:00
|
|
|
public Walker createWalkerByName(String walkerName)
|
|
|
|
|
throws InstantiationException, IllegalAccessException {
|
|
|
|
|
Class walker = walkers.get(walkerName);
|
2009-03-27 21:27:04 +08:00
|
|
|
return (Walker) walker.newInstance();
|
2009-03-27 04:45:27 +08:00
|
|
|
}
|
|
|
|
|
|
2009-05-16 05:02:12 +08:00
|
|
|
/**
|
|
|
|
|
* Retrieves the walker class given a walker name.
|
|
|
|
|
* @param walkerName Name of the walker.
|
|
|
|
|
* @return Class representing the walker.
|
|
|
|
|
*/
|
2009-03-27 21:27:04 +08:00
|
|
|
public Class getWalkerClassByName(String walkerName) {
|
2009-03-27 04:45:27 +08:00
|
|
|
return walkers.get(walkerName);
|
2009-03-18 07:22:37 +08:00
|
|
|
}
|
|
|
|
|
|
2009-05-16 05:02:12 +08:00
|
|
|
/**
|
|
|
|
|
* Gets the data source for the provided walker.
|
|
|
|
|
* @param walker The walker.
|
|
|
|
|
* @return Which type of data source to traverse over...reads or reference?
|
|
|
|
|
*/
|
|
|
|
|
public static DataSource getWalkerDataSource(Walker walker) {
|
|
|
|
|
Class<? extends Walker> walkerClass = walker.getClass();
|
|
|
|
|
By byDataSource = walkerClass.getAnnotation(By.class);
|
|
|
|
|
if( byDataSource == null )
|
|
|
|
|
throw new StingException("Unable to find By annotation for walker class " + walkerClass.getName());
|
|
|
|
|
return byDataSource.value();
|
|
|
|
|
}
|
|
|
|
|
|
2009-05-20 07:26:17 +08:00
|
|
|
/**
|
|
|
|
|
* Determine whether the given walker supports the given data source.
|
|
|
|
|
* @param walker Walker to query.
|
|
|
|
|
* @param dataSource Source to check for .
|
|
|
|
|
* @return True if the walker forbids this data type. False otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public static boolean isAllowed(Walker walker, DataSource dataSource) {
|
|
|
|
|
Allows allowsDataSource = getWalkerAllowed(walker);
|
|
|
|
|
|
|
|
|
|
// Allows is less restrictive than requires. If an allows
|
|
|
|
|
// clause is not specified, any kind of data is allowed.
|
|
|
|
|
if( allowsDataSource == null )
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return Arrays.asList(allowsDataSource.value()).contains(dataSource);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Determine whether the given walker supports the given reference ordered data.
|
|
|
|
|
* @param walker Walker to query.
|
|
|
|
|
* @param rod Source to check.
|
|
|
|
|
* @return True if the walker forbids this data type. False otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public static boolean isAllowed(Walker walker, ReferenceOrderedData<? extends ReferenceOrderedDatum> rod) {
|
|
|
|
|
Allows allowsDataSource = getWalkerAllowed(walker);
|
|
|
|
|
|
|
|
|
|
// Allows is less restrictive than requires. If an allows
|
|
|
|
|
// clause is not specified, any kind of data is allowed.
|
|
|
|
|
if( allowsDataSource == null )
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
// The difference between unspecified RMD and the empty set of metadata can't be detected.
|
|
|
|
|
// Treat an empty 'allows' as 'allow everything'. Maybe we can have a special RMD flag to account for this
|
|
|
|
|
// case in the future.
|
|
|
|
|
if( allowsDataSource.referenceMetaData().length == 0 )
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
for( RMD allowed: allowsDataSource.referenceMetaData() ) {
|
|
|
|
|
if( rod.matches(allowed.name(),allowed.type()) )
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Determine whether the given walker requires the given data source.
|
|
|
|
|
* @param walker Walker to query.
|
|
|
|
|
* @param dataSource Source to check for.
|
|
|
|
|
* @return True if the walker allows this data type. False otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public static boolean isRequired(Walker walker, DataSource dataSource) {
|
|
|
|
|
Requires requiresDataSource = getWalkerRequirements(walker);
|
|
|
|
|
return Arrays.asList(requiresDataSource.value()).contains(dataSource);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get a list of RODs required by the walker.
|
|
|
|
|
* @param walker Walker to query.
|
|
|
|
|
* @return True if the walker allows this data type. False otherwise.
|
|
|
|
|
*/
|
|
|
|
|
public static List<RMD> getRequiredMetaData(Walker walker) {
|
|
|
|
|
Requires requiresDataSource = getWalkerRequirements(walker);
|
|
|
|
|
return Arrays.asList(requiresDataSource.referenceMetaData());
|
|
|
|
|
}
|
|
|
|
|
|
2009-03-24 11:56:49 +08:00
|
|
|
/**
|
|
|
|
|
* Load classes internal to the classpath from an arbitrary location.
|
2009-03-27 21:27:04 +08:00
|
|
|
*
|
2009-03-24 11:56:49 +08:00
|
|
|
* @param location Location from which to load classes.
|
|
|
|
|
* @return List of classes.
|
|
|
|
|
* @throws IOException Problem occurred reading classes.
|
|
|
|
|
*/
|
2009-03-27 21:27:04 +08:00
|
|
|
private List<Class> loadClassesFromLocation(File location)
|
|
|
|
|
throws IOException {
|
|
|
|
|
if (location.getAbsolutePath().endsWith(".jar"))
|
2009-03-31 07:20:55 +08:00
|
|
|
return JVMUtils.loadInternalClassesFromJar(location);
|
2009-03-24 11:56:49 +08:00
|
|
|
else {
|
2009-03-31 07:20:55 +08:00
|
|
|
List<String> classFileNames = PathUtils.findFilesInPath(location, "", "class", true);
|
|
|
|
|
return JVMUtils.loadInternalClasses(classFileNames);
|
2009-03-27 21:27:04 +08:00
|
|
|
}
|
2009-03-24 11:56:49 +08:00
|
|
|
}
|
|
|
|
|
|
2009-03-19 01:32:24 +08:00
|
|
|
/**
|
|
|
|
|
* Given a list of classes, return a list of those classes which extend from the Walker base interface.
|
2009-03-27 21:27:04 +08:00
|
|
|
*
|
2009-03-19 01:32:24 +08:00
|
|
|
* @param classes Arbitrary list of classes.
|
|
|
|
|
* @return List of classes extending from Walker.
|
|
|
|
|
*/
|
|
|
|
|
private List<Class> filterWalkers(List<Class> classes) {
|
|
|
|
|
StdReflect reflect = new JdkStdReflect();
|
2009-03-31 07:20:55 +08:00
|
|
|
FunctionN<Boolean> filterFunc = reflect.instanceFunction(new JVMUtils.ClassFilter(Walker.class), "filter", Class.class);
|
2009-03-27 21:27:04 +08:00
|
|
|
return Functions.findAll(filterFunc.f1(), classes);
|
2009-03-19 01:32:24 +08:00
|
|
|
}
|
|
|
|
|
|
2009-03-18 07:22:37 +08:00
|
|
|
/**
|
|
|
|
|
* Instantiate the list of walker classes. Add them to the walker hashmap.
|
2009-03-27 21:27:04 +08:00
|
|
|
*
|
2009-03-18 07:22:37 +08:00
|
|
|
* @param walkerClasses Classes to instantiate.
|
2009-03-27 04:45:27 +08:00
|
|
|
* @return map of walker name to walker.
|
2009-03-18 07:22:37 +08:00
|
|
|
*/
|
2009-03-27 21:27:04 +08:00
|
|
|
private Map<String, Class> createWalkerDatabase(List<Class> walkerClasses) {
|
|
|
|
|
Map<String, Class> walkers = new HashMap<String, Class>();
|
2009-03-18 07:22:37 +08:00
|
|
|
|
2009-03-27 21:27:04 +08:00
|
|
|
for (Class<Walker> walkerClass : walkerClasses) {
|
|
|
|
|
String walkerName = getWalkerName(walkerClass);
|
2009-03-27 21:44:46 +08:00
|
|
|
logger.info(String.format("* Adding module %s", walkerName));
|
2009-03-27 21:27:04 +08:00
|
|
|
walkers.put(walkerName, walkerClass);
|
2009-03-18 07:22:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return walkers;
|
|
|
|
|
}
|
2009-03-27 04:45:27 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Create a name for this type of walker.
|
2009-03-27 21:27:04 +08:00
|
|
|
*
|
2009-03-27 04:45:27 +08:00
|
|
|
* @param walkerType The type of walker.
|
|
|
|
|
* @return A name for this type of walker.
|
|
|
|
|
*/
|
2009-05-20 07:26:17 +08:00
|
|
|
public static String getWalkerName(Class<? extends Walker> walkerType) {
|
2009-03-27 04:45:27 +08:00
|
|
|
String walkerName = "";
|
|
|
|
|
|
2009-03-27 21:27:04 +08:00
|
|
|
if (walkerType.getAnnotation(WalkerName.class) != null)
|
|
|
|
|
walkerName = walkerType.getAnnotation(WalkerName.class).value().trim();
|
2009-03-27 04:45:27 +08:00
|
|
|
|
2009-03-27 21:27:04 +08:00
|
|
|
if (walkerName.length() == 0) {
|
2009-03-27 04:45:27 +08:00
|
|
|
walkerName = walkerType.getSimpleName();
|
2009-03-27 21:27:04 +08:00
|
|
|
if (walkerName.endsWith("Walker"))
|
|
|
|
|
walkerName = walkerName.substring(0, walkerName.lastIndexOf("Walker"));
|
2009-03-27 04:45:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return walkerName;
|
|
|
|
|
}
|
2009-05-20 07:26:17 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Utility to get the requires attribute from the walker.
|
|
|
|
|
* Throws an exception if requirements are missing.
|
|
|
|
|
* @param walker Walker to query for required data.
|
|
|
|
|
* @return Required data attribute.
|
|
|
|
|
*/
|
|
|
|
|
private static Requires getWalkerRequirements(Walker walker) {
|
|
|
|
|
Class<? extends Walker> walkerClass = walker.getClass();
|
|
|
|
|
Requires requiresDataSource = walkerClass.getAnnotation(Requires.class);
|
|
|
|
|
if( requiresDataSource == null )
|
|
|
|
|
throw new StingException( "Unable to find data types required by walker class " + walkerClass.getName());
|
|
|
|
|
return requiresDataSource;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Utility to get the forbidden attribute from the walker.
|
|
|
|
|
* @param walker Walker to query for required data.
|
|
|
|
|
* @return Required data attribute. Null if forbidden info isn't present.
|
|
|
|
|
*/
|
|
|
|
|
private static Allows getWalkerAllowed(Walker walker) {
|
|
|
|
|
Class<? extends Walker> walkerClass = walker.getClass();
|
|
|
|
|
Allows allowsDataSource = walkerClass.getAnnotation(Allows.class);
|
|
|
|
|
return allowsDataSource;
|
|
|
|
|
}
|
2009-03-18 07:22:37 +08:00
|
|
|
}
|