/* * OpenClinica is distributed under the * GNU Lesser General Public License (GNU LGPL). * For details see: http://www.openclinica.org/license * * Copyright 2003-2009 Akaza Research */ package org.akaza.openclinica.ws; import org.akaza.openclinica.bean.login.UserAccountBean; import org.akaza.openclinica.dao.login.UserAccountDAO; import org.akaza.openclinica.exception.OpenClinicaSystemException; import org.akaza.openclinica.i18n.util.ResourceBundleProvider; import org.akaza.openclinica.service.EventServiceInterface; import org.akaza.openclinica.ws.bean.StudyEventTransferBean; import org.akaza.openclinica.ws.validator.StudyEventTransferValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.MessageSource; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.util.xml.DomUtils; import org.springframework.validation.DataBinder; import org.springframework.validation.Errors; import org.springframework.validation.ObjectError; import org.springframework.ws.server.endpoint.annotation.Endpoint; import org.springframework.ws.server.endpoint.annotation.PayloadRoot; import org.springframework.ws.server.endpoint.annotation.XPathParam; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import javax.sql.DataSource; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.Source; import javax.xml.transform.dom.DOMSource; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Locale; /** * @author Krikor Krumlian * */ @Endpoint public class EventEndpoint { protected final Logger logger = LoggerFactory.getLogger(getClass().getName()); private final String NAMESPACE_URI_V1 = "http://openclinica.org/ws/event/v1"; private String dateFormat; private final EventServiceInterface eventService; private final MessageSource messages; private final DataSource dataSource; Locale locale; /** * Constructor * * @param subjectService * @param cctsService */ public EventEndpoint(EventServiceInterface eventService, DataSource dataSource, MessageSource messages) { this.eventService = eventService; this.messages = messages; this.dataSource = dataSource; this.locale = new Locale("en_US"); } /** * if NAMESPACE_URI_V1:scheduleRequest execute this method * */ @PayloadRoot(localPart = "scheduleRequest", namespace = NAMESPACE_URI_V1) public Source createSubject(@XPathParam("//e:event") NodeList event, @XPathParam("//e:study") String study, @XPathParam("//e:eventDefinitionOID") String eventDefinitionOID, @XPathParam("//e:location") String location, @XPathParam("//e:startDate") String startDate, @XPathParam("//e:startTime") String startTime, @XPathParam("//e:endDate") String endDate, @XPathParam("//e:endTime") String endTime) throws Exception { ResourceBundleProvider.updateLocale(new Locale("en_US")); Element eventElement = (Element) event.item(0); StudyEventTransferBean studyEventTransferBean = unMarshallToEventTransfer(eventElement); DataBinder dataBinder = new DataBinder((studyEventTransferBean)); Errors errors = dataBinder.getBindingResult(); StudyEventTransferValidator studyEventTransferValidator = new StudyEventTransferValidator(dataSource); studyEventTransferValidator.validate((studyEventTransferBean), errors); if (!errors.hasErrors()) { try { HashMap<String, String> h = getEventService().scheduleEvent(studyEventTransferBean.getUser(), studyEventTransferBean.getStartDateTime(), studyEventTransferBean.getEndDateTime(), studyEventTransferBean.getLocation(), studyEventTransferBean.getStudyUniqueId(), studyEventTransferBean.getSiteUniqueId(), studyEventTransferBean.getEventDefinitionOID(), studyEventTransferBean.getSubjectLabel()); return new DOMSource(mapSuccessConfirmation(h)); } catch (OpenClinicaSystemException ose) { errors.reject("eventEndpoint.cannot_schedule", "Cannot schedule an event for this Subject."); return new DOMSource(mapFailConfirmation(errors)); } } else { return new DOMSource(mapFailConfirmation(errors)); } } /** * Create Success Response * * @param confirmation * @return * @throws Exception */ private Element mapSuccessConfirmation(HashMap<String, String> confirmation) throws Exception { DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); Document document = docBuilder.newDocument(); Element responseElement = document.createElementNS(NAMESPACE_URI_V1, "scheduleResponse"); Element resultElement = document.createElementNS(NAMESPACE_URI_V1, "result"); Element eventDefinitionOID = document.createElementNS(NAMESPACE_URI_V1, "eventDefinitionOID"); Element studySubjectOID = document.createElementNS(NAMESPACE_URI_V1, "studySubjectOID"); Element eventOrdinal = document.createElementNS(NAMESPACE_URI_V1, "studyEventOrdinal"); resultElement.setTextContent(messages.getMessage("eventEndpoint.success", null, "Success", locale)); eventDefinitionOID.setTextContent(confirmation.get("eventDefinitionOID")); studySubjectOID.setTextContent(confirmation.get("studySubjectOID")); eventOrdinal.setTextContent(confirmation.get("studyEventOrdinal")); responseElement.appendChild(resultElement); responseElement.appendChild(eventDefinitionOID); responseElement.appendChild(studySubjectOID); responseElement.appendChild(eventOrdinal); return responseElement; } /** * Process createEvent request by creating StudyEventTransferBean from received payload. * * @param subjectElement * @return SubjectTransferBean * @throws ParseException */ private StudyEventTransferBean unMarshallToEventTransfer(Element eventElement) throws ParseException { Element eventDefinitionOidElement = DomUtils.getChildElementByTagName(eventElement, "eventDefinitionOID"); Element locationElement = DomUtils.getChildElementByTagName(eventElement, "location"); Element startDateElement = DomUtils.getChildElementByTagName(eventElement, "startDate"); Element endDateElement = DomUtils.getChildElementByTagName(eventElement, "endDate"); Element startTimeElement = DomUtils.getChildElementByTagName(eventElement, "startTime"); Element endTimeElement = DomUtils.getChildElementByTagName(eventElement, "endTime"); Element subjectRefElement = DomUtils.getChildElementByTagName(eventElement, "studySubjectRef"); Element labelElement = DomUtils.getChildElementByTagName(subjectRefElement, "label"); Element studyRefElement = DomUtils.getChildElementByTagName(eventElement, "studyRef"); Element studyIdentifierElement = DomUtils.getChildElementByTagName(studyRefElement, "identifier"); Element siteRef = DomUtils.getChildElementByTagName(studyRefElement, "siteRef"); Element siteIdentifierElement = siteRef == null ? null : DomUtils.getChildElementByTagName(siteRef, "identifier"); String studySubjectId = DomUtils.getTextValue(labelElement).trim(); String eventDefinitionOID = DomUtils.getTextValue(eventDefinitionOidElement).trim(); String studyIdentifier = DomUtils.getTextValue(studyIdentifierElement).trim(); String siteIdentifier = siteIdentifierElement == null ? null : DomUtils.getTextValue(siteIdentifierElement).trim(); String location = locationElement == null ? null : DomUtils.getTextValue(locationElement).trim(); String startDate = DomUtils.getTextValue(startDateElement).trim(); String startTime = startTimeElement == null ? null : DomUtils.getTextValue(startTimeElement).trim(); String endDate = endDateElement == null ? null : DomUtils.getTextValue(endDateElement).trim(); String endTime = endTimeElement == null ? null : DomUtils.getTextValue(endTimeElement).trim(); StudyEventTransferBean studyEventTransferBean = new StudyEventTransferBean(studySubjectId, studyIdentifier, siteIdentifier, eventDefinitionOID, location, getDate(startDate, startTime), getDate( endDate, endTime), getUserAccount()); return studyEventTransferBean; } /** * Create Error Response * * @param confirmation * @return * @throws Exception */ private Element mapFailConfirmation(Errors errors) throws Exception { DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance(); DocumentBuilder docBuilder = dbfac.newDocumentBuilder(); Document document = docBuilder.newDocument(); Element responseElement = document.createElementNS(NAMESPACE_URI_V1, "scheduleResponse"); Element resultElement = document.createElementNS(NAMESPACE_URI_V1, "result"); resultElement.setTextContent(messages.getMessage("eventEndpoint.fail", null, "Fail", locale)); responseElement.appendChild(resultElement); for (ObjectError error : errors.getAllErrors()) { Element errorElement = document.createElementNS(NAMESPACE_URI_V1, "error"); String theMessage = messages.getMessage(error.getCode(), error.getArguments(), locale); errorElement.setTextContent(theMessage); responseElement.appendChild(errorElement); } return responseElement; } /** * Helper Method to resolve dates * * @param dateAsString * @return * @throws ParseException */ private Date getDate(String dateAsString, String hourMinuteAsString) throws ParseException { Date d = null; if (dateAsString != null && dateAsString.length() != 0) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); dateAsString += hourMinuteAsString == null ? " 00:00" : " " + hourMinuteAsString; d = sdf.parse(dateAsString); if (!sdf.format(d).equals(dateAsString)) { throw new OpenClinicaSystemException("Date not parseable"); } return sdf.parse(dateAsString); } else { return null; } } /** * Helper Method to get the user account * * @return UserAccountBean */ private UserAccountBean getUserAccount() { Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); String username = null; if (principal instanceof UserDetails) { username = ((UserDetails) principal).getUsername(); } else { username = principal.toString(); } UserAccountDAO userAccountDao = new UserAccountDAO(dataSource); return (UserAccountBean) userAccountDao.findByUserName(username); } /** * @return */ public String getDateFormat() { return dateFormat; } /** * @param dateFormat */ public void setDateFormat(String dateFormat) { this.dateFormat = dateFormat; } public EventServiceInterface getEventService() { return eventService; } }