/*
* Copyright (c) 2010 StockPlay development team
* All rights reserved.
*
* 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/>.
*
*/
package com.kapti.filter;
import com.kapti.exceptions.FilterException;
import com.kapti.filter.graph.Graph;
import com.kapti.filter.graph.Node;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
/**
* Abstracte klasse voor een converteerbaar object. Dit is een heel belangrijk
* object, die voorziet in een interface van methodes die elk conveertbaar
* object moet implementeren, maar ook een resem gedeelde functionaliteit
* (zoals parameters, laden van converters, ...) implementeert.
*
* @author tim
*/
public abstract class Convertable implements Serializable {
//
// Member data
//
protected List<Convertable> mParameters = new ArrayList<Convertable>();
private static String mConverterClass;
//
// Constructie
//
public Convertable(List<Convertable> iParameters) {
mParameters = iParameters;
}
public Convertable(Convertable iObject) {
mParameters = iObject.mParameters;
}
//
// Methods
//
public static void setConverterClass(String iConverterClass) {
mConverterClass = iConverterClass;
}
/**
* Deze methode geeft een Convertable terug die de nodige functionaliteit
* implementeert om het huidige object te compileren. Daarbij wordt
* gekeken naar een properties file om te zien welke converter ingeladen moet
* worden.
*/
public final Convertable getConverter() throws FilterException {
// Check if the converter class is defined
if (mConverterClass == null)
throw new FilterException(FilterException.Type.FILTER_FAILURE, "converter class is not defined");
// Get the constructor of a converter
String tObjectName = this.getClass().getPackage().getName() + "." + mConverterClass + "." + this.getClass().getSimpleName() + "Converter";
Constructor<?> tConstructor = null;
try {
Class<? extends Convertable> tObjectClass = Class.forName(tObjectName).asSubclass(Convertable.class);
tConstructor = tObjectClass.getConstructor(this.getClass());
}
catch (ClassNotFoundException e) {
throw new FilterException(FilterException.Type.FILTER_FAILURE, "could not find an appropriate converter for object '" + this.getClass().getSimpleName() + "'", e.getCause());
}
catch (NoSuchMethodException e) {
throw new FilterException(FilterException.Type.FILTER_FAILURE, "could not find converter constructor at class '" + tObjectName + "'", e.getCause());
}
// Create a new object
Object tObject = null;
try {
tObject = tConstructor.newInstance(this);
}
catch (InstantiationException e) {
throw new FilterException(FilterException.Type.FILTER_FAILURE, "requested instantiation of converter '" + tObjectName + "' failed as it is not a concrete class", e.getCause());
}
catch (IllegalAccessException e) {
throw new FilterException(FilterException.Type.FILTER_FAILURE, "illegal access to class '" + tObjectName + "'", e.getCause());
}
catch (InvocationTargetException e) {
throw new FilterException(FilterException.Type.FILTER_FAILURE, "an exception occured when instantiating a converter of class '" + tObjectName + "'", e.getCause());
}
// Call the object
Convertable tConverter = (Convertable) tObject;
return tConverter;
}
/**
* Compileert het huidige object door een Converter te instantiƫren, en dan
* daarop opnieuw de Compile functie aan te roepen. Het is dus duidelijk
* dat Converters de compile() functie moeten overschrijven door een
* effectieve implementatie, of een oneindige loop wordt gecreƫerd.
*
* @return
* @throws FilterException
*/
public Object compile() throws FilterException {
return getConverter().compile();
}
@Override
public int hashCode() {
// Hash the type of data
int code = this.getClass().hashCode();
// Hash all children
for (Convertable c : mParameters) {
code = (31 * code) + c.hashCode();
}
return code;
}
//
// Interface
//
/**
* Elke convertable methode moet ook voorzien in een statische getSignature
* methode, die de signatuur van de methode vastlegt. Java biedt echter
* geen faciliteiten om een statische methode af te dwingen, vandaar
* dit stukje commentaar.
*/
/**
* Verplicht te-implementeren methode, die instaat voor het toevoegen van
* zichzelf aan de globale Graph boom.
*
* @param iGraph
* @return
*/
public abstract Node addNode(Graph iGraph);
}