/* * Copyright (c) 2006-2007 Massachusetts General Hospital * All rights reserved. This program and the accompanying materials * are made available under the terms of the i2b2 Software License v1.0 * which accompanies this distribution. * * Contributors: * Rajesh Kuttan */ package edu.harvard.i2b2.crc.ejb; import java.io.StringWriter; import java.rmi.RemoteException; import java.util.Date; import java.util.Map; import javax.xml.bind.JAXBElement; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactory; import edu.harvard.i2b2.common.exception.I2B2DAOException; import edu.harvard.i2b2.common.exception.I2B2Exception; import edu.harvard.i2b2.common.util.jaxb.JAXBUnWrapHelper; import edu.harvard.i2b2.common.util.jaxb.JAXBUtil; import edu.harvard.i2b2.crc.dao.DAOFactoryHelper; import edu.harvard.i2b2.crc.dao.IDAOFactory; import edu.harvard.i2b2.crc.dao.SetFinderDAOFactory; import edu.harvard.i2b2.crc.dao.setfinder.IQueryInstanceDao; import edu.harvard.i2b2.crc.dao.setfinder.IQueryMasterDao; import edu.harvard.i2b2.crc.dao.setfinder.IQueryResultInstanceDao; import edu.harvard.i2b2.crc.datavo.CRCJAXBUtil; import edu.harvard.i2b2.crc.datavo.PSMFactory; import edu.harvard.i2b2.crc.datavo.db.DataSourceLookup; import edu.harvard.i2b2.crc.datavo.db.QtQueryInstance; import edu.harvard.i2b2.crc.datavo.db.QtQueryMaster; import edu.harvard.i2b2.crc.datavo.i2b2message.BodyType; import edu.harvard.i2b2.crc.datavo.i2b2message.PasswordType; import edu.harvard.i2b2.crc.datavo.i2b2message.RequestMessageType; import edu.harvard.i2b2.crc.datavo.setfinder.query.InstanceResultResponseType; import edu.harvard.i2b2.crc.datavo.setfinder.query.MasterInstanceResultResponseType; import edu.harvard.i2b2.crc.datavo.setfinder.query.QueryDefinitionRequestType; import edu.harvard.i2b2.crc.datavo.setfinder.query.QueryDefinitionType; import edu.harvard.i2b2.crc.datavo.setfinder.query.QueryInstanceType; import edu.harvard.i2b2.crc.datavo.setfinder.query.QueryMasterType; import edu.harvard.i2b2.crc.datavo.setfinder.query.ResultOutputOptionListType; import edu.harvard.i2b2.crc.datavo.setfinder.query.ResultOutputOptionType; import edu.harvard.i2b2.crc.datavo.setfinder.query.ResultResponseType; import edu.harvard.i2b2.crc.datavo.setfinder.query.StatusType; import edu.harvard.i2b2.crc.datavo.setfinder.query.StatusType.Condition; import edu.harvard.i2b2.crc.datavo.setfinder.query.UserType; import edu.harvard.i2b2.crc.delegate.pm.CallPMUtil; import edu.harvard.i2b2.crc.util.QueryProcessorUtil; /** * Ejb manager class for query operation * * @author rkuttan * * @ejb.bean description="QueryTool Query Manager" * display-name="QueryTool Query Manager" * jndi-name="ejb.querytool.QueryManager" * local-jndi-name="ejb.querytool.QueryManagerLocal" * name="querytool.QueryManager" type="Stateless" view-type="both" * transaction-type="Bean" * * @ejb.transaction type="Required" * * * @ejb.interface remote-class="edu.harvard.i2b2.crc.ejb.QueryManagerRemote" * * */ public class QueryManagerBean{ // implements SessionBean { private static Log log = LogFactory.getLog(QueryManagerBean.class); public static String RESPONSE_QUEUE_NAME = "queue/jms.querytool.QueryResponse"; // public static String UPLOADPROCESSOR_QUEUE_NAME = // "queue/jms.querytool.QueryExecutor"; // SessionContext context; /** * Function to publish patients using publish message format. * * @ejb.interface-method view-type="both" * @ejb.transaction type="Required" * * @param String * publish request XML fileName * * @return String publish response XML * @throws Exception */ public MasterInstanceResultResponseType processQuery( DataSourceLookup dataSourceLookup, String xmlRequest) throws Exception { String responseXML = null; MasterInstanceResultResponseType masterInstanceResultType = null; try { String sessionId = String.valueOf(System.currentTimeMillis()); QueryManagerBeanUtil qmBeanUtil = new QueryManagerBeanUtil(); long timeout = qmBeanUtil.getTimeout(xmlRequest); DataSourceLookup dsLookupInput = qmBeanUtil .getDataSourceLookupInput(xmlRequest); SetFinderDAOFactory sfDAOFactory = null; // tm.begin(); // transaction.begin(); if (dsLookupInput.getProjectPath() == null) { throw new I2B2Exception("project id is missing in the request"); } DAOFactoryHelper daoFactoryHelper = new DAOFactoryHelper( dsLookupInput.getDomainId(), dsLookupInput.getProjectPath(), dsLookupInput.getOwnerId()); IDAOFactory daoFactory = daoFactoryHelper.getDAOFactory(); sfDAOFactory = daoFactory.getSetFinderDAOFactory(); String generatedSql = null; RequestMessageType requestMsgType = this.getI2B2RequestType(xmlRequest); String queryMasterId = saveQuery(sfDAOFactory, requestMsgType, generatedSql); // create query instance IQueryInstanceDao queryInstanceDao = sfDAOFactory .getQueryInstanceDAO(); UserType userType = getUserTypeFromSetfinderHeader(requestMsgType); String userId = userType.getLogin(); String groupId = userType.getGroup(); String queryInstanceId = queryInstanceDao.createQueryInstance( queryMasterId, userId, groupId, "SMALL_QUEUE", 5); // QueryExecutorMDB.SMALL_QUEUE, 5); log.debug("New Query instance id " + queryInstanceId); IQueryResultInstanceDao patientSetResultDao = sfDAOFactory .getPatientSetResultDAO(); String patientSetId = null; QueryDefinitionRequestType queryDefRequestType = getQueryDefinitionRequestType(requestMsgType); ResultOutputOptionListType resultOptionList = queryDefRequestType .getResultOutputList(); if (resultOptionList != null && resultOptionList.getResultOutput() != null && resultOptionList.getResultOutput().size() > 0) { for (ResultOutputOptionType resultOption : resultOptionList .getResultOutput()) { patientSetId = patientSetResultDao.createPatientSet( queryInstanceId, resultOption.getName()); log.debug("Patient Set ID [" + patientSetId + "] for query instance= " + queryInstanceId); } } else { QueryProcessorUtil qp = QueryProcessorUtil.getInstance(); BeanFactory bf = qp.getSpringBeanFactory(); String defaultResultType = (String) bf .getBean(QueryProcessorUtil.DEFAULT_SETFINDER_RESULT_BEANNAME); patientSetId = patientSetResultDao.createPatientSet( queryInstanceId, defaultResultType); log.debug("Patient Set ID [" + patientSetId + "] for query instance= " + queryInstanceId); } // tm.commit(); // transaction.commit(); log.debug("getting responsetype"); ResultResponseType responseType = executeSqlInQueue( dsLookupInput.getDomainId(), dsLookupInput.getProjectPath(), dsLookupInput.getOwnerId(), userId, generatedSql, sessionId, queryInstanceId, patientSetId, xmlRequest, timeout); // transaction.begin(); // responseXML = qmBeanUtil.buildQueryRequestResponse(xmlRequest, // status, // sessionId,queryMasterId,queryInstanceId,responseType); log.debug("after queue exectution"); /* * query instance status is updated in the query executor class * QtQueryInstance queryInstance = updateQueryInstanceStatus( * sfDAOFactory, responseType, userId, queryInstanceId); */ IQueryMasterDao queryMasterDao = sfDAOFactory.getQueryMasterDAO(); QtQueryMaster queryMaster = queryMasterDao .getQueryDefinition(queryMasterId); masterInstanceResultType = new MasterInstanceResultResponseType(); QueryMasterType queryMasterType = PSMFactory .buildQueryMasterType(queryMaster); // set query master masterInstanceResultType.setQueryMaster(queryMasterType); // fetch query instance by queryinstance id and build response QtQueryInstance queryInstance = queryInstanceDao .getQueryInstanceByInstanceId(queryInstanceId); QueryInstanceType queryInstanceType = PSMFactory .buildQueryInstanceType(queryInstance); // set query instance masterInstanceResultType.setQueryInstance(queryInstanceType); // set status masterInstanceResultType.setStatus(responseType.getStatus()); QueryResultBean queryResultBean = new QueryResultBean(); ResultResponseType responseType1 = queryResultBean .getResultInstanceFromQueryInstanceId(dataSourceLookup, userId, queryInstanceId); log.debug("Size of result when called thru ejb " + responseType1.getQueryResultInstance().size()); //If query result instanace -> query_status_type is processing that set QUEUE if (responseType1.getQueryResultInstance() != null && responseType1.getQueryResultInstance().get(0).getQueryStatusType().getStatusTypeId().equals("2")) { responseType1.getQueryResultInstance().get(0).getQueryStatusType().setStatusTypeId("1"); responseType1.getQueryResultInstance().get(0).getQueryStatusType().setName("QUEUED"); responseType1.getQueryResultInstance().get(0).getQueryStatusType().setDescription("WAITING IN QUEUE TO START PROCESS"); StatusType stype = new StatusType(); Condition e = new Condition(); e.setType("RUNNING"); e.setValue("RUNNING"); stype.getCondition().add(e); responseType1.setStatus(stype); } // set result instance masterInstanceResultType.getQueryResultInstance().addAll( responseType1.getQueryResultInstance()); // transaction.commit(); } catch (I2B2DAOException ex) { log.debug("Got an error in QueryManagerBean, thropwing: " + ex.getMessage()); ex.printStackTrace(); throw new I2B2Exception(ex.getMessage()); } return masterInstanceResultType; } /** * Function to publish patients using publish message format. * * @ejb.interface-method view-type="both" * @ejb.transaction type="Required" * * @param String * userId * @param int master id * @param long timeout * * @return InstanceResultResponseType */ public InstanceResultResponseType runQueryMaster( DataSourceLookup dataSourceLookup, String userId, String masterId, long timeout) throws I2B2Exception { return null; } private ResultResponseType executeSqlInQueue(String domainId, String projectId, String ownerId, String userId, String generatedSql, String sessionId, String queryInstanceId, String patientSetId, String xmlRequest, long timeout) throws Exception { QueryManagerBeanUtil qmBeanUtil = new QueryManagerBeanUtil(); // process query in queue log.debug("process query in queue"); Map returnValues = qmBeanUtil.testSend(domainId, projectId, ownerId, generatedSql, sessionId, queryInstanceId, patientSetId, xmlRequest, timeout); log.debug("My returnValue map is:" + returnValues); log.debug("My mapssize is: " + returnValues.size()); // build response message, if query completed before given timeout String status = (String) returnValues .get(QueryManagerBeanUtil.QUERY_STATUS_PARAM); int queryResultInstanceId = (Integer) returnValues .get(QueryManagerBeanUtil.QT_QUERY_RESULT_INSTANCE_ID_PARAM); log.debug("Query Result Instance id " + queryResultInstanceId); log.debug("Status coming from queue : " + status); StatusType statusType = new StatusType(); StatusType.Condition condition = new StatusType.Condition(); condition.setValue(status); if (status != null && status.indexOf("LOCKEDOUT") > -1) { status = "ERROR"; } condition.setType(status); statusType.getCondition().add(condition); ResultResponseType responseType = new ResultResponseType(); responseType.setStatus(statusType); return responseType; } private String saveQuery(SetFinderDAOFactory sfDAOFactory, RequestMessageType i2b2RequestMsgType, String generatedSql) throws Exception { IQueryMasterDao queryMasterDao = sfDAOFactory.getQueryMasterDAO(); QtQueryMaster queryMaster = new QtQueryMaster(); UserType userType = getUserTypeFromSetfinderHeader(i2b2RequestMsgType); String userId = userType.getLogin(); String groupId = userType.getGroup(); QueryDefinitionType queryDefType = getQueryDefinition(i2b2RequestMsgType); edu.harvard.i2b2.crc.datavo.setfinder.query.ObjectFactory of = new edu.harvard.i2b2.crc.datavo.setfinder.query.ObjectFactory(); queryMaster.setUserId(userId); StringWriter queryDefWriter = new StringWriter(); CRCJAXBUtil.getQueryDefJAXBUtil().marshaller( of.createQueryDefinition(queryDefType), queryDefWriter); queryMaster.setRequestXml(queryDefWriter.toString()); queryMaster.setGroupId(groupId); queryMaster.setCreateDate(new Date(System.currentTimeMillis())); queryMaster.setDeleteFlag(QtQueryMaster.DELETE_OFF_FLAG); queryMaster.setGeneratedSql(generatedSql); queryMaster.setName(queryDefType.getQueryName()); String pmXml = CallPMUtil.callUserResponse(i2b2RequestMsgType.getMessageHeader().getSecurity(), ""); //remove user password form the request PasswordType passType = i2b2RequestMsgType.getMessageHeader().getSecurity().getPassword(); passType.setValue("password not stored"); passType.setIsToken(false); JAXBUtil util = CRCJAXBUtil.getJAXBUtil(); StringWriter strWriter = new StringWriter(); edu.harvard.i2b2.crc.datavo.i2b2message.ObjectFactory i2b2ObjFactory = new edu.harvard.i2b2.crc.datavo.i2b2message.ObjectFactory(); util.marshaller(i2b2ObjFactory.createRequest(i2b2RequestMsgType), strWriter); String queryMasterId = queryMasterDao.createQueryMaster(queryMaster, strWriter.toString(), pmXml); return queryMasterId; } private UserType getUserTypeFromSetfinderHeader(RequestMessageType requestMessageType) throws Exception { UserType userType = new UserType(); userType.setLogin(requestMessageType.getMessageHeader().getSecurity() .getUsername()); userType.setGroup(requestMessageType.getMessageHeader().getProjectId()); return userType; } private RequestMessageType getI2B2RequestType(String xmlRequest) throws Exception { JAXBUtil jaxbUtil = CRCJAXBUtil.getJAXBUtil(); JAXBElement jaxbElement = jaxbUtil.unMashallFromString(xmlRequest); if (jaxbElement == null) { throw new Exception( "null value in after unmarshalling request string "); } RequestMessageType requestMessageType = (RequestMessageType) jaxbElement .getValue(); return requestMessageType; } private QueryDefinitionRequestType getQueryDefinitionRequestType( RequestMessageType requestMessageType) throws Exception { String queryName = null; QueryDefinitionType queryDef = null; BodyType bodyType = requestMessageType.getMessageBody(); JAXBUnWrapHelper unWrapHelper = new JAXBUnWrapHelper(); QueryDefinitionRequestType queryDefReqType = (QueryDefinitionRequestType) unWrapHelper .getObjectByClass(bodyType.getAny(), QueryDefinitionRequestType.class); return queryDefReqType; } public QueryDefinitionType getQueryDefinition(RequestMessageType requestMessageType) throws Exception { QueryDefinitionRequestType queryDefReqType = getQueryDefinitionRequestType(requestMessageType); QueryDefinitionType queryDef = null; if (queryDefReqType != null) { queryDef = queryDefReqType.getQueryDefinition(); } return queryDef; } /** * Function to publish patients using publish message format. * * @ejb.interface-method view-type="both" * @ejb.transaction type="Required" * * @param int session id publish request XML fileName * * @return String publish response XML */ public String getResponseXML(String sessionId) { QueryManagerBeanUtil qmBeanUtil = new QueryManagerBeanUtil(); String status = qmBeanUtil.getStatus(sessionId); String response = qmBeanUtil.buildGetQueryResultResponse(sessionId, status); return response; } /* public void setSessionContext(SessionContext context) throws EJBException, RemoteException { this.context = context; } public void ejbCreate() throws CreateException { } public void ejbRemove() throws EJBException, RemoteException { } public void ejbActivate() throws EJBException, RemoteException { } public void ejbPassivate() throws EJBException, RemoteException { } */ }