/*
* FunctionCatalog.java
*
* Created on September 18, 2002, 2:01 PM
*/
package hep.aida.ref.function;
import hep.aida.IAnalysisFactory;
import hep.aida.IFunction;
import hep.aida.IFunctionCatalog;
import hep.aida.IFunctionFactory;
import hep.aida.IModelFunction;
import hep.aida.IRangeSet;
import hep.aida.ITree;
import hep.aida.dev.IDevFunctionCatalog;
import hep.aida.ext.IManagedFunction;
import hep.aida.ref.ManagedObject;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
*
* @author serbo
*/
public class FunctionCatalog implements IDevFunctionCatalog, Serializable {
private static Pattern pattern = Pattern.compile("\\s*(\\w+)\\s*\\+??");
public static String[] defaultNames = { "g2", "g", "e",
"moyal", "lorentzian",
"p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9" };
public static String prefix = "codelet:";
protected static FunctionCatalog catalog = null;
protected TreeMap hash;
protected TreeMap userHash;
protected FunctionCreator creator;
// Constructors
public static FunctionCatalog getFunctionCatalog() {
if (catalog == null) catalog = new FunctionCatalog();
return catalog;
}
public static FunctionCatalog getFunctionCatalog(String fileName) throws IOException {
try {
if (catalog == null) catalog = new FunctionCatalog(fileName);
} catch (IOException ioe) {
throw ioe;
}
return catalog;
}
protected FunctionCatalog() {
creator = new FunctionCreator();
hash = new TreeMap();
userHash = new TreeMap();
for (int i=0; i<defaultNames.length; i++) {
hash.put(defaultNames[i], new String("codelet:"+defaultNames[i]+":catalog"));
}
}
protected FunctionCatalog(String fileName) throws IOException {
creator = new FunctionCreator();
hash = new TreeMap();
userHash = new TreeMap();
for (int i=0; i<defaultNames.length; i++) {
hash.put(defaultNames[i], new String("codelet:"+defaultNames[i]+":catalog"));
}
loadAll(fileName);
}
// IFunctionCatalog and IDevFunctionCatalog methods
public boolean add(String nameId, IFunction f) {
return add(nameId, f.codeletString());
}
public boolean add(String nameId, String codelet) {
if (hash.containsKey(nameId.toLowerCase())) return false;
if (userHash.containsKey(nameId)) return false;
userHash.put(nameId, codelet);
return true;
}
public String[] list() {
String[] array = new String[hash.size()+userHash.size()];
Object[] entries = (hash.keySet()).toArray();
Object[] userEntries = (userHash.keySet()).toArray();
for (int i=0; i<hash.size(); i++) { array[i] = (String) entries[i]; }
for (int i=0; i<userHash.size(); i++) { array[i+hash.size()] = (String) userEntries[i]; }
return array;
}
private String codeletForName(String catalogName) {
String tmp = catalogName.trim();
String str = (String) hash.get(tmp.toLowerCase());
if (str == null) str = (String) userHash.get(tmp);
return str;
}
public IFunction create(String model) {
return create(null, model);
}
public IFunction create(String name, String model) {
if ( model.indexOf("*") > 0 || model.indexOf("-") > 0 || model.indexOf("/") >0 )
throw new IllegalArgumentException("Unsupported operation. We currently only support adding functions.");
ArrayList functions = new ArrayList();
Matcher matcher = pattern.matcher(model);
while (matcher.find()) {
String m = matcher.group(1);
String codeletString = codeletForName(m);
functions.add( creator.createFromCodelet(name, codeletString) );
}
if ( functions.size() == 0 )
throw new IllegalArgumentException("Problem parsing model "+model+". Please report this problem.");
else if ( functions.size() == 1 )
return (IFunction) functions.get(0);
else
return new SumOfFunctions(name,functions);
}
public IFunction clone(String nameInATree, IFunction f) {
IFunction clone;
String codeletString = f.codeletString();
if ( CodeletUtils.isCodeletFromCatalog(codeletString) ) {
String functionModel = CodeletUtils.modelFromCodelet(f.codeletString());
clone = create(nameInATree,functionModel);
} else if (f instanceof AbstractIFunction) {
try {
clone = (IFunction) ((AbstractIFunction) f).clone();
if (clone instanceof ManagedObject) ((ManagedObject) clone).setName(nameInATree);
if (clone instanceof IManagedFunction) ((IManagedFunction) clone).setName(nameInATree);
} catch (Exception e) {
throw new RuntimeException("Can not create clone of AbstractIFunction", e);
}
} else if (f instanceof Cloneable) {
try {
Class[] tmpC = new Class[0];
Method m = f.getClass().getMethod("clone", tmpC);
clone = (IFunction) m.invoke(f, tmpC);
if (clone instanceof ManagedObject) ((ManagedObject) clone).setName(nameInATree);
if (clone instanceof IManagedFunction) ((IManagedFunction) clone).setName(nameInATree);
} catch (Exception ec) {
throw new RuntimeException("Can not create clone of user function", ec);
}
} else {
clone = creator.createFromCodelet(nameInATree,codeletString);
}
if ( !(clone instanceof IModelFunction) )
clone = new BaseModelFunction(nameInATree, clone.title(), clone);
if (f instanceof IModelFunction) {
((IModelFunction) clone).normalize(((IModelFunction) f).isNormalized());
IRangeSet c_rs = null;
IRangeSet f_rs = null;
double[] upper = null;
double[] lower = null;
((IModelFunction) clone).excludeNormalizationAll();
for (int i=0; i<f.dimension(); i++) {
f_rs = ((IModelFunction) f).normalizationRange(i);
c_rs = ((IModelFunction) clone).normalizationRange(i);
upper = f_rs.upperBounds();
lower = f_rs.lowerBounds();
for (int n=0; n<f_rs.size(); n++) {
c_rs.include(lower[n], upper[n]);
}
}
} //else if (f instanceof IFunction) {
// BaseModelFunction bmf = new BaseModelFunction(nameInATree, nameInATree, clone);
// clone = bmf;
//}
if (clone instanceof BaseModelFunction) {
((BaseModelFunction) clone).setParameterNames(f.parameterNames());
}
clone.setParameters(f.parameters());
return clone;
}
// Other methods
public String[] defaultFunctions() { return defaultNames; }
public void loadAll(String nameOnDisk) throws IOException {
try {
FileInputStream in = new FileInputStream(nameOnDisk);
ObjectInputStream s = new ObjectInputStream(in);
userHash = (TreeMap)s.readObject();
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
throw new RuntimeException("Can not load FunctionCatalog. Please check file:"+nameOnDisk, e);
}
}
public void storeAll(String nameOnDisk) throws IOException {
try {
FileOutputStream out = new FileOutputStream(nameOnDisk);
ObjectOutputStream s = new ObjectOutputStream(out);
s.writeObject(userHash);
s.flush();
} catch (IOException ioe) {
throw ioe;
} catch (Exception e) {
throw new RuntimeException("Can not save FunctionCatalog. Please check file:"+nameOnDisk, e);
}
}
public void remove(String nameId) {
if (hash.containsKey(nameId)) hash.remove(nameId);
else
throw new IllegalArgumentException("Catalog does not contain function \""+nameId+"\"");
}
public FunctionCreator getFunctionCreator() {
return creator;
}
public String toString() {
String str = "";
str += "\nFunctionCatalog: prefix = "+prefix+"\n";
str += "------------------\n";
if (!hash.isEmpty()) {
str += "\n\tDefault Functions:\n";
Object[] keys = (hash.keySet()).toArray();
for (int i=0; i<keys.length; i++) {
str += "\t\t" + ((String) keys[i]) + "\t" + ((String) hash.get(keys[i])) +"\n";
}
}
if (!userHash.isEmpty()) {
str += "\n\tAdditional Functions:\n";
Object[] keys = (userHash.keySet()).toArray();
for (int i=0; i<keys.length; i++) {
str += "\t\t" + ((String) keys[i]) + "\t" + ((String) userHash.get(keys[i])) +"\n";
}
}
return str;
}
public static void main(String[] args) throws ClassNotFoundException, FileNotFoundException, IOException {
test1();
test2();
}
public static void test1() throws ClassNotFoundException, FileNotFoundException, IOException {
IAnalysisFactory af = IAnalysisFactory.create(); //jas.aida.gui.JASGUIAnalysisFactory.create();
ITree tree = af.createTreeFactory().create();
IFunctionFactory ff = af.createFunctionFactory( tree );
IModelFunction f1 = (IModelFunction) ff.createFunctionFromScript("name1", 1, "a*(1+c*sin(x[0]-d))", "a,c,d", "f1");
IModelFunction f2 = (IModelFunction) ff.createFunctionByName("name-2", "P5");
IFunctionCatalog cat = ff.catalog();
System.out.println(cat+"\n");
cat.add("script1", f1);
cat.add("poly-5", f2);
String[] names = cat.list();
for(int i=0; i<names.length; i++) System.out.println(i+"\t "+names[i]);
System.out.println(cat+"\n");
String codelet = "codelet:hep.aida.ref.TestUserFunction:file://afs/slac.stanford.edu/u/ey/serbo/java-tests/freehep-hep.jar";
cat.add("Victor-test", codelet);
System.out.println(cat+"\n");
cat.storeAll("Cat");
}
public static void test2() throws ClassNotFoundException, FileNotFoundException, IOException {
IAnalysisFactory af = IAnalysisFactory.create(); //jas.aida.gui.JASGUIAnalysisFactory.create();
ITree tree = af.createTreeFactory().create();
IFunctionFactory ff = af.createFunctionFactory( tree );
IFunctionCatalog cat = ff.catalog();
cat.loadAll("Cat");
System.out.println(cat+"\n");
IFunction f = ff.createFunctionByName("TreeName", "Victor-test");
System.out.println(FunctionCreator.toString(f));
}
}