package plugins.findingProxy;
import gcc.catalogue.MappingMeasurement;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.json.JSONObject;
import org.molgenis.framework.db.Database;
import org.molgenis.framework.db.Query;
import org.molgenis.framework.db.QueryRule;
import org.molgenis.framework.db.QueryRule.Operator;
import org.molgenis.framework.ui.PluginModel;
import org.molgenis.framework.ui.ScreenController;
import org.molgenis.framework.ui.ScreenMessage;
import org.molgenis.organization.Investigation;
import org.molgenis.pheno.Measurement;
import org.molgenis.protocol.Protocol;
import org.molgenis.util.Entity;
import org.molgenis.util.Tuple;
import plugins.HarmonizationComponent.LevenshteinDistanceModel;
import plugins.HarmonizationComponent.LinkedInformation;
import plugins.HarmonizationComponent.MappingList;
public class findingProxy extends PluginModel<Entity>
{
private List<String> listOfJSON = new ArrayList<String>();
private List<String> listOfValidationStudy = new ArrayList<String>();
private List<String> listOfPredictionModel = new ArrayList<String>();
private List<String> listOfParameters = new ArrayList<String>();
private List<String> manualMappingResultTable = new ArrayList<String>();
private String selectedPredictionModel = null;
private String selectedValidationStudy = null;
private String selectedManualParameter = null;
private boolean stage = true;
private LevenshteinDistanceModel model = new LevenshteinDistanceModel();
private int maxQuerySize = 0;
private double cutOffValue = 40;
private String userDefinedQuery = "";
private List<Measurement> measurementsInStudy = new ArrayList<Measurement>();
private HashMap<String, MappingList> mappingResultAndSimiarity = new HashMap<String, MappingList>();
private HashMap<String, List<String>> parameterToExpandedQuery = new HashMap<String, List<String>>();
private HashMap<String, List<String>> expandedQueries = new HashMap<String, List<String>>();
/**
*
*/
private static final long serialVersionUID = 7938039670107105296L;
public findingProxy(String name, ScreenController<?> parent)
{
super(name, parent);
// TODO Auto-generated constructor stub
}
public String getCustomHtmlHeaders()
{
return "<link rel=\"stylesheet\" style=\"text/css\" href=\"res/css/download_list.css\">";
}
@Override
public String getViewName()
{
return "plugins_findingProxy_findingProxy";
}
@Override
public String getViewTemplate()
{
return "plugins/findingProxy/findingProxy.ftl";
}
public void handleRequest(Database db, Tuple request)
{
try
{
if (request.getAction().equals("chooseModelAndStudy"))
{
listOfParameters.clear();
if (selectedPredictionModel != null)
{
Protocol p = db.find(Protocol.class,
new QueryRule(Protocol.NAME, Operator.EQUALS, selectedPredictionModel)).get(0);
List<Measurement> parameters = db.find(Measurement.class, new QueryRule(Measurement.NAME,
Operator.IN, p.getFeatures_Name()));
for (Measurement m : parameters)
{
String displayName = "";
if (m.getLabel() != null && !m.getLabel().equals(""))
{
displayName = m.getLabel();
}
else
{
displayName = m.getName();
}
listOfParameters.add(displayName);
}
}
selectedPredictionModel = request.getString("predictionModel");
selectedValidationStudy = request.getString("validationStudy");
stage = false;
}
else if (request.getAction().equals("customizedSearch"))
{
manualMappingResultTable.clear();
userDefinedQuery = request.getString("userDefinedQuery");
selectedManualParameter = request.getString("selectParameter");
System.out.println(userDefinedQuery);
if (request.getString("cutOffValue") != null && !request.getString("cutOffValue").equals(""))
{
cutOffValue = Double.parseDouble(request.getString("cutOffValue"));
}
else
{
cutOffValue = 50;
}
if (userDefinedQuery != null)
{
if (db.find(Measurement.class,
new QueryRule(Measurement.INVESTIGATION_NAME, Operator.EQUALS, selectedValidationStudy))
.size() > 0)
{
measurementsInStudy = db.find(Measurement.class, new QueryRule(Measurement.INVESTIGATION_NAME,
Operator.EQUALS, selectedValidationStudy));
}
List<String> query = new ArrayList<String>();
query.add(userDefinedQuery);
this.stringMatching(query, " ", request, true);
List<JSONObject> listOfJSON = new ArrayList<JSONObject>(makeHtmlTable(mappingResultAndSimiarity)
.values());
for (JSONObject eachJSON : listOfJSON)
{
manualMappingResultTable.add(eachJSON.toString());
}
}
}
else if (request.getAction().equals("addToExistingMapping"))
{
if (selectedValidationStudy != null && selectedValidationStudy.equals(""))
{
setMessages(new ScreenMessage("Please input a new name for this validation study", false));
}
else
{
Protocol validationStudyProtocol = null;
if (db.find(Protocol.class, new QueryRule(Protocol.NAME, Operator.EQUALS, selectedValidationStudy))
.size() != 0)
{
validationStudyProtocol = db.find(Protocol.class,
new QueryRule(Protocol.NAME, Operator.EQUALS, selectedValidationStudy)).get(0);
}
else
{
validationStudyProtocol = new Protocol();
validationStudyProtocol.setName(selectedValidationStudy);
// validationStudyProtocol.setInvestigation_Name("Validation Study");
validationStudyProtocol.setInvestigation_Name(selectedValidationStudy);
db.add(validationStudyProtocol);
}
for (Entry<String, MappingList> entry : mappingResultAndSimiarity.entrySet())
{
String originalQuery = entry.getKey();
if (request.getAction().equals("addToExistingMapping"))
{
originalQuery = request.getString("selectParameter");
}
List<LinkedInformation> listOfMatchedResult = entry.getValue().getSortedInformation();
List<String> listOFMatchedItem = new ArrayList<String>();
MappingMeasurement mapping = new MappingMeasurement();
for (LinkedInformation eachMatching : listOfMatchedResult)
{
String identifier = eachMatching.measurementName + "_" + entry.getKey();
if (request.getBool(identifier.replaceAll(" ", "_")) != null)
{
String dataItemName = eachMatching.measurementName;
listOFMatchedItem.add(dataItemName);
}
}
List<Measurement> measurements = new ArrayList<Measurement>();
if (listOFMatchedItem.size() > 0)
{
measurements = db.find(Measurement.class, new QueryRule(Measurement.NAME, Operator.IN,
listOFMatchedItem));
}
if (measurements.size() > 0)
{
List<Integer> measurementIds = new ArrayList<Integer>();
for (Measurement m : measurements)
{
measurementIds.add(m.getId());
}
if (measurementIds.size() > 0)
{
if (db.find(
Measurement.class,
new QueryRule(Measurement.NAME, Operator.EQUALS, originalQuery.replaceAll(" ",
"_") + "_" + selectedValidationStudy)).size() == 0)
{
Measurement m = new Measurement();
m.setName(originalQuery.toLowerCase().replaceAll(" ", "_") + "_"
+ selectedValidationStudy);
m.setInvestigation_Name(selectedValidationStudy);
db.add(m);
List<String> listOfFeatures = validationStudyProtocol.getFeatures_Name();
listOfFeatures.add(m.getName());
validationStudyProtocol.setFeatures_Name(listOfFeatures);
}
Query<MappingMeasurement> queryForMapping = db.query(MappingMeasurement.class);
queryForMapping.addRules(new QueryRule(MappingMeasurement.TARGET_NAME, Operator.EQUALS,
originalQuery.replaceAll(" ", "_") + "_" + selectedValidationStudy));
queryForMapping.addRules(new QueryRule(MappingMeasurement.MAPPING_NAME,
Operator.EQUALS, originalQuery));
if (queryForMapping.find().size() > 0)
{
mapping = queryForMapping.find().get(0);
for (Integer id : mapping.getFeature_Id())
{
if (!measurementIds.contains(id))
{
measurementIds.add(id);
}
}
mapping.setFeature_Id(measurementIds);
db.update(mapping);
}
else
{
mapping.setTarget_Name(originalQuery.toLowerCase().replaceAll(" ", "_") + "_"
+ selectedValidationStudy);
mapping.setInvestigation_Name(selectedValidationStudy);
mapping.setDataType("pairingrule");
mapping.setMapping_Name(originalQuery);
mapping.setFeature_Id(measurementIds);
db.add(mapping);
}
}
}
}
// TODO this needs to be revisited. Little bug here
db.update(validationStudyProtocol);
}
}
else if (request.getAction().equals("backToSelection"))
{
stage = true;
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
@Override
public void reload(Database db)
{
try
{
if (selectedPredictionModel == null)
{
listOfPredictionModel.clear();
List<Protocol> predictionModels = db.find(Protocol.class, new QueryRule(Protocol.INVESTIGATION_NAME,
Operator.EQUALS, "Prediction Model"));
for (Protocol p : predictionModels)
{
listOfPredictionModel.add(p.getName());
}
if (predictionModels.size() > 0)
{
selectedPredictionModel = listOfPredictionModel.get(0);
}
}
if (selectedValidationStudy == null)
{
listOfValidationStudy.clear();
List<Investigation> listOfInvestigation = db.find(Investigation.class, new QueryRule(
Investigation.NAME, Operator.NOT, "Prediction Model"));
for (Investigation inv : listOfInvestigation)
{
listOfValidationStudy.add(inv.getName());
}
if (listOfValidationStudy.size() > 0)
{
selectedValidationStudy = listOfValidationStudy.get(0);
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void stringMatching(List<String> listOfParameters, String separator, Tuple request, boolean cutOff)
throws Exception
{
mappingResultAndSimiarity.clear();
for (String eachParameter : listOfParameters)
{
List<String> expandedQuery = new ArrayList<String>();
List<String> finalQuery = new ArrayList<String>();
if (expandedQueries.containsKey(eachParameter.toLowerCase()))
{
expandedQuery = expandedQueries.get(eachParameter.toLowerCase());
}
else
{
expandedQuery.add(eachParameter.toLowerCase());
}
if (expandedQuery.contains("Prediction Model"))
{
System.out.println();
}
for (String eachQuery : expandedQuery)
{
String[] blocks = eachQuery.split(separator);
finalQuery.add(eachQuery.replaceAll(separator, " "));
if (request.getBool("baseline") != null)
{
finalQuery.add(eachQuery.replaceAll(separator, " ") + " baseline");
}
// else{
// finalQuery.add(eachQuery.replaceAll(separator, " "));
// }
for (int i = 0; i < blocks.length; i++)
{
if (!finalQuery.contains(blocks[i].toLowerCase())) finalQuery.add(blocks[i].toLowerCase());
if (request.getBool("baseline") != null)
{
if (!finalQuery.contains(blocks[i].toLowerCase() + " baseline")) finalQuery.add(blocks[i]
.toLowerCase() + " baseline");
}
// else{
// if(!finalQuery.contains(blocks[i].toLowerCase()))
// finalQuery.add(blocks[i].toLowerCase());
// }
}
}
parameterToExpandedQuery.put(eachParameter, finalQuery);
for (String eachQuery : finalQuery)
{
double maxSimilarity = 0;
String matchedDataItem = "";
String measurementName = "";
List<String> tokens = model.createNGrams(eachQuery.toLowerCase().trim(), true);
for (Measurement m : measurementsInStudy)
{
List<String> fields = new ArrayList<String>();
if (m.getDescription() != null && !m.getDescription().equals(""))
{
fields.add(m.getDescription());
if (m.getCategories_Name().size() > 0)
{
for (String categoryName : m.getCategories_Name())
{
fields.add(categoryName + " " + m.getDescription());
}
}
}
if (cutOff == true) fields.add(m.getName());
for (String question : fields)
{
List<String> dataItemTokens = model.createNGrams(question.toLowerCase().trim(), true);
double similarity = model.calculateScore(dataItemTokens, tokens);
if (cutOff == false && similarity > maxSimilarity)
{
if (m.getDescription() != null)
{
matchedDataItem = m.getDescription();
}
else
{
matchedDataItem = question;
}
maxSimilarity = similarity;
measurementName = m.getName();
}
if (cutOff == true && similarity >= cutOffValue)
{
MappingList temp = null;
if (mappingResultAndSimiarity.containsKey(eachParameter))
{
temp = mappingResultAndSimiarity.get(eachParameter);
}
else
{
temp = new MappingList();
}
if (m.getDescription() != null)
{
matchedDataItem = m.getDescription();
}
else
{
matchedDataItem = question;
}
temp.add(eachQuery, matchedDataItem, similarity, m.getName());
mappingResultAndSimiarity.put(eachParameter, temp);
}
}
}
if (cutOff == false)
{
MappingList temp = null;
if (mappingResultAndSimiarity.containsKey(eachParameter))
{
temp = mappingResultAndSimiarity.get(eachParameter);
}
else
{
temp = new MappingList();
}
temp.add(eachQuery, matchedDataItem, maxSimilarity, measurementName);
mappingResultAndSimiarity.put(eachParameter, temp);
}
}
}
}
public HashMap<String, JSONObject> makeHtmlTable(HashMap<String, MappingList> mappingResultAndSimiarity)
throws Exception
{
HashMap<String, JSONObject> parameterWithHtmlTable = new HashMap<String, JSONObject>();
for (String eachOriginalQuery : mappingResultAndSimiarity.keySet())
{
MappingList map = mappingResultAndSimiarity.get(eachOriginalQuery);
List<LinkedInformation> links = map.getSortedInformation();
int size = links.size();
String tableId = eachOriginalQuery + " table";
String matchingResult = "<table class='dataResult' id='" + tableId.replaceAll(" ", "_") + "' border='1'>";
Map<String, Map<String, Double>> uniqueMapping = new HashMap<String, Map<String, Double>>();
matchingResult += "<tr style='background: blue; color: white;'>"
+ "<td>Data Item</td><td>Description</td><td>Select mapping</td></tr>";
for (int i = size; i > 0; i--)
{
LinkedInformation eachRow = links.get(i - 1);
String expandedQuery = eachRow.expandedQuery;
String matchedItem = eachRow.matchedItem;
Double similarity = eachRow.similarity;
String measurementName = eachRow.measurementName;
String identifier = measurementName + "_" + eachOriginalQuery;
if (!uniqueMapping.containsKey(identifier))
{
Map<String, Double> queryAndSimilarity = new HashMap<String, Double>();
queryAndSimilarity.put(expandedQuery, similarity);
uniqueMapping.put(identifier, queryAndSimilarity);
matchingResult += "<tr class='clickRow' border='1' id='" + identifier.replaceAll(" ", "_")
+ "' style='cursor:pointer'>" + "<td>" + measurementName + "</td>" + "<td><div id='"
+ identifier.replaceAll(" ", "_") + "_div'>" + matchedItem
+ "</div></td><td><input type='checkbox' name='" + identifier.replaceAll(" ", "_")
+ "'></td></tr>";
}
else
{
Map<String, Double> queryAndSimilarity = uniqueMapping.get(identifier);
queryAndSimilarity.put(expandedQuery, similarity);
uniqueMapping.put(identifier, queryAndSimilarity);
}
// System.out.print(eachOriginalQuery + "\t" + expandedQuery +
// "\t" + matchedItem + "\t" + similarity);
// System.out.println();
}
matchingResult += "</table>";
String executiveScript = "";
if (maxQuerySize < uniqueMapping.keySet().size())
{
maxQuerySize = uniqueMapping.keySet().size();
}
for (String identifier : uniqueMapping.keySet())
{
if (uniqueMapping.get(identifier).size() > 0)
{
String table = "<table class='insertTable' id='" + identifier.replaceAll(" ", "_")
+ "_table' style='display:none;position:absolute;'>"
+ "<tr><td>expanded query</td><td>similarity</td></tr>";
for (Entry<String, Double> entry : uniqueMapping.get(identifier).entrySet())
{
String expandedQuery = entry.getKey();
Double similarity = entry.getValue();
table += "<tr class='insertTable'><td>" + expandedQuery + "</td><td>" + similarity
+ "</td></tr>";
}
table += "</table>";
executiveScript += table;
}
}
JSONObject json = new JSONObject();
json.put("term", eachOriginalQuery);
json.put("result", matchingResult);
json.put("script", executiveScript);
// if(!listOfParameters.contains(executiveScript))
// listOfScripts.add(executiveScript);
parameterWithHtmlTable.put(eachOriginalQuery, json);
}
// return parameterWithHtmlTable;
return parameterWithHtmlTable;
}
public List<String> getListOfValidationStudy()
{
return listOfValidationStudy;
}
public List<String> getListOfParameters()
{
return listOfParameters;
}
public String getSelectedValidationStudyName()
{
return selectedValidationStudy;
}
public String getSelectedPredictionModel()
{
return selectedPredictionModel;
}
public List<String> getlistOfPredictionModel()
{
return listOfPredictionModel;
}
public List<String> getManualMappingResultTable()
{
return manualMappingResultTable;
}
public String getSelectedManualParameter()
{
return selectedManualParameter;
}
public boolean getStage()
{
return stage;
}
public String getUserDefinedQuery()
{
return userDefinedQuery;
}
public List<String> getListOfJSON()
{
return listOfJSON;
}
@Override
public boolean isVisible()
{
// you can use this to hide this plugin, e.g. based on user rights.
// e.g.
// if(!this.getLogin().hasEditPermission(myEntity)) return false;
if (!this.getLogin().isAuthenticated())
{
return false;
}
return true;
}
}