package org.molgenis.omx.dataset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.molgenis.framework.db.Database;
import org.molgenis.framework.db.DatabaseException;
import org.molgenis.framework.db.QueryRule;
import org.molgenis.framework.tupletable.AbstractFilterableTupleTable;
import org.molgenis.framework.tupletable.DatabaseTupleTable;
import org.molgenis.framework.tupletable.TableException;
import org.molgenis.framework.tupletable.TupleTable;
import org.molgenis.model.elements.Field;
import org.molgenis.observ.Characteristic;
import org.molgenis.observ.DataSet;
import org.molgenis.observ.ObservableFeature;
import org.molgenis.observ.ObservationSet;
import org.molgenis.observ.ObservedValue;
import org.molgenis.util.SimpleTuple;
import org.molgenis.util.Tuple;
public class DataSetTable extends AbstractFilterableTupleTable implements DatabaseTupleTable
{
private DataSet dataSet;
private Database db;
private int rows = -1;
private List<Field> columns;
public DataSetTable(DataSet set, Database db) throws TableException
{
if (set == null) throw new TableException("DataSet cannot be null");
this.dataSet = set;
if (db == null) throw new TableException("db cannot be null");
this.setDb(db);
this.setFirstColumnFixed(true);
}
@Override
public List<Field> getAllColumns() throws TableException
{
if (columns == null) initColumnsFromDb();
return Collections.unmodifiableList(columns);
}
private void initColumnsFromDb() throws TableException
{
try
{
// instead ask for protocol.features?
String sql = "SELECT DISTINCT Characteristic.identifier as name, Characteristic.name as label FROM Characteristic, ObservedValue, ObservationSet WHERE ObservationSet.partOfDataSet="
+ dataSet.getId()
+ " AND ObservedValue.ObservationSet=ObservationSet.id AND Characteristic.id = ObservedValue.feature";
columns = new ArrayList<Field>();
Field targetField = new Field("target");
targetField.setLabel("target");
columns.add(targetField);
for (Tuple t : getDb().sql(sql))
{
Field f = new Field(t.getString("name"));
f.setLabel(t.getString("label"));
columns.add(f);
}
}
catch (Exception e)
{
throw new TableException(e);
}
}
@Override
public List<Tuple> getRows() throws TableException
{
try
{
List<Tuple> result = new ArrayList<Tuple>();
List<QueryRule> filters = getFilters();
rows = 0;
// load visible ObservationSet
if (filters.isEmpty())
{
rows = getDb().query(ObservationSet.class).eq(ObservationSet.PARTOFDATASET, dataSet.getId()).count();
for (ObservationSet os : getDb().query(ObservationSet.class)
.eq(ObservationSet.PARTOFDATASET, dataSet.getId()).find())
{
Tuple t = new SimpleTuple();
t.set("target", os.getTarget_Identifier());
for (ObservedValue v : getDb().query(ObservedValue.class)
.eq(ObservedValue.OBSERVATIONSET, os.getId()).find())
{
t.set(v.getFeature_Identifier(), v.getValue());
}
result.add(t);
}
}
else
{
for (ObservationSet os : getDb().query(ObservationSet.class)
.eq(ObservationSet.PARTOFDATASET, dataSet.getId()).find())
{
Tuple t = new SimpleTuple();
// TODO : remove the empty rows that do not much the filters
// from t
Integer rowId = 0;
// for (QueryRule queryRule : filters)
// {os.
// if (os.getTarget_Identifier().equals(os.) t.set("target",
// os.getTarget_Identifier());
// }
for (QueryRule queryRule : filters)
{
for (ObservedValue v : getDb().query(ObservedValue.class)
.eq(ObservedValue.OBSERVATIONSET, os.getId()).find())
{
// set the filter to the Observable features here
if (queryRule.getField().equals(v.getFeature_Identifier())
&& queryRule.getValue().equals(v.getValue()))
{
// t.set(v.getFeature_Identifier(),v.getValue());
rowId = v.getObservationSet_Id();
break;
}
}
//
}
if (rowId != 0)
{
t.set("target", os.getTarget_Identifier());
for (ObservedValue v : getDb().query(ObservedValue.class)
.eq(ObservedValue.OBSERVATIONSET, rowId).find())
{
t.set(v.getFeature_Identifier(), v.getValue());
}
result.add(t);
this.rows++;
}
// boolean keep = false;
//
// for (ObservedValue v : getDb().query(ObservedValue.class)
// .eq(ObservedValue.OBSERVATIONSET, os.getId()).find())
// {
// for (QueryRule queryRule : filters)
// {
// // set the filter to the Observable features here
// if
// (queryRule.getField().equals(v.getFeature_Identifier())
// && queryRule.getValue().equals(v.getValue()))
// t.set(v.getFeature_Identifier(),
// v.getValue());
// }
// result.add(t);
// }
}
}
return result;
}
catch (Exception e)
{
throw new TableException(e);
}
}
public void add(TupleTable table) throws TableException
{
try
{
getDb().beginTx();
// verify columns to be feature identifiers
Map<String, Integer> featureMap = new TreeMap<String, Integer>();
List<Field> cols = table.getAllColumns();
for (Field f : cols)
{
// first is always target, rest should be feature identifiers
if (!f.equals(cols.get(0)))
{
// slow
try
{
List<ObservableFeature> feature = getDb().query(ObservableFeature.class)
.eq(ObservableFeature.IDENTIFIER, f.getName()).find();
if (feature.size() != 1)
{
throw new TableException("add failed: " + f.getName() + " not known ObservableFeature");
}
else
{
featureMap.put(f.getName(), feature.get(0).getId());
}
}
catch (DatabaseException e)
{
throw new TableException(e);
}
}
}
// load the rows
int count = 0;
for (Tuple t : table)
{
// slow, check if target exists
List<Characteristic> targets = getDb().query(Characteristic.class)
.eq(Characteristic.IDENTIFIER, t.getString(0)).find();
if (targets.size() == 1)
{
ObservationSet es = new ObservationSet();
es.setPartOfDataSet(dataSet.getId());
es.setTarget(targets.get(0).getId());
getDb().add(es);
List<ObservedValue> values = new ArrayList<ObservedValue>();
for (String name : t.getFieldNames())
{
if (!name.equals(t.getColName(0)))
{
ObservedValue v = new ObservedValue();
v.setObservationSet(es.getId());
v.setFeature(featureMap.get(name));
v.setValue(t.getString(name));
values.add(v);
}
}
getDb().add(values);
}
else
{
throw new DatabaseException("import of row " + count + " failed: target " + t.getString(0)
+ " unknown");
}
}
count++;
getDb().commitTx();
}
catch (Exception e)
{
try
{
getDb().rollbackTx();
}
catch (DatabaseException e1)
{
;
}
throw new TableException(e);
}
}
@Override
public int getCount() throws TableException
{
getRows();
return this.rows;
}
@Override
public Database getDb()
{
return db;
}
@Override
public void setDb(Database db)
{
this.db = db;
}
public DataSet getDataSet()
{
return dataSet;
}
public void setDataSet(DataSet dataSet)
{
this.dataSet = dataSet;
}
}