/*
* This file is part of ADDIS (Aggregate Data Drug Information System).
* ADDIS is distributed from http://drugis.org/.
* Copyright © 2009 Gert van Valkenhoef, Tommi Tervonen.
* Copyright © 2010 Gert van Valkenhoef, Tommi Tervonen, Tijs Zwinkels,
* Maarten Jacobs, Hanno Koeslag, Florin Schimbinschi, Ahmad Kamal, Daniel
* Reid.
* Copyright © 2011 Gert van Valkenhoef, Ahmad Kamal, Daniel Reid, Florin
* Schimbinschi.
* Copyright © 2012 Gert van Valkenhoef, Daniel Reid, Joël Kuiper, Wouter
* Reckman.
* Copyright © 2013 Gert van Valkenhoef, Joël Kuiper.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.drugis.addis.imports;
import static org.apache.commons.collections15.CollectionUtils.find;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.bind.JAXBContext;
import org.apache.commons.collections15.CollectionUtils;
import org.apache.commons.collections15.Predicate;
import org.apache.commons.collections15.PredicateUtils;
import org.apache.commons.lang.StringUtils;
import org.drugis.addis.entities.AdverseEvent;
import org.drugis.addis.entities.Arm;
import org.drugis.addis.entities.BasicContinuousMeasurement;
import org.drugis.addis.entities.BasicMeasurement;
import org.drugis.addis.entities.BasicRateMeasurement;
import org.drugis.addis.entities.BasicStudyCharacteristic;
import org.drugis.addis.entities.BasicStudyCharacteristic.Allocation;
import org.drugis.addis.entities.BasicStudyCharacteristic.Blinding;
import org.drugis.addis.entities.ContinuousVariableType;
import org.drugis.addis.entities.DrugTreatment;
import org.drugis.addis.entities.Endpoint;
import org.drugis.addis.entities.Epoch;
import org.drugis.addis.entities.Indication;
import org.drugis.addis.entities.Note;
import org.drugis.addis.entities.ObjectWithNotes;
import org.drugis.addis.entities.PopulationCharacteristic;
import org.drugis.addis.entities.PredefinedActivity;
import org.drugis.addis.entities.PubMedId;
import org.drugis.addis.entities.PubMedIdList;
import org.drugis.addis.entities.RateVariableType;
import org.drugis.addis.entities.Source;
import org.drugis.addis.entities.Study;
import org.drugis.addis.entities.StudyActivity;
import org.drugis.addis.entities.StudyOutcomeMeasure;
import org.drugis.addis.entities.TreatmentActivity;
import org.drugis.addis.entities.Variable;
import org.drugis.addis.entities.WhenTaken;
import org.drugis.addis.entities.WhenTaken.RelativeTo;
import org.drugis.addis.util.EntityUtil;
import org.drugis.common.EqualsUtil;
import org.drugis.common.gui.ErrorDialog;
public class ClinicaltrialsImporter {
private static final String INCLUSION_CRITERIA = "inclusion criteria";
private static final String EXCLUSION_CRITERIA = "exclusion criteria";
public static Study getClinicaltrialsData(String url, boolean importResults) throws MalformedURLException, IOException {
Study study = new Study("", new Indication(0l, ""));
getClinicaltrialsData(study ,url, importResults);
return study;
}
static void getClinicaltrialsData(Study study, String url, boolean importResults) throws IOException {
URLConnection conn = new URL(url).openConnection();
conn.setRequestProperty("Accept", "application/xml");
getClinicaltrialsData(study, conn.getInputStream(), importResults);
}
static void getClinicaltrialsData(Study study, InputStream is, boolean importResults) {
JAXBContext jc;
try {
jc = JAXBContext.newInstance("org.drugis.addis.imports");
ClinicalStudy studyImport = (ClinicalStudy) jc.createUnmarshaller().unmarshal(is);
new ClinicaltrialsImporter(study, studyImport, importResults).importStudy();
} catch (Exception e) {
String exceptionTitle = "Could not complete import from ClinicalTrials.gov";
StringBuilder errorMessage = new StringBuilder();
errorMessage.append("Something went wrong while importing from ClinicalTrials.gov.");
if (importResults) {
errorMessage.append(" Please try again without importing results.");
}
errorMessage.append("\n\nWhen reporting this problem please include the NCT-ID where possible.");
ErrorDialog.showDialog(e, exceptionTitle, errorMessage.toString(), true);
}
}
private Study d_study;
private ClinicalStudy d_studyImport;
private boolean d_importResults;
private Epoch d_mainEpoch;
public ClinicaltrialsImporter(Study study, ClinicalStudy studyImport, boolean importResults) {
d_study = study;
d_studyImport = studyImport;
d_importResults = importResults;
}
public void importStudy() {
importStudyCharacteristics();
importReferences();
// Add default epochs + the study arms
d_mainEpoch = new Epoch("Main phase", null);
d_study.getEpochs().add(d_mainEpoch);
importArms();
if (d_study.getCharacteristic(BasicStudyCharacteristic.ALLOCATION).equals(Allocation.RANDOMIZED)) {
addRandomizationEpochAndActivity();
}
importStudyOutcomeMeasures();
if (shouldImportResults()) {
importAdverseEvents();
importPopulationCharacteristics();
}
// Import date & Source.
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.CREATION_DATE,
objectWithNote(new Date(), d_studyImport.getRequiredHeader().getDownloadDate().trim()));
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.SOURCE,
objectWithNote(Source.CLINICALTRIALS, d_studyImport.getRequiredHeader().getUrl().trim()));
}
/**
* @return true if results import has been requested AND results are available.
*/
private boolean shouldImportResults() {
return d_importResults && d_studyImport.getClinicalResults() != null;
}
private void importStudyCharacteristics() {
// ID (& ID note =study url)
d_study.setName(d_studyImport.getIdInfo().getNctId());
d_study.getNotes().add(new Note(Source.CLINICALTRIALS, d_studyImport.getIdInfo().getNctId()));
// Title
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.TITLE,
objectWithNote(d_studyImport.getBriefTitle().trim(), createTitleNote(d_studyImport)));
// Study Centers
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.CENTERS,
objectWithNote(d_studyImport.getLocation().size(), createCentersNote(d_studyImport)));
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.ALLOCATION,
objectWithNote(guessAllocation(d_studyImport), d_studyImport.getStudyDesign().trim()));
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.BLINDING,
objectWithNote(guessBlinding(d_studyImport), d_studyImport.getStudyDesign().trim()));
// Objective
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.OBJECTIVE,
objectWithNote(deindent(d_studyImport.getBriefSummary().getTextblock()),
deindent(d_studyImport.getBriefSummary().getTextblock())));
// Indication note
d_study.getIndicationWithNotes().getNotes().add(new Note(Source.CLINICALTRIALS, createIndicationNote(d_studyImport)));
// Start and end date
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.STUDY_START,
objectWithNote(guessDate(d_studyImport.getStartDate()), d_studyImport.getStartDate() != null ? d_studyImport.getStartDate().getContent() : ""));
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.STUDY_END,
objectWithNote(guessDate(d_studyImport.getCompletionDate()), d_studyImport.getCompletionDate() != null ? d_studyImport.getCompletionDate().getContent() : ""));
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.STATUS,
objectWithNote(guessStatus(d_studyImport), d_studyImport.getOverallStatus().trim()));
String criteria = deindent(d_studyImport.getEligibility().getCriteria().getTextblock());
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.INCLUSION,
objectWithNote(guessInclusionCriteria(criteria), criteria));
d_study.setCharacteristicWithNotes(BasicStudyCharacteristic.EXCLUSION,
objectWithNote(guessExclusion(criteria), criteria));
}
private void importReferences() {
PubMedIdList list = (PubMedIdList) d_study.getCharacteristic(BasicStudyCharacteristic.PUBMED);
for (ReferenceStruct ref : d_studyImport.getReference()) {
if (ref.getPMID() != null) {
list.add(new PubMedId(ref.getPMID()));
}
}
if (d_importResults && d_studyImport.getResultsReference() != null) {
for (ReferenceStruct ref : d_studyImport.getResultsReference()) {
if (ref.getPMID() != null) {
list.add(new PubMedId(ref.getPMID()));
}
}
}
}
private WhenTaken createDefaultWhenTaken(StudyOutcomeMeasure<? extends Variable> som) {
WhenTaken wt = new WhenTaken(EntityUtil.createDuration("P0D"), RelativeTo.BEFORE_EPOCH_END, d_mainEpoch);
wt.commit();
som.getWhenTaken().add(wt);
return wt;
}
private void importArms() {
// Add note to the study-arms.
Map<String,Arm> armLabels = new HashMap<String,Arm>();
for(ArmGroupStruct ag : d_studyImport.getArmGroup()){
Arm arm = new Arm(ag.getArmGroupLabel(), 0);
d_study.getArms().add(arm);
StringBuilder noteBuilder = new StringBuilder();
noteBuilder.append(formatIfAny("Arm Name", ag.getArmGroupLabel(), ""));
noteBuilder.append(formatIfAny("Arm Type", ag.getArmGroupType(), "\n"));
noteBuilder.append(formatIfAny("Arm Description", ag.getDescription(), "\n"));
arm.getNotes().add(new Note(Source.CLINICALTRIALS, noteBuilder.toString()));
armLabels.put(ag.getArmGroupLabel(), arm);
}
// Add interventions to the study-arms.
List<String> interventionNames = new ArrayList<String>();
for(InterventionStruct i : d_studyImport.getIntervention()) {
interventionNames.add(i.getInterventionName());
}
uniqueify(interventionNames);
for (int i = 0; i < d_studyImport.getIntervention().size(); i++) {
InterventionStruct intervention = d_studyImport.getIntervention().get(i);
StringBuilder noteBuilder = new StringBuilder();
noteBuilder.append(formatIfAny("Intervention Name", intervention.getInterventionName(), "\n"));
noteBuilder.append(formatIfAny("Intervention Type", intervention.getInterventionType(), "\n"));
noteBuilder.append(formatIfAny("Intervention Description", intervention.getDescription(), "\n"));
boolean notAssigned = true;
for (String label : intervention.getArmGroupLabel()) {
StudyActivity act = new StudyActivity(interventionNames.get(i), new TreatmentActivity(new DrugTreatment(null, null)));
d_study.getStudyActivities().add(act);
act.getNotes().add(new Note(Source.CLINICALTRIALS, intervention.getDescription()));
Arm arm = armLabels.get(label);
if (arm != null) {
notAssigned = false;
Note note = arm.getNotes().get(0);
note.setText(note.getText() + "\n" + noteBuilder.toString());
d_study.setStudyActivityAt(arm, d_mainEpoch, act);
}
}
// Add the intervention note to all arms if it can't be mapped to any single arm
if (notAssigned) {
for (Arm arm : d_study.getArms()) {
Note note = arm.getNotes().get(0);
note.setText(note.getText() + "\n" + noteBuilder.toString());
}
}
// Add Arm sizes to arms
if (shouldImportResults()) {
BaselineStruct baseline = d_studyImport.getClinicalResults().getBaseline();
for (final GroupStruct xmlArm : baseline.groupList.group) {
Arm arm = findArmWithName(d_study, xmlArm.getTitle());
if (arm != null) {
MeasureCategoryStruct measures = baseline.getMeasureList().measure.get(0).categoryList.category.get(0);
MeasurementStruct measurement = findMeasurement(xmlArm.groupId, measures.getMeasurementList().measurement);
if (measurement != null) {
arm.setSize(convertToInteger(measurement.getValueAttribute()));
}
}
}
}
}
}
private void addRandomizationEpochAndActivity() {
Epoch randomizationEpoch = new Epoch("Randomization", null);
d_study.getEpochs().add(0, randomizationEpoch);
StudyActivity randomizationActivity = new StudyActivity("Randomization", PredefinedActivity.RANDOMIZATION);
d_study.getStudyActivities().add(randomizationActivity);
for (Arm a: d_study.getArms()) {
d_study.setStudyActivityAt(a, randomizationEpoch, randomizationActivity);
}
}
private void importStudyOutcomeMeasures() {
for (ProtocolOutcomeStruct outcome : d_studyImport.getPrimaryOutcome()) {
importStudyOutcomeMeasure(outcome, true);
}
for (ProtocolOutcomeStruct outcome : d_studyImport.getSecondaryOutcome()) {
importStudyOutcomeMeasure(outcome, false);
}
}
private void importStudyOutcomeMeasure(ProtocolOutcomeStruct outcome, boolean isPrimary) {
StudyOutcomeMeasure<Endpoint> som = new StudyOutcomeMeasure<Endpoint>(Endpoint.class);
som.setIsPrimary(isPrimary);
StringBuilder noteBuilder = new StringBuilder(outcome.getMeasure());
noteBuilder.append(formatIfAny("Description", outcome.getDescription(), "\n"));
noteBuilder.append(formatIfAny("Time frame", outcome.getTimeFrame(), "\n"));
noteBuilder.append(formatIfAny("Safety issue", outcome.getSafetyIssue(), "\n"));
som.getNotes().add(new Note(Source.CLINICALTRIALS, noteBuilder.toString()));
WhenTaken wt = createDefaultWhenTaken(som);
d_study.getEndpoints().add(som);
if (shouldImportResults()) {
importMeasurements(outcome, som, wt);
}
}
private void importMeasurements(final ProtocolOutcomeStruct outcome, StudyOutcomeMeasure<Endpoint> som, WhenTaken wt) {
List<ResultsOutcomeStruct> outcomes = d_studyImport.getClinicalResults().getOutcomeList().outcome;
ResultsOutcomeStruct results = find(outcomes, new Predicate<ResultsOutcomeStruct>() {
public boolean evaluate(ResultsOutcomeStruct object) {
return object.getTitle().equals(outcome.getMeasure());
}
});
importMeasurements(som, wt, results.measureList.measure, results.getGroupList().group);
}
private void importMeasurements(StudyOutcomeMeasure<? extends Variable> som, WhenTaken wt, List<MeasureStruct> measurements, List<GroupStruct> groups) {
for (GroupStruct xmlArm : groups) {
// Fails for multiple epochs since we treat them as categorical variables (seems to be the default)
MeasureStruct total = measurements.get(0);
MeasureStruct second = measurements.get(1);
List<MeasureCategoryStruct> categories = second.getCategoryList().getCategory();
if (categories.size() == 1) {
if (total.getParam().equals("Number") && second.getParam().equals("Number")) {
addBasicRateMeasurement(d_study, som, wt, xmlArm, measurements);
}
if (total.getParam().equals("Number") && !second.getParam().equals("Number")) {
addContinuousMeasurement(d_study, som, wt, xmlArm, measurements);
}
} else if (categories.size() > 1) { // Categorical variable
addFrequencyMeasurement(d_study, som, wt, xmlArm, second);
}
}
}
private void importAdverseEvents() {
ReportedEventsStruct reportedEvents = d_studyImport.clinicalResults.reportedEvents;
for (EventCategoryStruct sae : reportedEvents.seriousEvents.categoryList.category) {
importEvents(reportedEvents, sae);
}
for (EventCategoryStruct ae : reportedEvents.otherEvents.categoryList.category) {
importEvents(reportedEvents, ae);
}
}
private void importEvents(ReportedEventsStruct reportedEvents, EventCategoryStruct categories) {
for (EventStruct event : categories.getEventList().event) {
StudyOutcomeMeasure<AdverseEvent> som = new StudyOutcomeMeasure<AdverseEvent>(AdverseEvent.class);
String noteStr = event.getSubTitle().value + " (" + categories.title + ")";
noteStr = addIfAny(noteStr, "Description", event.description);
noteStr = addIfAny(noteStr, "Assessment", event.assessment);
WhenTaken wt = createDefaultWhenTaken(som);
d_study.getAdverseEvents().add(som);
som.getNotes().add(new Note(Source.CLINICALTRIALS, noteStr));
for (final EventCountsStruct counts : event.getCounts()) {
GroupStruct xmlArm = find(reportedEvents.groupList.group, new Predicate<GroupStruct>() {
public boolean evaluate(GroupStruct object) {
return object.getGroupId().equalsIgnoreCase(counts.groupId);
}});
Arm arm = findArmWithName(d_study, xmlArm.getTitle());
if (arm == null && !EqualsUtil.equal(xmlArm.getTitle(), "Total")) {
continue;
}
BasicRateMeasurement m = buildRateMeasurement(counts.subjectsAtRisk, counts.subjectsAffected, false);
som.getValue().setVariableType(new RateVariableType());
d_study.setMeasurement(som, arm, wt, m);
}
}
}
private void importPopulationCharacteristics() {
BaselineStruct baseline = d_studyImport.getClinicalResults().getBaseline();
List<MeasureStruct> measureList = baseline.getMeasureList().measure;
for (MeasureStruct popchar : measureList.subList(1, measureList.size())) {
StudyOutcomeMeasure<PopulationCharacteristic> som = new StudyOutcomeMeasure<PopulationCharacteristic>(PopulationCharacteristic.class);
d_study.getPopulationChars().add(som);
StringBuilder builder = new StringBuilder(popchar.getTitle());
builder.append(formatIfAny("Description", popchar.getDescription(), "\n"));
builder.append(formatIfAny("Units", popchar.getUnits(), "\n"));
som.getNotes().add(new Note(Source.CLINICALTRIALS, builder.toString()));
// Baseline measurements: at start of treatment
WhenTaken wt = new WhenTaken(EntityUtil.createDuration("P0D"), RelativeTo.FROM_EPOCH_START, d_mainEpoch);
wt.commit();
som.getWhenTaken().add(wt);
importMeasurements(som, wt, Arrays.asList(measureList.get(0), popchar), baseline.getGroupList().group);
}
}
private static ObjectWithNotes<Object> objectWithNote(Object val, String note) {
ObjectWithNotes<Object> obj = new ObjectWithNotes<Object>(val);
obj.getNotes().add(new Note(Source.CLINICALTRIALS, note != null ? note : "N/A"));
return obj;
}
/**
* Remove indentation and text wrapping from a text field.
* All leading and trailing whitespace is removed from each line of input.
* Single newlines are removed, double newlines are retained.
*/
private static String deindent(String textblock) {
BufferedReader bufferedReader = new BufferedReader(new StringReader(textblock.trim()));
StringBuilder builder = new StringBuilder();
try {
boolean first = true;
for (String line = bufferedReader.readLine(); line != null; line = bufferedReader.readLine()) {
line = line.trim();
if (!line.isEmpty()) {
builder.append((first ? "" : " ") + line);
first = false;
} else {
builder.append("\n\n");
first = true;
}
}
bufferedReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
return builder.toString();
}
private static void addFrequencyMeasurement(
Study study,
StudyOutcomeMeasure<? extends Variable> som,
WhenTaken wt,
GroupStruct xmlArm,
MeasureStruct measurement) {
final Arm arm = findArmWithName(study, xmlArm.getTitle());
if (arm == null && !EqualsUtil.equal(xmlArm.getTitle(), "Total")) {
return;
}
/*
List<MeasureCategoryStruct> categories = measurement.getCategoryList().getCategory();
List<String> categoryNames = new LinkedList<String>();
Map<String, Integer> frequencies = new HashMap<String, Integer>();
for (int i = 0; i < categories.size(); i++) {
MeasureCategoryStruct category = categories.get(i);
String name = category.subTitle;
categoryNames.add(name);
int frequency = Integer.parseInt(getMeasurementForArm(xmlArm.groupId, i, measurement).getValueAttribute());
frequencies.put(name, frequency);
}
som.getValue().setVariableType(new CategoricalVariableType(categoryNames));
study.setMeasurement(som, arm, wt, new FrequencyMeasurement(categoryNames, frequencies));
*/
}
private static void addBasicRateMeasurement(
final Study study,
final StudyOutcomeMeasure<? extends Variable> som,
final WhenTaken wt,
GroupStruct xmlArm,
List<MeasureStruct> measurements) {
final Arm arm = findArmWithName(study, xmlArm.getTitle());
if (arm == null && !EqualsUtil.equal(xmlArm.getTitle(), "Total")) {
return;
}
final String xmlArmId = xmlArm.groupId;
BasicMeasurement meas = createBasicRateMeasurement(
getMeasurementForArm(xmlArmId, 0, measurements.get(0)), // Total number of participants
getMeasurementForArm(xmlArmId, 0, measurements.get(1)), // Number of responders
measurements.get(1));
som.getValue().setVariableType(new RateVariableType());
study.setMeasurement(som, arm, wt, meas);
}
private static void addContinuousMeasurement(
final Study study,
final StudyOutcomeMeasure<? extends Variable> som,
final WhenTaken wt,
GroupStruct xmlArm,
List<MeasureStruct> measurements) {
final Arm arm = findArmWithName(study, xmlArm.getTitle());
if (arm == null && !EqualsUtil.equal(xmlArm.getTitle(), "Total")) {
return;
}
final String xmlArmId = xmlArm.groupId;
MeasureStruct measure = measurements.get(1);
if(!(measure.param.equalsIgnoreCase("Mean") || measure.param.equalsIgnoreCase("Least Squares Mean"))) {
System.err.println(("Cannot import mean, not of type Mean or Least Squares Mean, but " + measure.param));
return;
}
BasicMeasurement meas = createBasicContinuousMeasurement(
getMeasurementForArm(xmlArmId, 0, measurements.get(0)), // Total number of participants
getMeasurementForArm(xmlArmId, 0, measurements.get(1)), // Mean and std.dev
measure);
som.getValue().setVariableType(new ContinuousVariableType());
study.setMeasurement(som, arm, wt, meas);
}
private static BasicMeasurement createBasicContinuousMeasurement(
MeasurementStruct totalStruct,
MeasurementStruct measurementStruct,
MeasureStruct measure) {
int total = Integer.parseInt(totalStruct.valueAttribute);
Double mean = convertToDouble(measurementStruct.valueAttribute);
Double stdDev = convertToDouble(measurementStruct.spread);
if (measure.dispersion.equals("Standard Error") && stdDev != null) {
stdDev = stdDev * Math.sqrt(total);
} else if (!measure.dispersion.equals("Standard Deviation")) {
System.err.println("Cannot convert dispersion in " + measure.title + " of type" + measure.dispersion);
return null;
}
return new BasicContinuousMeasurement(mean, stdDev, total);
}
private static BasicMeasurement createBasicRateMeasurement(
MeasurementStruct totalStruct,
MeasurementStruct rateStruct,
MeasureStruct rateMeasure) {
return buildRateMeasurement(totalStruct.valueAttribute, rateStruct.valueAttribute, StringUtils.containsIgnoreCase(rateMeasure.units, "Percentage"));
}
private static BasicRateMeasurement buildRateMeasurement(String total, String rate, boolean isPercentage) {
Double totalValue = total == null ? null : convertToDouble(total);
Double rateValue = rate == null ? null : convertToDouble(rate);
if (totalValue == null && rateValue != null) {
return new BasicRateMeasurement((int)Math.round(rateValue), null);
} else if (totalValue != null && rateValue == null) {
return new BasicRateMeasurement(null, (int)Math.round(totalValue));
} else if (rateValue != null && totalValue != null ) {
return new BasicRateMeasurement((int)Math.round((isPercentage ? ((rateValue / 100) * totalValue) : rateValue)), (int)Math.round(totalValue));
}
return new BasicRateMeasurement();
}
private static Double convertToDouble(String text) {
return (text != null && !text.toLowerCase().contains("na")) ? Double.parseDouble(text) : null;
}
private static Integer convertToInteger(String text) {
return (text != null && !text.toLowerCase().contains("na")) ? Integer.parseInt(text) : null;
}
private static MeasurementStruct getMeasurementForArm(final String xmlArmId, int categoryIdx, MeasureStruct measure) {
List<MeasurementStruct> measureMeasurements = measure.getCategoryList().getCategory().get(categoryIdx).measurementList.measurement;
return findMeasurement(xmlArmId, measureMeasurements);
}
private static MeasurementStruct findMeasurement(final String xmlArmId, List<MeasurementStruct> measurements) {
return find(measurements, new Predicate<MeasurementStruct>() {
public boolean evaluate(MeasurementStruct object) {
return object.getGroupId().equalsIgnoreCase(xmlArmId);
}
});
}
private static Arm findArmWithName(final Study study, final String armName) {
return find(study.getArms(), new Predicate<Arm>() {
public boolean evaluate(Arm object) {
return object.getName().equalsIgnoreCase(armName);
}
});
}
private static String formatIfAny(String fieldName, String value, String separator) {
if (value != null && !value.equals("")) {
return separator + fieldName + ": " + value;
}
return "";
}
private static String addIfAny(String noteStr, String fieldName, String value) {
return noteStr + formatIfAny(fieldName, value, "\n\n");
}
private static void uniqueify(List<String> names) {
for (int i = 0; i < names.size() - 1; ++i) {
List<String> sublist = names.subList(i + 1, names.size());
String name = names.get(i);
if (sublist.contains(name)) {
names.set(i, name + " " + i);
for (int idx = sublist.indexOf(name); idx > -1; idx = sublist.indexOf(name)) {
sublist.set(idx, name + " " + (i + 1 + idx));
}
}
}
}
private static String guessExclusion(String criteria) {
int exclusionStart = criteria.toLowerCase().indexOf(EXCLUSION_CRITERIA) + EXCLUSION_CRITERIA.length()+1;
String exclusion = null;
if(criteria.toLowerCase().indexOf(EXCLUSION_CRITERIA) != -1)
exclusion = criteria.substring(exclusionStart).trim();
return exclusion;
}
private static String guessInclusionCriteria(String criteria) {
int inclusionStart = criteria.toLowerCase().indexOf(INCLUSION_CRITERIA) + INCLUSION_CRITERIA.length()+1;
int inclusionEnd = criteria.toLowerCase().indexOf(EXCLUSION_CRITERIA);
if(inclusionEnd == -1)
inclusionEnd = criteria.length()-1;
String inclusion = null;
if(criteria.toLowerCase().indexOf(INCLUSION_CRITERIA) != -1)
inclusion = criteria.substring(inclusionStart, inclusionEnd).trim();
return inclusion;
}
private static BasicStudyCharacteristic.Status guessStatus(
ClinicalStudy studyImport) {
BasicStudyCharacteristic.Status status = BasicStudyCharacteristic.Status.UNKNOWN;
if (studyImport.getOverallStatus().toLowerCase().contains("recruiting"))
status = BasicStudyCharacteristic.Status.RECRUITING;
else if (studyImport.getOverallStatus().contains("Enrolling"))
status = BasicStudyCharacteristic.Status.RECRUITING;
else if (studyImport.getOverallStatus().contains("Active"))
status = BasicStudyCharacteristic.Status.ACTIVE;
else if (studyImport.getOverallStatus().contains("Completed"))
status = BasicStudyCharacteristic.Status.COMPLETED;
else if (studyImport.getOverallStatus().contains("Available"))
status = BasicStudyCharacteristic.Status.COMPLETED;
return status;
}
private static Date guessDate(DateStruct startDate2) {
Date startDate = null;
SimpleDateFormat sdf = new SimpleDateFormat("MMM yyyy");
try {
if (startDate2 != null)
startDate = sdf.parse(startDate2.getContent());
} catch (ParseException e) {
System.err.println("ClinicalTrialsImporter:: Couldn't parse date. Left empty.");
}
return startDate;
}
private static String createIndicationNote(ClinicalStudy studyImport) {
String out = "";
for(String s : studyImport.getCondition()){
out = out+s+"\n";
}
out = out.trim();
return out;
}
private static BasicStudyCharacteristic.Blinding guessBlinding(
ClinicalStudy studyImport) {
BasicStudyCharacteristic.Blinding blinding = Blinding.UNKNOWN;
if (designContains(studyImport, "open label"))
blinding = BasicStudyCharacteristic.Blinding.OPEN;
else if (designContains(studyImport, "single blind"))
blinding = BasicStudyCharacteristic.Blinding.SINGLE_BLIND;
else if (designContains(studyImport, "double blind"))
blinding = BasicStudyCharacteristic.Blinding.DOUBLE_BLIND;
else if (designContains(studyImport, "triple blind"))
blinding = BasicStudyCharacteristic.Blinding.TRIPLE_BLIND;
return blinding;
}
private static BasicStudyCharacteristic.Allocation guessAllocation(
ClinicalStudy studyImport) {
Allocation allocation = Allocation.UNKNOWN;
if (designContains(studyImport, "non-randomized"))
allocation = Allocation.NONRANDOMIZED;
else if (designContains(studyImport, "randomized"))
allocation = Allocation.RANDOMIZED;
return allocation;
}
private static String createCentersNote(ClinicalStudy studyImport) {
StringBuilder noteBuilder = new StringBuilder();
for (LocationStruct l : studyImport.getLocation()) {
FacilityStruct f = l.getFacility();
AddressStruct a = f.getAddress();
List<String> fields = new ArrayList<String>(Arrays.asList(new String[] {
f.getName(), a.getZip(), a.getCity(), a.getState(), a.getCountry()
}));
CollectionUtils.filter(fields, PredicateUtils.notNullPredicate());
noteBuilder.append(StringUtils.join(fields, ", "));
noteBuilder.append('\n');
}
return noteBuilder.toString();
}
private static String createTitleNote(ClinicalStudy studyImport) {
StringBuilder titleNote = new StringBuilder();
titleNote.append("Brief title: ");
if (studyImport.getBriefTitle() != null) {
titleNote.append(studyImport.getBriefTitle().trim());
} else {
titleNote.append("N/A");
}
titleNote.append("\n\n");
titleNote.append("Official title: ");
if (studyImport.getOfficialTitle() != null) {
titleNote.append(studyImport.getOfficialTitle().trim());
} else {
titleNote.append("N/A");
}
return titleNote.toString();
}
private static boolean designContains(ClinicalStudy studyImport, String contains) {
return studyImport.getStudyDesign().toLowerCase().contains(contains) || studyImport.getStudyDesign().toLowerCase().contains(contains.replace(' ', '-'));
}
}