package hep.aida.ref.tuple;
import hep.aida.IEvaluator;
import hep.aida.IFilter;
import hep.aida.IManagedObject;
import hep.aida.ITree;
import hep.aida.ITuple;
import hep.aida.ITupleFactory;
import hep.aida.ref.tree.Tree;
/**
*
* @author The FreeHEP Team @ SLAC.
*
*/
public class TupleFactory implements ITupleFactory {
private Tree tree;
private final static char separatorChar = '/';
private String nameInPath( String path ) {
int index = path.lastIndexOf( separatorChar );
if ( index == -1 )
return path;
return path.substring( index+1 );
}
private String parentPath( String path ) {
int index = path.lastIndexOf( separatorChar );
if ( index == -1 )
return null;
return path.substring(0,index);
}
public TupleFactory(ITree tree) {
this.tree = tree instanceof Tree ? (Tree) tree : null;
}
/**
* Create an NTuple
* @param path The persistency path of the n-tuple
* @param title The title of the n-tuple
* @param columnName The names of the columns
* @param columnType The types of the columns
* @param options NTuple options (currently undefined)
*/
public ITuple create(String path, String title, String[] columnName, Class[] columnType, String options) {
Tuple tuple = new Tuple(nameInPath(path), title, columnName, columnType, options);
if ( tree != null ) tree.addFromFactory(parentPath(path),tuple);
return tuple;
}
public ITuple create(String path, String title, String[] columnName, Class[] columnType) {
return create(path,title,columnName,columnType,"");
}
/**
* Create an NTuple
* @param path The persistency path of the n-tuple
* @param title The title of the n-tuple
* @param columns The names and types of the columns e.g. "float px, py, pz, float energy, int charge"
* @param options NTuple options (currently undefined)
*/
public ITuple create(String path, String title, String columns, String options) {
Tuple tuple = new Tuple(nameInPath(path), title, columns, options);
if ( tree != null ) tree.addFromFactory(parentPath(path),tuple);
return tuple;
}
public ITuple create(String path, String title, String columns) {
return create(path,title,columns,"");
}
/**
* Create a logical chain of ITuples. All ITuples in the set must
* have the same structure. Chained ITuple can not be filled.
* @param path The persistency name of the new n-tuple
* @param title The title of the new n-tuple
* @param set The array of ITuples to chain
*/
public ITuple createChained(String path, String title, ITuple[] set) {
ITuple tuple = new ChainedTuple(nameInPath(path), title, set);
if ( tree != null ) tree.addFromFactory(parentPath(path),(IManagedObject) tuple);
return tuple;
}
public ITuple createChained(String path, String title, String[] setName) {
if ( tree == null )
throw new IllegalArgumentException("This TupleFactory does not have a Tree. Can not find Tuple by name.");
ITuple[] tupleSet = new ITuple[setName.length];
for (int i=0; i<setName.length; i++) {
Object t = tree.find(setName[i]);
if (t instanceof ITuple) tupleSet[i] = (ITuple) t;
else throw new IllegalArgumentException("ManagedObject \""+setName[i]+"\" is not an ITuple");
}
return createChained(path, title, tupleSet);
}
public ITuple createFiltered(String path, ITuple tuple, IFilter filter) {
int nColumns = tuple.columns();
String[] columnNames = new String[nColumns];
for (int i=0; i<nColumns; i++) {
columnNames[i] = tuple.columnName(i);
}
return createFiltered(path,tuple, filter, columnNames);
}
public ITuple createFiltered(String path, ITuple tuple, IFilter filter, String[] columns) {
int nColumns = columns.length;
if ( nColumns > tuple.columns() )
throw new IllegalArgumentException("Original ITuple has less columns ("+tuple.columns()+
") than requested for copy ("+nColumns+")");
int[] columnId = new int[nColumns];
String[] fullColumnNames = new String[nColumns];
Class[] columnTypes = new Class[nColumns];
// To get Default Column String
AbstractTuple cdsTuple = null;
if (tuple instanceof Tuple) {
cdsTuple = (AbstractTuple) tuple;
}
for (int i=0; i<nColumns; i++) {
columnId[i] = tuple.findColumn(columns[i]);
columnTypes[i] = tuple.columnType(columnId[i]);
fullColumnNames[i] = null;
if (cdsTuple != null) {
fullColumnNames[i] = cdsTuple.columnDefaultString(columnId[i]);
} else {
// This all is for just a simple ITuple
if ( tuple.columnType(i) != ITuple.class )
fullColumnNames[i] = tuple.columnDefaultValue(i).toString();
else {
ITuple tup = tuple.findTuple(i);
if ( tup != null ) {
String tupName = "";
if (tup instanceof IManagedObject) tupName = ((IManagedObject) tup).name();
else tupName = tup.title();
String tmpColumnsString = "";
int nCol = tup.columns();
for (int j=0; j<nCol; j++) {
Class colType = tup.columnType(j);
String colName =tup.columnName(j);
tmpColumnsString += colType + " " + colName;
if ( i < nCol ) tmpColumnsString += ";";
}
fullColumnNames[i] = tupName+" = {"+tmpColumnsString+"}";
} else
fullColumnNames[i] = "null";
}
}
if ( columnTypes[i] != ITuple.class )
fullColumnNames[i] = columns[i] + " = " + fullColumnNames[i];
}
String title = tuple.title();
//Tuple newTuple = new Tuple(name,title, fullColumnNames, columnTypes, null);
Tuple newTuple = new Tuple(nameInPath(path),title, fullColumnNames, columnTypes, null);
if ( tree != null ) tree.addFromFactory(parentPath(path),newTuple);
copyTuple(tuple, newTuple, filter);
return newTuple;
}
/**
* Create a copy of an ITuple.
* @param path The path of the resulting ITuple. The path can either be a relative or full path.
* ("/folder1/folder2/dataName" and "../folder/dataName" are valid paths).
* All the directories in the path must exist. The characther `/` cannot be used
* in names; it is only used to delimit directories within paths.
* @param tuple The ITuple to be copied.
* @return The copy of the ITuple.
*
*/
public ITuple createCopy(String path, ITuple tuple) throws IllegalArgumentException {
return createFiltered(path, tuple, null);
}
private void copyTuple(ITuple tuple, ITuple newTuple, IFilter filter) {
// fill new n-tuple
if (tuple.rows() > 0) {
int nColumns = newTuple.columns();
int[] columnId = new int[nColumns];
Class[] columnTypes = new Class[nColumns];
for (int i=0; i<nColumns; i++) {
columnId[i] = tuple.findColumn(newTuple.columnName(i));
columnTypes[i] = newTuple.columnType(i);
}
tuple.start();
if ( filter != null ) filter.initialize(tuple);
while (tuple.next()) {
if (filter == null || filter.accept()) {
for (int i=0; i<nColumns; i++) {
int j = columnId[i];
if ( columnTypes[i] == Integer.TYPE ) newTuple.fill(i, tuple.getInt(j));
else if ( columnTypes[i] == Short.TYPE) newTuple.fill(i, tuple.getShort(j));
else if ( columnTypes[i] == Long.TYPE) newTuple.fill(i, tuple.getLong(j));
else if ( columnTypes[i] == Float.TYPE) newTuple.fill(i, tuple.getFloat(j));
else if ( columnTypes[i] == Double.TYPE) newTuple.fill(i, tuple.getDouble(j));
else if ( columnTypes[i] == Boolean.TYPE) newTuple.fill(i, tuple.getBoolean(j));
else if ( columnTypes[i] == Byte.TYPE) newTuple.fill(i, tuple.getByte(j));
else if ( columnTypes[i] == Character.TYPE) newTuple.fill(i, tuple.getChar(j));
else if ( columnTypes[i] == ITuple.class) {
ITuple tOld = (ITuple)tuple.getObject(j);
ITuple tNew = newTuple.getTuple(i);
copyTuple(tOld, tNew, null);
}
else newTuple.fill(i, tuple.getObject(j));
}
newTuple.addRow();
}
}
}
}
/**
* Create IFilter.
*
*/
public IFilter createFilter(String expression) {
return new Filter(expression);
}
public IFilter createFilter(String expression, int rowsToProcess, int startingRow) {
return new Filter(expression,rowsToProcess,startingRow);
}
public IFilter createFilter(String expression, int rowsToProcess) {
return new Filter(expression,rowsToProcess, 0);
}
/**
* Create IEvaluator.
*
*/
public IEvaluator createEvaluator(String expression) {
return new Evaluator(expression);
}
}