/*
* FunctionCreator.java
*
* Created on September 26, 2002, 11:57 AM
*/
package hep.aida.ref.function;
import hep.aida.IFunction;
import hep.aida.IManagedObject;
import hep.aida.ext.IManagedFunction;
import hep.aida.ref.ManagedObject;
import java.io.File;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.StringTokenizer;
/**
* Singleton class that is used by FunctionFactory and FunctionCatalog
* to create functions from codelet strings. Use static method
* getFunctionCreator() to get an instance of this class.
*
* @author serbo
*/
public class FunctionCreator {
public FunctionCreator() {
}
public IFunction createFromCodelet(String codeletString) {
return createFromCodelet(null, codeletString);
}
public IFunction createFromCodelet(String nameInTree, String codeletString) {
IFunction f = null;
if (!codeletString.toLowerCase().startsWith(FunctionCatalog.prefix))
throw new IllegalArgumentException("\""+ codeletString + "\" is not a codelet string (must start with \""+FunctionCatalog.prefix+"\")");
String name = CodeletUtils.modelFromCodelet(codeletString);
String location = CodeletUtils.locationFromCodelet(codeletString);
//System.out.println("Catalog: index="+index+", name="+name+", location="+location);
// Catalog entries for Build-in functions
if (CodeletUtils.isCodeletFromCatalog(codeletString)) {
if (name.toLowerCase().equals("e")) {
f = new BaseModelFunction(name, name, new ExponentialCoreNotNorm(name), new ExponentialCoreNorm(name));
} else if (name.toLowerCase().startsWith("p")) {
f = new BaseModelFunction(name, name, new PolynomialCoreNotNorm(name), new PolynomialCoreNorm(name));
} else if (name.toLowerCase().startsWith("g2")) {
f = new BaseModelFunction(name, name, new GaussianCore2DNotNorm(name), new GaussianCore2DNorm(name));
} else if (name.toLowerCase().startsWith("g")) {
f = new BaseModelFunction(name, name, new GaussianCoreNotNorm(name), new GaussianCoreNorm(name));
} else if (name.toLowerCase().startsWith("moyal")) {
f = new BaseModelFunction(name, name, new MoyalCoreNotNorm(name), null);
} else if (name.toLowerCase().startsWith("lorentzian")) {
f = new BaseModelFunction(name, name, new LorentzianCoreNotNorm(name), null);
} else {
throw new UnsupportedOperationException("Can not create function: "+name);
}
((BaseModelFunction) f).setCodeletString(codeletString);
if ( nameInTree == null ) nameInTree = name;
((ManagedObject) f).setName(nameInTree);
}
// Create JEL-based scripted function. The codeletString explession after
// "codelet:verbatim:jel:" MUST contain a full description of scripted function.
// Currently use ":" as deliminators. Example:
// codelet:Script_Function:verbatim:jel :1 : a*(1+c*sin(x[0]-d)) : a,c,d : a*c*cos(x[0]-d)
else if (CodeletUtils.isCodeletFromScript(codeletString)) {
//System.out.println("CODELETSTRING :: "+codeletString);
StringTokenizer st = new StringTokenizer(codeletString, ":");
String[] args = new String[st.countTokens()];
int i = 0;
while (st.hasMoreTokens()) {
args[i] = st.nextToken().trim();
//System.out.println(i+" "+args[i]);
i++;
}
int dim = Integer.parseInt(args[4]);
String valexpr = args[5];
String parameters = args[6];
String gradexpr = "";
if (args.length > 7) {
gradexpr = args[7];
}
if (gradexpr.trim().toLowerCase().equals("null") || gradexpr.trim().equals("") ) gradexpr = null;
//System.out.println("dim="+dim+", valexpr="+valexpr+", parameters="+parameters+", gradexpr="+gradexpr);
f = new JELBaseModelFunction(name, dim, valexpr, parameters, name, gradexpr);
((JELBaseModelFunction) f).setCodeletString(codeletString);
((ManagedObject) f).setName(nameInTree);
}
// Create function, given its full class name:
// codelet:my.functions.MyFunction:classPath
// No-argument constructor is used in such case: new MyFunction()
// If optional list of variable names and parameter names is provided:
// codelet:my.functions.MyFunction:classPath:x0, x1: a, b, c
// MyFunction(String[] varNames, String[] parNames) constructor is used
else if (CodeletUtils.isCodeletFromClass(codeletString)) {
StringTokenizer st = new StringTokenizer(codeletString, ":");
String[] args = new String[st.countTokens()];
int i = 0;
while (st.hasMoreTokens()) {
args[i] = st.nextToken().trim();
i++;
}
String[] varList = CodeletUtils.stringToArray(args[3]);
String[] parList = CodeletUtils.stringToArray(args[4]);
try {
if (varList != null && parList != null) {
Class[] types = new Class[] {String[].class, String[].class};
Class cl = Class.forName(name);
f = (IFunction) cl.getConstructor(types).newInstance(new Object[] {varList, parList});
} else {
Class cl = Class.forName(name);
f = (IFunction) cl.newInstance();
}
if (f instanceof ManagedObject) ((ManagedObject) f).setName(nameInTree);
if (f instanceof IManagedFunction) ((IManagedFunction) f).setName(nameInTree);
if (f != null) f.setTitle(nameInTree);
} catch (Exception ec) {
throw new RuntimeException("Can not create user CLASS function:"+name, ec);
}
}
// Load function from file. "name" MUST be just FULL name of the class
// (e.g. "fitProject.functions.MyFunction"
else if (CodeletUtils.isCodeletFromFile(codeletString)) {
try {
String urlString = location.substring(5).trim();
if (urlString == null || urlString.equals("")) {
Class cl = Class.forName(name);
f = (IFunction) cl.newInstance();
} else {
URL[] urlList = new URL[] { new File(urlString.substring(1)).toURL() };
URLClassLoader loader = new URLClassLoader(urlList);
System.out.println("Name: "+name+"\nFile Name: "+urlString);
System.out.println("URL: "+urlList[0].getFile());
Class cl = loader.loadClass(name);
f = (IFunction) cl.newInstance();
}
if (f instanceof ManagedObject) ((ManagedObject) f).setName(nameInTree);
if (f instanceof IManagedFunction) ((IManagedFunction) f).setName(nameInTree);
} catch (Exception ec) {
throw new RuntimeException("Can not create user FILE function:"+name, ec);
}
}
return f;
}
public static String toString(IFunction f) {
String out = "Codelet: "+f.codeletString()+"\n";
if (f instanceof IManagedObject) out += " name: "+((IManagedObject) f).name()+"\n";
out += "\tDimensions: "+f.dimension()+"\n";
for (int i =0; i<f.dimension(); i++) out += "\t\t Variable "+i+"\t Name: "+f.variableName(i)+"\n";
out += "\tParameters: "+f.numberOfParameters()+"\n";
String[] par = f.parameterNames();
for (int i =0; i<f.numberOfParameters(); i++) out += "\t\t Parameter "+i+"\t Name: "+par[i]+"\n";
out += "Provides gradiant: "+f.providesGradient();
return out;
}
}