package org.molgenis.lifelinesresearchportal.plugins.loader.listeners;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.molgenis.framework.db.Database;
import org.molgenis.framework.db.Database.DatabaseAction;
import org.molgenis.framework.db.DatabaseException;
import org.molgenis.organization.Investigation;
import org.molgenis.pheno.Individual;
import org.molgenis.pheno.Measurement;
import org.molgenis.pheno.ObservedValue;
import org.molgenis.protocol.Protocol;
import org.molgenis.protocol.ProtocolApplication;
import org.molgenis.util.Tuple;
import org.molgenis.util.TupleReader;
/**
* Standard importer for lifelines. Fields with name 'PA_ID' are considered to
* be Individual'
*/
public class LifeLinesStandardListener extends ImportTupleLoader
{
private final int BATCH_SIZE = 1000;
private Logger logger;
private final Map<String, Measurement> measurements = new HashMap<String, Measurement>();
private final Map<String, Individual> targets = new HashMap<String, Individual>();
private final Map<String, ProtocolApplication> protocolApps = new HashMap<String, ProtocolApplication>();
private final List<ObservedValue> values = new ArrayList<ObservedValue>();
private Protocol protocol;
private Investigation investigation;
public LifeLinesStandardListener(Investigation investigation, Protocol protocol, Database db)
throws DatabaseException
{
super(protocol.getName(), db);
this.investigation = investigation;
this.protocol = protocol;
this.logger = Logger.getLogger("LLimport(" + protocol.getName() + ")");
// WANTED: List<Measurement> result = protocol.getFeatures(db);
for (Measurement m : db.query(Measurement.class).in(Measurement.ID, protocol.getFeatures_Id()).find())
{
measurements.put(m.getName(), m);
}
}
private int rowCount = 0;
private int valueCount = 0;
private int batchCount = 0;
@Override
public void load(TupleReader tupleIterator) throws Exception
{
int line_number = 1;
for (Tuple tuple : tupleIterator)
{
// get reference to individual
String pa_id = tuple.getString("PA_ID");
if (pa_id == null) throw new Exception("PA_ID missing for protocol " + protocol.getName() + " in tuple: "
+ tuple);
Individual target = new Individual();
target.setName(pa_id);
target.setInvestigation(investigation);
targets.put(target.getName(), target);
ProtocolApplication app = new ProtocolApplication();
app.setProtocol(protocol);
app.setName(protocol.getName() + "_" + pa_id + "_" + line_number);
app.setInvestigation(investigation);
protocolApps.put(app.getName(), app);
// we iterate through all fields. Each field that is also a
// Measurement
for (String field : tuple.getFieldNames())
{
// only include fields that are selected as measurement
String mName = protocol.getName() + "_" + field; // temporarily
// prepend
// measurement
// name with
// table
// (protocol)
// name
if (measurements.containsKey(mName))
{
ObservedValue v = new ObservedValue();
v.setTarget(target);
v.setInvestigation(investigation);
v.setFeature(measurements.get(mName));
v.setValue(tuple.getString(field));
v.setProtocolApplication(app);
values.add(v);
valueCount++;
batchCount++;
}
}
++rowCount;
if (batchCount > BATCH_SIZE)
{
logger.info("parsed row: " + rowCount + "(valuecount='" + valueCount + "')");
storeValuesInDatabase();
batchCount = 0;
}
line_number++;
}
}
private void storeValuesInDatabase() throws DatabaseException, ParseException
{
// add protocol applications
db.add(new ArrayList(protocolApps.values()));
// only add targets if they are not already there
db.update(new ArrayList(targets.values()), DatabaseAction.ADD_IGNORE_EXISTING, Individual.NAME);
// update all _names with the _ids
for (ObservedValue v : values)
{
v.setTarget(targets.get(v.getTarget_Name()));
v.setProtocolApplication(protocolApps.get(v.getProtocolApplication_Name()));
}
// clear the targets and protocol applications for next batch
this.targets.clear();
this.protocolApps.clear();
// add the values
db.add(this.values);
// clear the values
values.clear();
}
@Override
public void commit() throws DatabaseException, ParseException
{
storeValuesInDatabase();
}
public Investigation getInvestigation()
{
return investigation;
}
public Protocol getProtocol()
{
return protocol;
}
public List<Measurement> getMeasurements()
{
return new ArrayList<Measurement>(measurements.values());
}
}