/*
* OpenClinica is distributed under the GNU Lesser General Public License (GNU
* LGPL).
*
* For details see: http://www.openclinica.org/license copyright 2003-2005 Akaza
* Research
*
*/
package org.akaza.openclinica.logic.odmExport;
import org.akaza.openclinica.bean.extract.DatasetBean;
import org.akaza.openclinica.bean.managestudy.StudyBean;
import org.akaza.openclinica.bean.managestudy.StudyEventDefinitionBean;
import org.akaza.openclinica.bean.odmbeans.ElementRefBean;
import org.akaza.openclinica.bean.odmbeans.GlobalVariablesBean;
import org.akaza.openclinica.bean.odmbeans.MetaDataVersionBean;
import org.akaza.openclinica.bean.odmbeans.MetaDataVersionIncludeBean;
import org.akaza.openclinica.bean.odmbeans.ODMBean;
import org.akaza.openclinica.bean.odmbeans.OdmStudyBean;
import org.akaza.openclinica.bean.odmbeans.RangeCheckBean;
import org.akaza.openclinica.bean.service.StudyParameterValueBean;
import org.akaza.openclinica.dao.extract.OdmExtractDAO;
import org.akaza.openclinica.dao.hibernate.RuleSetRuleDao;
import org.akaza.openclinica.dao.managestudy.StudyDAO;
import org.akaza.openclinica.dao.service.StudyConfigService;
import org.akaza.openclinica.dao.service.StudyParameterValueDAO;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
import javax.sql.DataSource;
/**
* A class for ODM metadata of one study.
*
* @author ywang (May, 2009)
*/
public class MetadataUnit extends OdmUnit {
private OdmStudyBean odmStudy;
private StudyBean parentStudy;
private RuleSetRuleDao ruleSetRuleDao;
public static final String FAKE_STUDY_NAME ="OC_FORM_LIB_STUDY";
public static final String FAKE_STUDY_OID = "OC_FORM_LIB";
public static final String FAKE_STUDY_EVENT_OID = "OC_FORM_LIB_SE";
public static final String FAKE_SE_NAME = "OC_FORM_LIB_SE_NAME";
public static final String FAKE_SE_REPEATING="NO";
public static final String FAKE_SE_TYPE ="SCHEDULED";
public static final String FAKE_FR_MANDATORY = "No";
public MetadataUnit() {
}
public MetadataUnit(DataSource ds, StudyBean study, int category) {
super(ds, study, category);
this.odmStudy = new OdmStudyBean();
if (study.getParentStudyId() > 0) {
this.parentStudy = (StudyBean) new StudyDAO(ds).findByPK(study.getParentStudyId());
} else {
this.parentStudy = new StudyBean();
}
}
public MetadataUnit(DataSource ds){
this.ds = ds;
}
public MetadataUnit(DataSource ds, DatasetBean dataset, ODMBean odmBean, StudyBean study, int category,RuleSetRuleDao ruleSetRuleDao) {
super(ds, dataset, odmBean, study, category);
this.odmStudy = new OdmStudyBean();
this.ruleSetRuleDao = ruleSetRuleDao;
if (study.getParentStudyId() > 0) {
this.parentStudy = (StudyBean) new StudyDAO(ds).findByPK(study.getParentStudyId());
} else {
this.parentStudy = new StudyBean();
}
}
public void collectOdmStudy(String formVersionOID) {
StudyBean study = studyBase.getStudy();
String studyOID = study.getOid();
if (studyOID == null || studyOID.length() <= 0) {
logger.info("Constructed studyOID using study_id because oc_oid is missing from the table - study.");
studyOID = "" + study.getId();
}
odmStudy.setOid(studyOID);
if(studyOID.equals(FAKE_STUDY_OID)){
collectGlobalVariables();
collectBasicDefinitions(formVersionOID);
collectMetaDataVersion(formVersionOID)
;
}
else
{
collectGlobalVariables();
collectBasicDefinitions();
collectMetaDataVersion();
}
}
public void collectOdmStudy(){
StudyBean study = studyBase.getStudy();
String studyOID = study.getOid();
if (studyOID == null || studyOID.length() <= 0) {
logger.info("Constructed studyOID using study_id because oc_oid is missing from the table - study.");
studyOID = "" + study.getId();
}
collectGlobalVariables();
collectBasicDefinitions();
collectMetaDataVersion();
}
private void collectGlobalVariables() {
StudyBean study = studyBase.getStudy();
String sn = study.getName();
String sd = study.getSummary().trim();
String pn = study.getIdentifier();
if (parentStudy.getId() > 0) {
sn = parentStudy.getName() + " - " + study.getName();
sd = parentStudy.getSummary().trim() + " - " + study.getSummary().trim();
pn = parentStudy.getIdentifier() + " - " + study.getIdentifier();
}
GlobalVariablesBean gv = this.odmStudy.getGlobalVariables();
gv.setStudyName(sn);
gv.setStudyDescription(sd);
gv.setProtocolName(pn);
}
private void collectBasicDefinitions() {
int studyid = studyBase.getStudy().getParentStudyId()>0 ? studyBase.getStudy().getParentStudyId() : studyBase.getStudy().getId();
new OdmExtractDAO(this.ds).getBasicDefinitions(studyid, odmStudy.getBasicDefinitions());
}
private void collectBasicDefinitions(String formVersionOID){
new OdmExtractDAO(this.ds).getBasicDefinitions(formVersionOID, odmStudy.getBasicDefinitions());
}
/**
* To retrieve the ODM with form version OID as one of the parameters
* @param formVersionOID
*/
private void collectMetaDataVersion(String formVersionOID){
StudyBean study = studyBase.getStudy();
OdmExtractDAO oedao = new OdmExtractDAO(this.ds);
MetaDataVersionBean metadata = this.odmStudy.getMetaDataVersion();
ODMBean odmBean = new ODMBean();
odmBean.setODMVersion("oc1.3");
setOdmBean( odmBean);
ArrayList<StudyEventDefinitionBean> sedBeansInStudy = (ArrayList<StudyEventDefinitionBean>) studyBase.getSedBeansInStudy();
if (sedBeansInStudy == null || sedBeansInStudy.size() < 1) {
logger.info("null, because there is no study event definition in this study.");
return;
}
if (metadata.getOid() == null || metadata.getOid().length() <= 0) {
metadata.setOid("v1.0.0");
}
if (metadata.getName() == null || metadata.getName().length() <= 0) {
metadata.setName("MetaDataVersion_v1.0.0");
}
oedao.getODMMetadataForForm(metadata,formVersionOID,this.odmBean.getODMVersion());
}
private void collectMetaDataVersion() {
ArrayList<StudyEventDefinitionBean> sedBeansInStudy = (ArrayList<StudyEventDefinitionBean>) studyBase.getSedBeansInStudy();
if (sedBeansInStudy == null || sedBeansInStudy.size() < 1) {
logger.info("null, because there is no study event definition in this study.");
return;
}
StudyBean study = studyBase.getStudy();
StudyConfigService studyConfig = new StudyConfigService(this.ds);
study = studyConfig.setParametersForStudy(study);
MetaDataVersionBean metadata = this.odmStudy.getMetaDataVersion();
metadata.setStudy(study);
StudyParameterValueDAO spvdao = new StudyParameterValueDAO(this.ds);
int parentId = study.getParentStudyId()>0 ? study.getParentStudyId() : study.getId();
StudyParameterValueBean spv = spvdao.findByHandleAndStudy(parentId, "discrepancyManagement");
metadata.setSoftHard(spv.getValue().equalsIgnoreCase("true") ? "Hard" : "Soft");
OdmExtractDAO oedao = new OdmExtractDAO(this.ds);
int studyId = study.getId();
int parentStudyId = study.getParentStudyId() > 0 ? study.getParentStudyId() : studyId;
if (this.getCategory() == 1 && study.isSite(study.getParentStudyId())) {
// populate MetaDataVersion attributes
if (dataset != null) {
metadata.setOid(dataset.getODMMetaDataVersionOid() + "-" + study.getOid());
metadata.setName(dataset.getODMMetaDataVersionName() + "-" + study.getOid());
this.setParentMetaDataVersionOid(dataset.getODMMetaDataVersionOid());
}
if (metadata.getOid() == null || metadata.getOid().length() <= 0) {
metadata.setOid("v1.0.0" + "-" + study.getOid());
this.setParentMetaDataVersionOid("v1.0.0");
}
if (metadata.getName() == null || metadata.getName().length() <= 0) {
metadata.setName("MetaDataVersion_v1.0.0" + "-" + study.getOid());
}
// populate Include
this.collectIncludeFromParentInSameFile();
// populate protocol
oedao.getUpdatedSiteMetadata(parentStudyId, studyId, metadata, this.odmBean.getODMVersion());
} else {
if (dataset != null) {
metadata.setOid(dataset.getODMMetaDataVersionOid());
metadata.setName(dataset.getODMMetaDataVersionName());
}
if (metadata.getOid() == null || metadata.getOid().length() <= 0) {
metadata.setOid("v1.0.0");
}
if (metadata.getName() == null || metadata.getName().length() <= 0) {
metadata.setName("MetaDataVersion_v1.0.0");
}
// populate Include
String psOid = new String();
String pmOid = new String();
if (dataset != null) {
psOid = dataset.getODMPriorStudyOid();
pmOid = dataset.getODMPriorMetaDataVersionOid();
}
if (pmOid != null && pmOid.length() > 0) {
MetaDataVersionIncludeBean ib = metadata.getInclude();
ib.setMetaDataVersionOID(pmOid);
if (psOid != null && psOid.length() > 0) {
ib.setStudyOID(psOid);
} else {
ib.setStudyOID(study.getOid());
}
}
// populate protocol
// Set<Integer> nullCodeSet = oedao.getMetadata(parentStudyId,
// studyId,
// metadata, this.getODMBean().getODMVersion());
// studyBase.setNullClSet(nullCodeSet);
oedao.getMetadata(parentStudyId, studyId, metadata, this.odmBean.getODMVersion());
metadata.setRuleSetRules(getRuleSetRuleDao().findByRuleSetStudyIdAndStatusAvail(parentStudyId));
}
}
/**
* Include parent study metadata which is in the same ODM XML file.
*
* @return
*/
private void collectIncludeFromParentInSameFile() {
MetaDataVersionIncludeBean ib = this.odmStudy.getMetaDataVersion().getInclude();
String metaOid = this.getParentMetaDataVersionOid();
String pstudyOID = this.parentStudy.getOid();
if (pstudyOID == null || pstudyOID.length() <= 0) {
pstudyOID = "" + this.parentStudy.getId();
}
ib.setMetaDataVersionOID(metaOid);
ib.setStudyOID(pstudyOID);
}
public static String getOdmItemDataType(int responseTypeId, int OCDataTypeId) {
// 3: checkbox; 7: multi-select
if (responseTypeId == 3 || responseTypeId == 7) {
return "text";
} else {
return getOdmItemDataType(OCDataTypeId);
}
}
/**
* Handle mapping among odm-1.2 datatypes and openclinica datatypes
*
* @param OCDataTypeId
* @return
*/
public static String getOdmItemDataType(int OCDataTypeId) {
switch (OCDataTypeId) {
// BL //BN //ED //TEL //ST
case 1:
return "text";
case 2:
return "text";
case 3:
return "text";
case 4:
return "text";
case 5:
return "text";
case 8:
return "text";
case 10: // partial-date
return "partialDate";
// INT
case 6:
return "integer";
// REAL
case 7:
return "float";
// DATE
case 9:
return "date";
default:
return "text";
}
}
public static String getOdmItemDataType(int responseTypeId, int OCDataTypeId, String odmVersion) {
if (odmVersion.contains("1.2")) {
return getOdmItemDataType(responseTypeId, OCDataTypeId);
} else {
// 3: checkbox; 7: multi-select
if (responseTypeId == 3 || responseTypeId == 7) {
return "text";
} else {
switch (OCDataTypeId) {
case 1:
return "boolean";
//not be supported in openclinica-3.0.4.1
//case 10:
//return "partialDate";
default:
return getOdmItemDataType(OCDataTypeId);
}
}
}
}
public static int getSignificantDigits(String datatype, List<String> values, boolean hasCode) {
if ("float".equalsIgnoreCase(datatype)) {
return hasCode ? getSignificantDigits(values) : 6;
}
return new String().length();
}
public static int getSignificantDigits(String datatype, Set<String> values, boolean hasCode) {
if ("float".equalsIgnoreCase(datatype)) {
return hasCode ? getSignificantDigits(values) : 6;
}
return new String().length();
}
public static int getDataTypeLength(List<String> values) {
int len = 0;
for (String value : values) {
len = Math.max(len, value.length());
}
return len;
}
public static int getDataTypeLength(Set<String> values) {
int len = 0;
Iterator<String> iter = values.iterator();
while (iter.hasNext()) {
String value = iter.next();
len = Math.max(len, value.length());
}
return len;
}
public static int getSignificantDigits(List<String> values) {
int d = 0;
for (String v : values) {
if (v != null && v.length() > 0) {
double temp = 0;
try {
temp = Double.parseDouble(v);
} catch (NumberFormatException e) {
temp = 0;
}
d = temp != 0 ? Math.max(d, BigDecimal.valueOf(temp).scale()) : d;
}
}
return d;
}
public static int getSignificantDigits(Set<String> values) {
int d = 0;
Iterator<String> iter = values.iterator();
while (iter.hasNext()) {
String v = iter.next();
if (v != null && v.length() > 0) {
double temp = 0;
try {
temp = Double.parseDouble(v);
} catch (NumberFormatException e) {
temp = 0;
}
d = temp != 0 ? Math.max(d, BigDecimal.valueOf(temp).scale()) : d;
}
}
return d;
}
public static String getItemQuestionText(String header, String left, String right) {
String t = header != null && header.length() > 0 ? header : "";
if (left != null && left.length() > 0) {
t += t.length() > 0 ? " - " + left : left;
}
if (right != null && right.length() > 0) {
t += t.length() > 0 ? " - " + right : right;
}
return t;
}
public static List<RangeCheckBean> getItemRangeCheck(String func, String constraint, String errorMessage, String muOid) {
// at this time only supports one measurement unit for a RangeCheck,
// and it is the same as its item unit
ArrayList<ElementRefBean> unitRefs = new ArrayList<ElementRefBean>();
ElementRefBean unit = new ElementRefBean();
unit.setElementDefOID(muOid);
unitRefs.add(unit);
List<RangeCheckBean> rcs = new ArrayList<RangeCheckBean>();
// final String[] odmComparator = { "LT", "LE", "GT", "GE", "EQ", "NE",
// "IN", "NOTIN" };
String[] s = func.split("\\(");
RangeCheckBean rc = new RangeCheckBean();
if (s[0].equalsIgnoreCase("range")) {
String[] values = s[1].split("\\,");
String smaller = values[0];
String larger = values[1].trim();
larger = larger.substring(0, larger.length() - 1);
rc.setComparator("GE");
rc.setSoftHard(constraint);
rc.getErrorMessage().setText(errorMessage);
rc.setCheckValue(smaller);
rc.setMeasurementUnitRefs(unitRefs);
rcs.add(rc);
rc = new RangeCheckBean();
rc.setComparator("LE");
rc.setSoftHard(constraint);
rc.getErrorMessage().setText(errorMessage);
rc.setCheckValue(larger);
rc.setMeasurementUnitRefs(unitRefs);
rcs.add(rc);
} else {
rc = new RangeCheckBean();
String value = s[1].trim();
value = value.substring(0, value.length() - 1);
if (s[0].equalsIgnoreCase("gt")) {
rc.setComparator("GT");
} else if (s[0].equalsIgnoreCase("lt")) {
rc.setComparator("LT");
} else if (s[0].equalsIgnoreCase("gte")) {
rc.setComparator("GE");
} else if (s[0].equalsIgnoreCase("lte")) {
rc.setComparator("LE");
} else if (s[0].equalsIgnoreCase("ne")) {
rc.setComparator("NE");
} else if (s[0].equalsIgnoreCase("eq")) {
rc.setComparator("EQ");
}
rc.setSoftHard(constraint);
rc.getErrorMessage().setText(errorMessage);
rc.setCheckValue(value);
rc.setMeasurementUnitRefs(unitRefs);
rcs.add(rc);
}
return rcs;
}
public static boolean needCodeList(int rsTypeId, int datatypeid) {
if ((rsTypeId == 5 || rsTypeId == 6) && (datatypeid == 5 || datatypeid == 6 || datatypeid == 7)) {
return true;
}
return false;
}
public static boolean needMultiSelectList(int rsTypeId) {
if (rsTypeId == 3 || rsTypeId == 7) {
return true;
}
return false;
}
public static LinkedHashMap<String, String> parseCode(String rsText, String rsValue, String nullValue) {
LinkedHashMap<String, String> code = parseCode(rsText, rsValue);
String[] nulls = nullValue.split(",");
for (String s : nulls) {
s = s.trim().toUpperCase();
if (s.length() > 0 && nullValueMap.containsKey(s)) {
code.put(nullValueMap.get(s), s);
}
}
return code;
}
public static LinkedHashMap<String, String> parseCode(String rsText, String rsValue) {
LinkedHashMap<String, String> code = new LinkedHashMap<String, String>();
// code below following logic of the method
// "setOptions(String optionsText, String optionsValues)"
// in ResponseSetBean.java
String[] keys = rsValue.replaceAll("\\\\,", "##").split(",");
String[] values = rsText.replaceAll("\\\\,", "##").split(",");
if (values == null) {
return code;
}
if (keys == null) {
keys = new String[0];
}
for (int i = 0; i < values.length; i++) {
if (values[i] == null || values[i].length() <= 0) {
continue;
}
String v = values[i].trim().replaceAll("##", ",");
if (keys.length <= i || keys[i] == null || keys[i].length() <= 0) {
code.put(v, v);
} else {
code.put(keys[i].trim().replaceAll("##", ","), v);
}
}
return code;
}
@Override
public OdmStudyBase getStudyBase() {
return studyBase;
}
@Override
public void setStudyBase(OdmStudyBase studyBase) {
this.studyBase = studyBase;
}
public OdmStudyBean getOdmStudy() {
return odmStudy;
}
public void setOdmStudy(OdmStudyBean odmStudy) {
this.odmStudy = odmStudy;
}
public RuleSetRuleDao getRuleSetRuleDao() {
return ruleSetRuleDao;
}
public void setRuleSetRuleDao(RuleSetRuleDao ruleSetRuleDao) {
this.ruleSetRuleDao = ruleSetRuleDao;
}
public StudyBean getParentStudy() {
return parentStudy;
}
public void setParentStudy(StudyBean parentStudy) {
this.parentStudy = parentStudy;
}
}