package edu.ualberta.med.biobank.common.action.study; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.hibernate.Query; import edu.ualberta.med.biobank.common.action.Action; import edu.ualberta.med.biobank.common.action.ActionContext; import edu.ualberta.med.biobank.common.action.ListResult; import edu.ualberta.med.biobank.common.action.exception.ActionException; import edu.ualberta.med.biobank.common.action.study.StudyGetClinicInfoAction.ClinicInfo; import edu.ualberta.med.biobank.common.util.NotAProxy; import edu.ualberta.med.biobank.model.Clinic; import edu.ualberta.med.biobank.model.Contact; import edu.ualberta.med.biobank.model.Study; public class StudyGetClinicInfoAction implements Action<ListResult<ClinicInfo>> { private static final long serialVersionUID = 1L; @SuppressWarnings("nls") private static final String STUDY_CONTACTS_HQL = "SELECT clinics,contacts " + "FROM " + Study.class.getName() + " study" + " INNER JOIN study.contacts contacts" + " INNER JOIN contacts.clinic clinics" + " WHERE study.id=?"; @SuppressWarnings("nls") private static final String STUDY_CLINIC_INFO_HQL = "SELECT clinics,COUNT(DISTINCT patients)," + " COUNT(DISTINCT cevents)" + " FROM " + Study.class.getName() + " study" + " INNER JOIN study.contacts contacts" + " INNER JOIN contacts.clinic clinics" + " LEFT JOIN clinics.originInfos originInfo" + " LEFT JOIN originInfo.specimens specimens" + " LEFT JOIN specimens.collectionEvent cevents" + " LEFT JOIN cevents.patient patients" + " WHERE study.id = ?" + " GROUP BY clinics"; private final Integer studyId; public StudyGetClinicInfoAction(Integer studyId) { this.studyId = studyId; } public StudyGetClinicInfoAction(Study study) { this(study.getId()); } @Override public boolean isAllowed(ActionContext context) throws ActionException { return true; } @SuppressWarnings("unchecked") @Override public ListResult<ClinicInfo> run(ActionContext context) throws ActionException { // first get contacts by clinic Map<Clinic, List<Contact>> contactsByClinic = new HashMap<Clinic, List<Contact>>(); Query query = context.getSession().createQuery(STUDY_CONTACTS_HQL); query.setParameter(0, studyId); List<Object[]> results = query.list(); for (Object[] row : results) { Clinic clinic = (Clinic) row[0]; Contact contact = (Contact) row[1]; List<Contact> contactList = contactsByClinic.get(clinic); if (contactList == null) { contactList = new ArrayList<Contact>(); contactList.add(contact); contactsByClinic.put(clinic, contactList); } else { contactList.add(contact); } } ArrayList<ClinicInfo> infos = new ArrayList<ClinicInfo>(); query = context.getSession().createQuery(STUDY_CLINIC_INFO_HQL); query.setParameter(0, studyId); results = query.list(); for (Object[] row : results) { Clinic clinic = (Clinic) row[0]; List<Contact> contactList = contactsByClinic.get(clinic); if (contactList == null) { throw new ActionException("clinic should have contacts: " + clinic.getNameShort()); } ClinicInfo info = new ClinicInfo(clinic, (Long) row[1], (Long) row[2], contactList); infos.add(info); } return new ListResult<ClinicInfo>(infos); } public static class ClinicInfo implements Serializable, NotAProxy { private static final long serialVersionUID = 1L; private final Clinic clinic; private final Long patientCount; private final Long ceventCount; private final List<Contact> contacts; public ClinicInfo(Clinic clinic, Long patientCount, Long ceventCount, List<Contact> contacts) { this.clinic = clinic; this.patientCount = patientCount; this.ceventCount = ceventCount; this.contacts = contacts; } public Clinic getClinic() { return clinic; } public Long getPatientCount() { return patientCount; } public Long getCeventCount() { return ceventCount; } public List<Contact> getContacts() { return contacts; } } }