package org.molgenis.datatable.model;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import org.json.JSONObject;
import org.molgenis.datatable.util.MolgenisUpdateDatabase;
import org.molgenis.framework.db.Database;
import org.molgenis.framework.db.DatabaseException;
import org.molgenis.framework.db.Query;
import org.molgenis.framework.db.QueryRule;
import org.molgenis.framework.db.QueryRule.Operator;
import org.molgenis.framework.tupletable.AbstractFilterableTupleTable;
import org.molgenis.framework.tupletable.EditableTupleTable;
import org.molgenis.framework.tupletable.TableException;
import org.molgenis.model.elements.Field;
import org.molgenis.pheno.Individual;
import org.molgenis.pheno.Measurement;
import org.molgenis.pheno.ObservedValue;
import org.molgenis.util.SimpleTuple;
import org.molgenis.util.Tuple;
import app.DatabaseFactory;
/**
* Wrap one Protocol EAV model in a TupleTable so that you can query this
* protocol as if it was a real table (which we actually could implement for
* smaller protocols).
*
* Here each Measurement is converted into Field, and each ProtocolApplication
* becomes a Tuple with the ObservedValue for filling the elements of the Tuple.
* In addition, the 'target' is assumed constant for all ObservedValue and is
* added as first column. Optionally, the ProtocolApplication metadata can be
* viewed (future todo).
*/
public class AnimalDBTable extends AbstractFilterableTupleTable implements EditableTupleTable
{
// mapping to Field (changes on paging)
private List<Field> columns = new ArrayList<Field>();
private List<Field> visibleColumns = new ArrayList<Field>();
private List<String> measNames = new ArrayList<String>();
private int numberofrows = 0;
private HashMap<String, String> hashMeasurementsWithCategories;
public AnimalDBTable(Database db) throws TableException
{
this.setDb(db);
}
/*
* @Override public int getColCount() { // +1 for the target column return
* protocol.getFeatures_Id().size() + 1; }
*/
@Override
public int getCount() throws TableException
{
try
{
return getDb().find(Individual.class).size();
}
catch (DatabaseException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
return numberofrows;
}
public boolean isFirstColumnFixed()
{
return true;
}
// public List<Field> getVisibleColumns() throws TableException
// {
// return visibleColumns;
// }
public List<Field> getAllColumns() throws TableException
{
if (columns.size() == 0)
{
try
{
List<String> arrayVisColumns = new ArrayList<String>();
arrayVisColumns.add("Active");
arrayVisColumns.add("Line");
arrayVisColumns.add("Location");
arrayVisColumns.add("Sex");
arrayVisColumns.add("Species");
arrayVisColumns.add("Background");
Field target = new Field("target");
columns.add(target);
// Preset the variables that are shown in the matrix
for (Measurement columnName : getDb().find(Measurement.class,
new QueryRule(Measurement.NAME, Operator.IN, arrayVisColumns)))
{
columns.add(new Field(columnName.getName()));
}
for (Measurement columnName : getDb().find(Measurement.class))
{
if (!arrayVisColumns.contains(columnName.getName()))
{
columns.add(new Field(columnName.getName()));
}
// if (arrayVisColumns.contains(columnName.getName()))
// {
// visibleColumns.add(columns.get(columns.size() - 1));
// }
}
}
catch (DatabaseException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return columns;
}
// private List<String> getColumnNames()
// {
// try
// {
// for (Measurement columnName : getDb().find(Measurement.class))
// {
// measNames.add(columnName.getName());
// }
// }
// catch (DatabaseException e)
// {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
//
// return measNames;
// }
@Override
public void close()
{
}
public List<Tuple> getRows()
{
List<Individual> obT;
List<Tuple> result = new ArrayList<Tuple>();
try
{
obT = getDb().find(Individual.class);
List<String> targetNames = new ArrayList<String>();
for (Individual target : obT)
{
targetNames.add(target.getName());
}
String lastTarget = "";
Tuple t = null;
for (ObservedValue v : getDb().find(ObservedValue.class,
new QueryRule(ObservedValue.TARGET_NAME, Operator.IN, targetNames)))
{
// New target in the table, we should create a new tuple
if (!lastTarget.equals(v.getTarget_Name()))
{
if (t != null)
{
result.add(t);
}
t = new SimpleTuple();
lastTarget = v.getTarget_Name();
t.set("target", v.getTarget_Name());
}
t.set(v.getFeature_Name(), v.getValue());
}
result.add(t);
}
catch (Exception e1)
{
result = null;
System.out.println("There is no RESULT tuple");
// TODO Auto-generated catch block
e1.printStackTrace();
}
return result;
}
/*
* @Override protected Tuple getValues(int row, List<Field> columns) throws
* TableException { numberofrows = obsT.size();
*
* Tuple tuple = new SimpleTuple(); ; try {
*
* for (ObservedValue o : getDb().find(ObservedValue.class)) { //
*
* tuple.set(o.getTarget_Name(), getColumnNames()); } } catch
* (DatabaseException e) { // TODO Auto-generated catch block
* e.printStackTrace(); } return tuple;
*
* }
*/
@Override
public void add(Tuple request) throws TableException
{
Database db = getDb();
String patientID = request.getString("targetID");
Individual ot = null;
String investigationName = "";
try
{
// Check if the individual already exists in the database,
// if
// so, it only gives back the message. If it doesn`t, the
// individual is added to the database
if (db.find(Individual.class, new QueryRule(Individual.NAME, Operator.EQUALS, patientID)).size() > 0)
{
throw new TableException("The patient has already existed and adding failed. Please edit this patient");
}
else
{
ot = new Individual();
ot.setName(patientID);
}
// If the individual is new, the following code will be
// executed.
if (ot != null)
{
if (request.getString("data") != null)
{
// Get the data and transform it to json object. And
// this json object contains all the new added
// values
JSONObject json = new JSONObject(request.getString("data"));
List<ObservedValue> listOfNewValues = new ArrayList<ObservedValue>();
// create an iterator for the json object.
Iterator<?> iterator = json.keys();
int count = 0;
while (iterator.hasNext())
{
String feature = iterator.next().toString();
// We do not know which investigation it is in
// JQGridView.java class. Therefore we take the
// investigationName from measurement
if (count == 0)
{
investigationName = db
.find(Measurement.class, new QueryRule(Measurement.NAME, Operator.EQUALS, feature))
.get(0).getInvestigation_Name();
count++;
}
String value = json.get(feature).toString();
if (!value.equals(""))
{
ObservedValue ov = new ObservedValue();
ov.setTarget_Name(patientID);
ov.setFeature_Name(feature);
if (getHashMeasurementsWithCategories().containsKey(feature))
{
String[] splitValue = value.split("\\.");
ov.setValue(splitValue[0]);
}
else
{
ov.setValue(value);
}
ov.setInvestigation_Name(investigationName);
listOfNewValues.add(ov);
}
}
ot.setInvestigation_Name(investigationName);
db.add(ot);
db.add(listOfNewValues);
}
}
}
catch (Exception e)
{
e.printStackTrace();
throw new TableException(e);
}
}
@Override
public void update(Tuple request) throws TableException
{
String targetString = "Pa_Id";
String targetID = request.getString(targetString);
if (targetID != null)
{
try
{
List<String> listFields = request.getFieldNames();
List<QueryRule> listQuery = new ArrayList<QueryRule>();
listQuery.add(new QueryRule(ObservedValue.TARGET_NAME, Operator.EQUALS, targetID));
listQuery.add(new QueryRule(ObservedValue.FEATURE_NAME, Operator.IN, listFields));
Integer protAppID = getDb().find(ObservedValue.class, new QueryRule(listQuery)).get(0)
.getProtocolApplication_Id();
for (Field eachField : getAllColumns())
{
if (!eachField.getName().equals(targetString))
{
MolgenisUpdateDatabase mu = new MolgenisUpdateDatabase();
mu.UpdateDatabase(getDb(), targetID, request.getString(eachField.getName()),
eachField.getName(), protAppID);
}
}
}
catch (Exception e)
{
e.printStackTrace();
throw new TableException(e);
}
}
}
@Override
public void remove(Tuple request) throws TableException
{
try
{
String paId = request.getString("Pa_Id");
Query<ObservedValue> query = getDb().query(ObservedValue.class);
List<String> listOfColumns = new ArrayList<String>();
for (Field f : getAllColumns())
{
if (!f.getName().equals("Pa_Id"))
{
listOfColumns.add(f.getName());
}
}
query.addRules(new QueryRule(ObservedValue.TARGET_NAME, Operator.EQUALS, paId));
query.addRules(new QueryRule(ObservedValue.FEATURE_NAME, Operator.IN, listOfColumns));
List<ObservedValue> listOfRemoveValues = query.find();
if (listOfRemoveValues.size() > 0)
{
Database db = getDb();
Individual ind = db.find(Individual.class, new QueryRule(Individual.NAME, Operator.EQUALS, paId))
.get(0);
db.remove(ind);
}
}
catch (Exception e)
{
e.printStackTrace();
throw new TableException(e);
}
}
private HashMap<String, String> getHashMeasurementsWithCategories() throws DatabaseException
{
if (hashMeasurementsWithCategories == null)
{
hashMeasurementsWithCategories = new HashMap<String, String>();
List<Measurement> listOM = getDb().find(Measurement.class);
for (Measurement m : listOM)
{
if (m.getCategories_Name().size() > 0)
{
hashMeasurementsWithCategories.put(m.getName(), m.getDataType());
}
}
}
return hashMeasurementsWithCategories;
}
/**
* very bad: bypasses all security and connection management
*/
private Database db;
public void setDb(Database db)
{
if (db == null) throw new NullPointerException("database cannot be null in setDb(db)");
this.db = db;
}
public Database getDb()
{
try
{
db = DatabaseFactory.create();
}
catch (DatabaseException e)
{
throw new RuntimeException(e);
}
return this.db;
}
}