package org.akaza.openclinica.service; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import javax.sql.DataSource; import org.akaza.openclinica.bean.login.UserAccountBean; import org.akaza.openclinica.bean.managestudy.StudyBean; import org.akaza.openclinica.bean.managestudy.StudyGroupBean; import org.akaza.openclinica.bean.managestudy.StudySubjectBean; import org.akaza.openclinica.bean.submit.EventCRFBean; import org.akaza.openclinica.bean.submit.ItemBean; import org.akaza.openclinica.bean.submit.ItemDataBean; import org.akaza.openclinica.bean.submit.SubjectBean; import org.akaza.openclinica.dao.hibernate.DynamicsItemFormMetadataDao; import org.akaza.openclinica.dao.hibernate.DynamicsItemGroupMetadataDao; import org.akaza.openclinica.dao.login.UserAccountDAO; import org.akaza.openclinica.dao.managestudy.EventDefinitionCRFDAO; import org.akaza.openclinica.dao.managestudy.StudyDAO; import org.akaza.openclinica.dao.managestudy.StudyEventDAO; import org.akaza.openclinica.dao.managestudy.StudyGroupClassDAO; import org.akaza.openclinica.dao.managestudy.StudyGroupDAO; import org.akaza.openclinica.dao.managestudy.StudySubjectDAO; import org.akaza.openclinica.dao.submit.EventCRFDAO; import org.akaza.openclinica.dao.submit.ItemDAO; import org.akaza.openclinica.dao.submit.ItemDataDAO; import org.akaza.openclinica.dao.submit.ItemFormMetadataDAO; import org.akaza.openclinica.dao.submit.ItemGroupDAO; import org.akaza.openclinica.dao.submit.ItemGroupMetadataDAO; import org.akaza.openclinica.dao.submit.SectionDAO; import org.akaza.openclinica.dao.submit.SubjectDAO; import org.akaza.openclinica.domain.rule.RuleSetBean; import org.akaza.openclinica.domain.rule.action.StratificationFactorBean; import org.akaza.openclinica.service.pmanage.SeRandomizationDTO; import org.akaza.openclinica.service.pmanage.RandomizationRegistrar; import org.akaza.openclinica.service.rule.expression.ExpressionService; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.exception.ExceptionUtils; import org.json.JSONException; import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestTemplate; public class RandomizeService extends RandomizationRegistrar { protected final Logger logger = LoggerFactory.getLogger(getClass().getName()); private final String ESCAPED_SEPERATOR = "\\."; private DynamicsItemFormMetadataDao dynamicsItemFormMetadataDao; private DynamicsItemGroupMetadataDao dynamicsItemGroupMetadataDao; DataSource ds; private EventCRFDAO eventCRFDAO; private ItemDataDAO itemDataDAO; private ItemDAO itemDAO; private ItemGroupDAO itemGroupDAO; private SectionDAO sectionDAO; // private CRFVersionDAO crfVersionDAO; private ItemFormMetadataDAO itemFormMetadataDAO; private ItemGroupMetadataDAO itemGroupMetadataDAO; private StudyEventDAO studyEventDAO; private EventDefinitionCRFDAO eventDefinitionCRFDAO; private ExpressionService expressionService; HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); public static final int RANDOMIZATION_READ_TIMEOUT = 10000; StudyDAO sdao=null; public RandomizeService(DataSource ds) { this.ds = ds; this.expressionService = new ExpressionService(ds); } // Rest Call to OCUI to get Randomization public String getRandomizationCode(EventCRFBean eventCrfBean, List<StratificationFactorBean> stratificationFactorBeans, RuleSetBean ruleSet) throws JSONException { StudySubjectDAO ssdao = new StudySubjectDAO<>(ds); StudySubjectBean ssBean = (StudySubjectBean) ssdao.findByPK(eventCrfBean.getStudySubjectId()); String identifier = ssBean.getOid(); // study subject oid StudyDAO sdao = new StudyDAO<>(ds); StudyBean sBean = (StudyBean) sdao.findByPK(ssBean.getStudyId()); String siteIdentifier = sBean.getOid(); // site or study oid String name = sBean.getName(); // site or study name UserAccountDAO udao = new UserAccountDAO(ds); int userId = 0; if (eventCrfBean.getUpdaterId() == 0) { userId = eventCrfBean.getOwnerId(); } else { userId = eventCrfBean.getUpdaterId(); } UserAccountBean uBean = (UserAccountBean) udao.findByPK(userId); String user = uBean.getName(); // sBean should be parent study // put randomization object in cache StudyBean study = getParentStudy(sBean.getOid()); SeRandomizationDTO randomization = null; try { randomization = getCachedRandomizationDTOObject(study.getOid(), false); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } String randomiseUrl = randomization.getUrl(); String username = randomization.getUsername(); String password = randomization.getPassword(); String timezone = "America/New_York"; // String randomiseUrl = "https://evaluation.sealedenvelope.com/redpill/seti2"; // String username = "oc"; // String password = "secret"; HttpHeaders headers = createHeaders(username, password); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // retrieve json object if Randomization exist ,otherwise return a null object JSONObject jsonRandObject = retrieveARandomisation(randomiseUrl, ssBean, headers); if (jsonRandObject != null) { return (String) jsonRandObject.get("code"); } else { // if Site identifier exists ,then update otherwise create new Site identifier addOrUpdateASite(randomiseUrl, sBean, headers, timezone); // send for Randomization JSONObject jsonRandomisedObject = randomiseSubject(randomiseUrl, ssBean, sBean, headers, user, stratificationFactorBeans, eventCrfBean, ruleSet); if (jsonRandomisedObject != null) return (String) jsonRandomisedObject.get("code"); else return ""; } } private String getExpressionValue(String expr, EventCRFBean eventCrfBean, RuleSetBean ruleSet) { String expression = getExpressionService().constructFullExpressionIfPartialProvided(expr, ruleSet.getTarget().getValue()); ItemDataBean itemData = null; if (expression != null && !expression.isEmpty()) { ItemBean itemBean = getExpressionService().getItemBeanFromExpression(expression); String itemGroupBOrdinal = getExpressionService().getGroupOrdninalCurated(expression); itemData = getItemDataDAO().findByItemIdAndEventCRFIdAndOrdinal(itemBean.getId(), eventCrfBean.getId(), itemGroupBOrdinal == "" ? 1 : Integer.valueOf(itemGroupBOrdinal)); } return itemData.getValue(); } private String getStudySubjectAttrValue(String expr, EventCRFBean eventCrfBean, RuleSetBean ruleSet) { String value = ""; StudySubjectDAO<String, ArrayList> ssdao = new StudySubjectDAO<>(ds); SubjectDAO subdao = new SubjectDAO(ds); StudyGroupClassDAO sgcdao = new StudyGroupClassDAO(ds); StudyGroupDAO sgdao = new StudyGroupDAO(ds); StudyDAO<String, ArrayList> sdao = new StudyDAO<>(ds); StudySubjectBean ssBean = (StudySubjectBean) ssdao.findByPK(eventCrfBean.getStudySubjectId()); SubjectBean subjectBean = (SubjectBean) subdao.findByPK(ssBean.getSubjectId()); String prefix = "STUDYGROUPCLASSLIST"; String param = expr.split("\\.", -1)[1].trim(); if (param.equalsIgnoreCase("BIRTHDATE")) { value = subjectBean.getDateOfBirth().toString(); } else if (param.equalsIgnoreCase("SEX")) { if (String.valueOf(subjectBean.getGender()).equals("m")) value = "Male"; else value = "Female"; // value =String.valueOf(ssBean.getGender()); } else if (param.startsWith(prefix)) { String gcName = param.substring(21, param.indexOf("\"]")); StudyGroupBean sgBean = sgdao.findSubjectStudyGroup(ssBean.getId(), gcName); if (sgBean != null) value = sgBean.getName(); } return value; } private JSONObject retrieveARandomisation(String randomiseUrl, StudySubjectBean studySubject, HttpHeaders headers) throws JSONException { // method : GET randomiseUrl = randomiseUrl + "/api/randomisation?identifier=" + studySubject.getOid(); // concatenate // Study_Siubject_oid RestTemplate rest = new RestTemplate(requestFactory); ResponseEntity<String> response = null; String body = null; JSONObject jsonObject = null; HttpEntity<String> request = new HttpEntity<String>(headers); try { response = rest.exchange(randomiseUrl, HttpMethod.GET, request, String.class); body = response.getBody(); jsonObject = new JSONObject(body); // if (!jsonObject.get("error").equals("0")) // jsonObject= null; } catch (Exception e) { System.out.println(e.getMessage()); logger.error(e.getMessage()); logger.error(ExceptionUtils.getStackTrace(e)); } return jsonObject; } private void addOrUpdateASite(String randomiseUrl, StudyBean studyBean, HttpHeaders headers, String timezone) { // mehtod : POST randomiseUrl = randomiseUrl + "/api/sites"; RestTemplate rest = new RestTemplate(requestFactory); ResponseEntity<String> response = null; MultiValueMap<String, String> siteMap = new LinkedMultiValueMap<String, String>(); siteMap.add("siteIdentifier", studyBean.getOid()); siteMap.add("name", studyBean.getName()); siteMap.add("timezone", timezone); HttpEntity<MultiValueMap<String, String>> siteRequest = new HttpEntity<MultiValueMap<String, String>>(siteMap, headers); try { response = rest.exchange(randomiseUrl, HttpMethod.POST, siteRequest, String.class); } catch (Exception e) { logger.error(e.getMessage()); logger.error(ExceptionUtils.getStackTrace(e)); } } private JSONObject randomiseSubject(String randomiseUrl, StudySubjectBean studySubject, StudyBean studyBean, HttpHeaders headers, String user, List<StratificationFactorBean> stratificationFactorBeans, EventCRFBean eventCrfBean, RuleSetBean ruleSet) { // method : POST int i = 1; String exp = ""; randomiseUrl = randomiseUrl + "/api/randomise"; RestTemplate rest = new RestTemplate(requestFactory); ResponseEntity<String> response = null; MultiValueMap<String, String> subjectMap = new LinkedMultiValueMap<String, String>(); subjectMap.add("identifier", String.valueOf(studySubject.getOid())); subjectMap.add("siteIdentifier", studyBean.getOid()); subjectMap.add("user", user); for (StratificationFactorBean stratificationFactorBean : stratificationFactorBeans) { i++; exp = stratificationFactorBean.getStratificationFactor().getValue(); if (exp.startsWith("SS.")) { subjectMap.add("question" + i, getStudySubjectAttrValue(exp, eventCrfBean, ruleSet)); } else { String output = getExpressionValue(exp, eventCrfBean, ruleSet); subjectMap.add("question" + i, output); } } String body = null; JSONObject jsonObject = null; HttpEntity<MultiValueMap<String, String>> subjectRequest = new HttpEntity<MultiValueMap<String, String>>(subjectMap, headers); try { response = rest.exchange(randomiseUrl, HttpMethod.POST, subjectRequest, String.class); body = response.getBody(); jsonObject = new JSONObject(body); } catch (Exception e) { System.out.println(e.getMessage()); logger.error(e.getMessage()); System.out.println(ExceptionUtils.getStackTrace(e)); logger.error(ExceptionUtils.getStackTrace(e)); } return jsonObject; } HttpHeaders createHeaders(final String username, final String password) { return new HttpHeaders() { { String auth = username + ":" + password; byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(Charset.forName("US-ASCII"))); String authHeader = "Basic " + new String(encodedAuth); set("Authorization", authHeader); } }; } public ExpressionService getExpressionService() { return expressionService; } public void setExpressionService(ExpressionService expressionService) { this.expressionService = expressionService; } public ItemDataDAO getItemDataDAO() { return new ItemDataDAO(ds); } public void setItemDataDAO(ItemDataDAO itemDataDAO) { this.itemDataDAO = itemDataDAO; } private StudyBean getStudy(String oid) { sdao = new StudyDAO(ds); StudyBean studyBean = (StudyBean) sdao.findByOid(oid); return studyBean; } private StudyBean getParentStudy(String studyOid) { StudyBean study = getStudy(studyOid); if (study.getParentStudyId() == 0) { return study; } else { StudyBean parentStudy = (StudyBean) sdao.findByPK(study.getParentStudyId()); return parentStudy; } } }