package org.akaza.openclinica.service.crfdata;
import java.io.StringWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import javax.servlet.ServletContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.akaza.openclinica.dao.core.CoreResources;
import org.akaza.openclinica.dao.hibernate.CrfVersionDao;
import org.akaza.openclinica.dao.hibernate.EventCrfDao;
import org.akaza.openclinica.dao.hibernate.ItemDao;
import org.akaza.openclinica.dao.hibernate.ItemDataDao;
import org.akaza.openclinica.dao.hibernate.ItemFormMetadataDao;
import org.akaza.openclinica.dao.hibernate.ItemGroupDao;
import org.akaza.openclinica.dao.hibernate.ItemGroupMetadataDao;
import org.akaza.openclinica.dao.hibernate.ResponseTypeDao;
import org.akaza.openclinica.dao.hibernate.StudyEventDao;
import org.akaza.openclinica.dao.hibernate.StudyEventDefinitionDao;
import org.akaza.openclinica.dao.hibernate.StudySubjectDao;
import org.akaza.openclinica.dao.login.UserAccountDAO;
import org.akaza.openclinica.dao.managestudy.StudyDAO;
import org.akaza.openclinica.domain.datamap.CrfVersion;
import org.akaza.openclinica.domain.datamap.EventCrf;
import org.akaza.openclinica.domain.datamap.Item;
import org.akaza.openclinica.domain.datamap.ItemData;
import org.akaza.openclinica.domain.datamap.ItemFormMetadata;
import org.akaza.openclinica.domain.datamap.ItemGroup;
import org.akaza.openclinica.domain.datamap.ItemGroupMetadata;
import org.akaza.openclinica.domain.datamap.ResponseType;
import org.akaza.openclinica.domain.datamap.StudyEvent;
import org.akaza.openclinica.domain.datamap.StudyEventDefinition;
import org.akaza.openclinica.domain.datamap.StudySubject;
import org.akaza.openclinica.service.crfdata.xform.EnketoAPI;
import org.akaza.openclinica.service.crfdata.xform.EnketoCredentials;
import org.akaza.openclinica.service.crfdata.xform.PFormCacheSubjectContextEntry;
import org.akaza.openclinica.service.pmanage.Authorization;
import org.akaza.openclinica.service.pmanage.ParticipantPortalRegistrar;
import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@Service
public class EnketoUrlService {
@Autowired
@Qualifier("dataSource")
private BasicDataSource dataSource;
@Autowired
ServletContext context;
@Autowired
private CrfVersionDao crfVersionDao;
@Autowired
private StudyEventDao studyEventDao;
@Autowired
private StudyEventDefinitionDao studyEventDefinitionDao;
@Autowired
private StudySubjectDao studySubjectDao;
@Autowired
private EventCrfDao eventCrfDao;
@Autowired
private ItemDao itemDao;
@Autowired
private ItemGroupDao itemGroupDao;
@Autowired
private ItemGroupMetadataDao itemGroupMetadataDao;
@Autowired
private ItemFormMetadataDao itemFormMetadataDao;
@Autowired
private ResponseTypeDao responseTypeDao;
@Autowired
private ItemDataDao itemDataDao;
public static final String FORM_CONTEXT = "ecid";
ParticipantPortalRegistrar participantPortalRegistrar;
protected final Logger logger = LoggerFactory.getLogger(getClass().getName());
UserAccountDAO udao;
StudyDAO sdao;
public String getInitialDataEntryUrl(String subjectContextKey, PFormCacheSubjectContextEntry subjectContext, String studyOid) throws Exception {
// Call Enketo api to get edit url
EnketoAPI enketo = new EnketoAPI(EnketoCredentials.getInstance(studyOid));
return enketo.getFormURL(subjectContext.getCrfVersionOid()) + "?ecid=" + subjectContextKey;
}
public String getEditUrl(String subjectContextKey, PFormCacheSubjectContextEntry subjectContext, String studyOid) throws Exception {
String editURL = null;
// Lookup relevant data
StudyEventDefinition eventDef = studyEventDefinitionDao.findByStudyEventDefinitionId(subjectContext.getStudyEventDefinitionId());
CrfVersion crfVersion = crfVersionDao.findByOcOID(subjectContext.getCrfVersionOid());
StudySubject subject = studySubjectDao.findByOcOID(subjectContext.getStudySubjectOid());
StudyEvent event = studyEventDao.fetchByStudyEventDefOIDAndOrdinal(eventDef.getOc_oid(), Integer.valueOf(subjectContext.getOrdinal()),
subject.getStudySubjectId());
EventCrf eventCrf = eventCrfDao.findByStudyEventIdStudySubjectIdCrfVersionId(event.getStudyEventId(), subject.getStudySubjectId(),
crfVersion.getCrfVersionId());
// Load populated instance
String populatedInstance = getPopulatedInstance(crfVersion, eventCrf);
// Call Enketo api to get edit url
EnketoAPI enketo = new EnketoAPI(EnketoCredentials.getInstance(studyOid));
// Build redirect url
String redirectUrl = getRedirectUrl(subject.getOcOid(), studyOid);
// Return Enketo URL
editURL = enketo.getEditURL(crfVersion.getOcOid(), populatedInstance, subjectContextKey, redirectUrl).getEdit_url() + "&ecid=" + subjectContextKey;
logger.debug("Generating Enketo edit url for form: " + editURL);
return editURL;
}
private String getRedirectUrl(String studySubjectOid, String studyOid) {
String portalURL = CoreResources.getField("portalURL");
String url = "";
if (portalURL != null && !portalURL.equals("")) {
ParticipantPortalRegistrar registrar = new ParticipantPortalRegistrar();
Authorization pManageAuthorization = registrar.getAuthorization(studyOid);
try {
URL pManageUrl = new URL(portalURL);
if (pManageAuthorization != null && pManageAuthorization.getStudy() != null && pManageAuthorization.getStudy().getHost() != null
&& !pManageAuthorization.getStudy().getHost().equals("")) {
url = pManageUrl.getProtocol() + "://" + pManageAuthorization.getStudy().getHost() + "." + pManageUrl.getHost()
+ ((pManageUrl.getPort() > 0) ? ":" + String.valueOf(pManageUrl.getPort()) : "");
}
} catch (MalformedURLException e) {
logger.error("Error building redirect URL: " + e.getMessage());
logger.error(ExceptionUtils.getStackTrace(e));
return "";
}
}
if (!url.equals(""))
url = url + "/#/event/" + studySubjectOid + "/dashboard";
return url;
}
private String getPopulatedInstance(CrfVersion crfVersion, EventCrf eventCrf) throws Exception {
boolean isXform = false;
if (crfVersion.getXform() != null && !crfVersion.getXform().equals(""))
isXform = true;
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder build = docFactory.newDocumentBuilder();
Document doc = build.newDocument();
Element crfElement = null;
if (isXform)
crfElement = doc.createElement(crfVersion.getXformName());
else
crfElement = doc.createElement(crfVersion.getOcOid());
doc.appendChild(crfElement);
ArrayList<ItemGroup> itemGroups = itemGroupDao.findByCrfVersionId(crfVersion.getCrfVersionId());
for (ItemGroup itemGroup : itemGroups) {
ItemGroupMetadata itemGroupMetadata = itemGroupMetadataDao.findByItemGroupCrfVersion(itemGroup.getItemGroupId(), crfVersion.getCrfVersionId()).get(
0);
ArrayList<Item> items = (ArrayList<Item>) itemDao.findByItemGroupCrfVersionOrdered(itemGroup.getItemGroupId(), crfVersion.getCrfVersionId());
// Get max repeat in item data
int maxGroupRepeat = itemDataDao.getMaxGroupRepeat(eventCrf.getEventCrfId(), items.get(0).getItemId());
// loop thru each repeat creating items in instance
String repeatGroupMin = itemGroupMetadata.getRepeatNumber().toString();
Boolean isrepeating = itemGroupMetadata.isRepeatingGroup();
// TODO: Test empty group here (no items). make sure doesn't get nullpointer exception
for (int i = 0; i < maxGroupRepeat; i++) {
Element groupElement = null;
if (isXform)
groupElement = doc.createElement(itemGroup.getName());
else
groupElement = doc.createElement(itemGroup.getOcOid());
Element repeatOrdinal = null;
if (isrepeating) {
repeatOrdinal = doc.createElement("OC.REPEAT_ORDINAL");
repeatOrdinal.setTextContent(String.valueOf(i+1));
groupElement.appendChild(repeatOrdinal);
}
boolean hasItemData = false;
for (Item item : items) {
ItemFormMetadata itemMetadata = itemFormMetadataDao.findByItemCrfVersion(item.getItemId(), crfVersion.getCrfVersionId());
ItemData itemData = itemDataDao.findByItemEventCrfOrdinal(item.getItemId(), eventCrf.getEventCrfId(), i + 1);
Element question = null;
if (crfVersion.getXform() != null && !crfVersion.getXform().equals(""))
question = doc.createElement(item.getName());
else
question = doc.createElement(item.getOcOid());
if (itemData != null && itemData.getValue() != null && !itemData.getValue().equals("")) {
ResponseType responseType = responseTypeDao.findByItemFormMetaDataId(itemMetadata.getItemFormMetadataId());
String itemValue = itemData.getValue();
if (responseType.getResponseTypeId() == 3 || responseType.getResponseTypeId() == 7) {
itemValue = itemValue.replaceAll(",", " ");
}
question.setTextContent(itemValue);
}
if (itemData==null || !itemData.isDeleted()) {
hasItemData = true;
groupElement.appendChild(question);
}
} // end of item
if (hasItemData) {
crfElement.appendChild(groupElement);
}
}
} // end of group
TransformerFactory transformFactory = TransformerFactory.newInstance();
Transformer transformer = transformFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
DOMSource source = new DOMSource(doc);
transformer.transform(source, result);
String instance = writer.toString();
return instance;
}
}