package edu.ualberta.med.biobank.server.applicationservice; import edu.ualberta.med.biobank.common.action.Action; import edu.ualberta.med.biobank.common.action.ActionResult; import edu.ualberta.med.biobank.common.action.exception.ActionException; import edu.ualberta.med.biobank.common.peer.UserPeer; import edu.ualberta.med.biobank.common.permission.Permission; import edu.ualberta.med.biobank.common.reports.QueryCommand; import edu.ualberta.med.biobank.common.reports.QueryHandle; import edu.ualberta.med.biobank.common.reports.QueryHandleRequest; import edu.ualberta.med.biobank.common.reports.QueryHandleRequest.CommandType; import edu.ualberta.med.biobank.common.wrappers.actions.BiobankSessionAction; import edu.ualberta.med.biobank.model.Log; import edu.ualberta.med.biobank.model.PrintedSsInvItem; import edu.ualberta.med.biobank.model.Report; import edu.ualberta.med.biobank.model.Site; import edu.ualberta.med.biobank.model.User; import edu.ualberta.med.biobank.server.applicationservice.exceptions.BiobankServerException; import edu.ualberta.med.biobank.server.logging.MessageGenerator; import edu.ualberta.med.biobank.server.orm.BiobankORMDAOImpl; import edu.ualberta.med.biobank.server.query.BiobankSQLCriteria; import gov.nih.nci.system.applicationservice.ApplicationException; import gov.nih.nci.system.applicationservice.impl.WritableApplicationServiceImpl; import gov.nih.nci.system.dao.Request; import gov.nih.nci.system.dao.Response; import gov.nih.nci.system.query.SDKQuery; import gov.nih.nci.system.query.example.InsertExampleQuery; import gov.nih.nci.system.query.example.UpdateExampleQuery; import gov.nih.nci.system.query.hibernate.HQLCriteria; import gov.nih.nci.system.util.ClassCache; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; import org.apache.log4j.Level; import org.apache.log4j.Logger; /** * Implementation of the BiobankApplicationService interface. This class will be * only on the server side. * * See build.properties of the sdk for the generator configuration + * application-config*.xml for the generated files. */ public class BiobankApplicationServiceImpl extends WritableApplicationServiceImpl implements BiobankApplicationService { public BiobankApplicationServiceImpl(ClassCache classCache) { super(classCache); } /** * How can we manage security using sql ?? */ @Override public <E> List<E> query(BiobankSQLCriteria sqlCriteria, String targetClassName) throws ApplicationException { return privateQuery(sqlCriteria, targetClassName); } @Override protected Request prepareRequest(SDKQuery query, String classname) { Request request = super.prepareRequest(query, classname); // super.prepareRequest replaces the request of SearchHQLQuery, switch // it back to the query if it's a BiobankSessionAction if (query instanceof BiobankSessionAction) { request.setRequest(query); } return request; } @Override public void logActivity(String action, String site, String patientNumber, String inventoryID, String locationLabel, String details, String type) throws Exception { Log log = new Log(); log.setAction(action); log.setCenter(site); log.setPatientNumber(patientNumber); log.setInventoryId(inventoryID); log.setLocationLabel(locationLabel); log.setDetails(details); log.setType(type); logActivity(log); } /** * See log4j.xml: it should contain the Biobank.Activity appender */ @Override public void logActivity(Log log) throws Exception { Logger logger = Logger.getLogger("Biobank.Activity"); //$NON-NLS-1$ logger.log(Level.toLevel("INFO"), //$NON-NLS-1$ MessageGenerator.generateStringMessage(log)); } @Override public List<Object> runReport(Report report, int maxResults, int firstRow, int timeout) throws ApplicationException { ReportData reportData = new ReportData(report); reportData.setMaxResults(maxResults); reportData.setFirstRow(firstRow); reportData.setTimeout(timeout); Request request = new Request(reportData); request.setIsCount(Boolean.FALSE); request.setFirstRow(0); request.setDomainObjectName(Report.class.getName()); Response response = query(request); @SuppressWarnings("unchecked") List<Object> results = (List<Object>) response.getResponse(); return results; } @Override public QueryHandle createQuery(QueryCommand qc) throws Exception { QueryHandleRequest qhr = new QueryHandleRequest(qc, CommandType.CREATE, null, this); return (QueryHandle) getWritableDAO(Site.class.getName()).query( new Request(qhr)).getResponse(); } @SuppressWarnings("unchecked") @Override public List<Object> startQuery(QueryHandle qh) throws Exception { QueryHandleRequest qhr = new QueryHandleRequest(null, CommandType.START, qh, this); return (List<Object>) getWritableDAO(Site.class.getName()).query( new Request(qhr)).getResponse(); } @Override public void stopQuery(QueryHandle qh) throws Exception { QueryHandleRequest qhr = new QueryHandleRequest(null, CommandType.STOP, qh, this); getWritableDAO(Site.class.getName()).query(new Request(qhr)) .getResponse(); } @SuppressWarnings("nls") private static final String GET_USER_QRY = "from " + User.class.getName() + " where " + UserPeer.CSM_USER_ID.getName() + " = ?"; @Override public void executeModifyPassword(Long csmUserId, String oldPassword, String newPassword, Boolean recvBulkEmails) throws ApplicationException { BiobankCSMSecurityUtil.modifyPassword(csmUserId, oldPassword, newPassword); List<User> users = query(new HQLCriteria(GET_USER_QRY, Arrays.asList(csmUserId))); if (users.size() != 1) { throw new ApplicationException("Problem with HQL result size"); //$NON-NLS-1$ } User user = users.get(0); user.setNeedPwdChange(false); if (recvBulkEmails != null) user.setRecvBulkEmails(recvBulkEmails); executeQuery(new UpdateExampleQuery(user)); } @Override public void unlockUser(String userNameToUnlock) throws ApplicationException { BiobankCSMSecurityUtil.unlockUser(userNameToUnlock); } @Override public void checkVersion(String clientVersion) throws ApplicationException { BiobankVersionUtil.checkVersion(clientVersion); } @Override public String getServerVersion() { return BiobankVersionUtil.getServerVersion(); } // @Override // @Deprecated // public ScanProcessResult processScanResult(Map<RowColPos, Cell> cells, // ProcessData processData, boolean isRescanMode, // Integer currentWorkingCenterId, Locale locale) // throws ApplicationException { // try { // ServerProcess process = processData.getProcessInstance(this, // currentWorkingCenterId, locale); // return process.processScanResult(cells, isRescanMode); // } catch (ApplicationException ae) { // throw ae; // } catch (Exception e) { // throw new ApplicationException(e); // } // } // // @Override // @Deprecated // public CellProcessResult processCellStatus(Cell cell, // ProcessData processData, Integer currentWorkingCenterId, Locale locale) // throws ApplicationException { // try { // ServerProcess process = processData.getProcessInstance(this, // currentWorkingCenterId, locale); // return process.processCellStatus(cell); // } catch (ApplicationException ae) { // throw ae; // } catch (Exception e) { // throw new ApplicationException(e); // } // } private static final int SS_INV_ID_LENGTH = 12; @SuppressWarnings("nls") private static final String SS_INV_ID_ALPHABET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; private static final int SS_INV_ID_ALPHABET_LENGTH = SS_INV_ID_ALPHABET .length(); private static final int SS_INV_ID_GENERATE_RETRIES = (int) Math.pow( SS_INV_ID_ALPHABET_LENGTH, SS_INV_ID_ALPHABET_LENGTH); @SuppressWarnings("nls") private static final String SS_INV_ID_UNIQ_BASE_QRY = "SELECT count(*) " + "FROM printed_ss_inv_item where txt=\"{id}\""; @Override public List<String> executeGetSourceSpecimenUniqueInventoryIds(int numIds) throws ApplicationException { boolean isUnique; int genRetries; Random r = new Random(); StringBuilder newInvId; List<String> result = new ArrayList<String>(); while (result.size() < numIds) { isUnique = false; genRetries = 0; newInvId = new StringBuilder(); while (!isUnique && (genRetries < SS_INV_ID_GENERATE_RETRIES)) { for (int j = 0; j < SS_INV_ID_LENGTH; ++j) { newInvId.append(SS_INV_ID_ALPHABET.charAt(r .nextInt(SS_INV_ID_ALPHABET_LENGTH))); genRetries++; } // check database if string is unique String potentialInvId = newInvId.toString(); String qry = SS_INV_ID_UNIQ_BASE_QRY.replace("{id}", //$NON-NLS-1$ potentialInvId); List<BigInteger> count = privateQuery(new BiobankSQLCriteria( qry), PrintedSsInvItem.class.getName()); if (count.get(0).equals(BigInteger.ZERO)) { // add new inventory id to the database isUnique = true; result.add(potentialInvId); PrintedSsInvItem newInvIdItem = new PrintedSsInvItem(); newInvIdItem.setTxt(potentialInvId); SDKQuery query = new InsertExampleQuery(newInvIdItem); executeQuery(query); } } if (genRetries >= SS_INV_ID_GENERATE_RETRIES) { // cannot generate any more unique strings throw new BiobankServerException( "cannot generate any more source specimen inventory IDs"); //$NON-NLS-1$ } } return result; } @Override public String getUserPassword(String login) throws ApplicationException { return BiobankCSMSecurityUtil.getUserPassword(login); } @Override public boolean isUserLockedOut(Long csmUserId) throws ApplicationException { return BiobankCSMSecurityUtil.isUserLockedOut(csmUserId); } @Override public <T extends ActionResult> T doAction(Action<T> action) throws ApplicationException { try { Request request = new Request(new AppServiceAction<T>(action, this)); request.setDomainObjectName(Site.class.getName()); Response response = query(request); @SuppressWarnings("unchecked") T tmp = (T) response.getResponse(); return tmp; } catch (ApplicationException e) { if (e.getCause() instanceof ActionException) throw (ActionException) e.getCause(); throw e; } } @Override public boolean isAllowed(Permission permission) throws ApplicationException { return ((BiobankORMDAOImpl) this.getWritableDAO(Site.class.getName())) .isAllowed(permission); } public class AppServiceAction<T extends ActionResult> { public Action<T> action; public BiobankApplicationService appService; public AppServiceAction(Action<T> action, BiobankApplicationService appService) { this.action = action; this.appService = appService; } } }