Repository /TunedIT/core.jar:org.tunedit.core.StandardLoader


Back

No file description

Source code

/*
 *  Copyright (C) 2009 by TunedIT. All rights reserved.
 *
 */
package org.tunedit.core;


import java.io.InputStream;
import java.util.List;

import org.debellor.base.Buffer;
import org.debellor.core.Cell;
import org.debellor.core.exception.cell.CellException;
import org.debellor.rseslib.RseslibClassifier;
import org.debellor.weka.ArffReader;
import org.debellor.weka.WekaClassifier;
import org.tunedit.core.exception.AlgorithmErrorException;
import org.tunedit.core.exception.ClassExpectedException;
import org.tunedit.core.exception.TunedTesterException;

/**
 * <p>StandardLoader is a wrapper class for {@link ResourceLoader} -
 * it extends ResourceLoader with convenient methods for simultaneous
 * loading and converting resources to appropriate classes or objects,
 * as expected by the client code (evaluation procedure).
 * Thus, StandardLoader not only loads but also <i>interprets</i>
 * the resource according to the client's request. 
 * For example, if the client expects the resource to be a Debellor's Cell subclass,
 * StandardLoader will try to cast the downloaded class to Cell
 * or - if this fails - to interpret the class as Weka's or Rseslib's classifier,
 * which then can be wrapped up into a cell using Debellor's standard wrappers: 
 * WekaClassifier or RseslibClassifier.
 * </p>
 * <p>
 * StandardLoader facilitates loading of resources from TunedIT Repository
 * and instantiating them as objects of proper types.
 * This makes implementation of evaluation procedures easier
 * and more versatile, as addition of new types of algorithms
 * or data storage formats can be done through extending
 * StandardLoader alone, without touching the code of evaluation procedures.
 * </p>
 * 
 * @author Marcin Wojnarski
 *
 */
public class StandardLoader implements ResourceLoader {

	private ResourceLoader loader;
	
	
	public StandardLoader(ResourceLoader loader) {
		this.loader = loader;
	}


	@Override
	public ExternalProcess runProcess(ResourceName fileResource, List<String> args) throws TunedTesterException{
		return loader.runProcess(fileResource, args);
	}


	
	// TODO loadCell should allocate objects of different types reflectively, to avoid compilation-time dependencies (needed to support versioning)
	/**
	 * Loads the resource from TunedIT Repository and attempts to 
	 * interpret it as Debellor's Cell subclass.
	 * Then constructs an instance of this class.
	 * Currently, the resource must be either a Cell subclass
	 * or a Weka's or Rseslib's classifier (subclass of 
	 * <code>weka.classifiers.Classifier</code>
	 * or <code>rseslib.processing.classification.Classifier</code>).
	 * 
	 * @param classResource  name of TunedIT resource, the resource must be a Java class
	 * @return  an instance of Cell subclass represented by the resource
	 * @throws TunedTesterException
	 */
	@SuppressWarnings("unchecked")
	public Cell loadCell(ResourceName classResource) throws TunedTesterException, AlgorithmErrorException {
		Class<?> c = loadClass(classResource);
		try {
			if(isSubclass(c, "org.debellor.core.Cell"))
				return (Cell) c.newInstance();
			if(isSubclass(c, "weka.classifiers.Classifier"))
				return new WekaClassifier((Class<? extends weka.classifiers.Classifier>) c);
			if(isSubclass(c, "rseslib.processing.classification.Classifier"))
				return new RseslibClassifier((Class<? extends rseslib.processing.classification.Classifier>) c);
		}
		catch(Exception e) {
			throw new AlgorithmErrorException(e);
		}
		throw new AlgorithmErrorException("Class " + classResource + " is neither a cell nor can be converted to a cell");
	}
	
	/**
	 * Loads Java class represented by <code>classResource</code> from TunedIT Repository
	 * and dynamically links into TunedTester. Returns the loaded class.
	 * 
	 * @param classResource  name of TunedIT resource, the resource must be a Java class
	 * @return  representation of the class as an instance of <code>java.lang.Class</code>
	 * @throws TunedTesterException
	 */
	public Class<?> loadClass(ResourceName classResource) throws TunedTesterException {
		verifyClassLoader();
		String className = classResource.getClassPart();
		if (className == null){
			throw new ClassExpectedException(classResource);
		}
		try {
			return Class.forName(className);
		}
		catch (ClassNotFoundException e) {
			throw new TunedTesterException("Class " + className + " cannot be found", e);
		}
	}
	
	/** Loads data from an ARFF file, buffers them in memory and returns
	 * in the form of a Debellor's cell.
	 * Data can be accessed by calling open()-next()...-close() on the returned cell.
	 * This cell can be opened many times and it will produce always the same
	 * sequence of samples. 
	 * 
	 * @param dataset  name of a TunedIT resource, the resource must be an ARFF file
	 */
	public Cell loadData(ResourceName dataset) throws TunedTesterException {
		String s = dataset.getFilePart();
		if ((s != null) && (s.endsWith(".arff"))) {
			try {
				ArffReader reader = new ArffReader();
				reader.setInputStream(open(dataset));
				reader.set("decisionAttr", "last");
				
				Cell buffer = new Buffer();
				buffer.setSource(reader);
				buffer.learn();				// materialize input data in memory
				buffer.setSource(null);		// release 'reader' to be garbage-collected
				
				return buffer;
			} catch (CellException e) {
				throw new TunedTesterException(e);
			}
		} else {
			Class<?> c = loadClass(dataset);
			try {
				if(isSubclass(c, "org.debellor.core.Cell"))
					return (Cell) c.newInstance();
			} catch (Exception e) {
				throw new TunedTesterException(e);
			}
			throw new TunedTesterException();
		}
	}

	@Override
	public InputStream open(ResourceName resource) throws TunedTesterException {
		return loader.open(resource);
	}

	/**
	 * @param cls - class to be checked
	 * @param baseClass - name of the hypothetical superclass or interface of cls
	 * @return <code>true</code> if <code>cls</code> subclasses/implements the class/interface <code>baseClass</code>
	 * @throws TunedTesterException 
	 */
	private boolean isSubclass(Class<?> cls, String baseClass) throws TunedTesterException {
		verifyClassLoader();
		try {
			return Class.forName(baseClass).isAssignableFrom(cls);
		} catch (ClassNotFoundException e) {
			return false;
		}
	}

	private void verifyClassLoader() throws TunedTesterException {
		try {
			ClassLoader sys = ClassLoader.getSystemClassLoader();
			// if we get here it means that there is something wrong with class loaders
			if(getClass().getClassLoader() == sys)
				throw new TunedTesterException("StandardLoader was loaded by system ClassLoader");
			else
				throw new TunedTesterException("StandardLoader has access rights to get system ClassLoader");
		}
		catch(SecurityException e) {
			// SecurityException should occur, which indicates that this StandardLoader
			// has been loaded properly with a custom TunedTester's class loader,
			// not with the system class loader.
			return;
		}
	}

}

Copyright © 2008-2011 by TunedIT
Design by luksite