package edu.ualberta.med.biobank.common.wrappers; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; import edu.ualberta.med.biobank.common.exception.BiobankException; import edu.ualberta.med.biobank.common.exception.BiobankQueryResultSizeException; import edu.ualberta.med.biobank.common.peer.CapacityPeer; import edu.ualberta.med.biobank.common.peer.ContainerLabelingSchemePeer; import edu.ualberta.med.biobank.common.peer.ContainerPeer; import edu.ualberta.med.biobank.common.peer.ContainerTypePeer; import edu.ualberta.med.biobank.common.peer.SitePeer; import edu.ualberta.med.biobank.common.util.RowColPos; import edu.ualberta.med.biobank.common.wrappers.WrapperTransaction.TaskList; import edu.ualberta.med.biobank.common.wrappers.base.ContainerTypeBaseWrapper; import edu.ualberta.med.biobank.common.wrappers.checks.ContainerTypePostPersistChecks; import edu.ualberta.med.biobank.common.wrappers.checks.ContainerTypePrePersistChecks; import edu.ualberta.med.biobank.model.Container; import edu.ualberta.med.biobank.model.ContainerType; import gov.nih.nci.system.applicationservice.ApplicationException; import gov.nih.nci.system.applicationservice.WritableApplicationService; import gov.nih.nci.system.query.hibernate.HQLCriteria; public class ContainerTypeWrapper extends ContainerTypeBaseWrapper { public static final Property<Integer, ContainerType> ROW_CAPACITY = ContainerTypePeer.CAPACITY .wrap(CapacityPeer.ROW_CAPACITY); public static final Property<Integer, ContainerType> COL_CAPACITY = ContainerTypePeer.CAPACITY .wrap(CapacityPeer.COL_CAPACITY); private static final Collection<Property<?, ? super ContainerType>> UNIQUE_NAME_PROPS, UNIQUE_NAME_SHORT_PROPS; private static final String CONTAINER_TYPE_IS_USED_MSG = Messages .getString("ContainerTypeWrapper.container.type.isused.msg"); //$NON-NLS-1$ public static final List<Property<?, ? super ContainerType>> PROPERTIES; static { List<Property<?, ? super ContainerType>> aList = new ArrayList<Property<?, ? super ContainerType>>(); aList.addAll(ContainerTypePeer.PROPERTIES); aList.add(ROW_CAPACITY); aList.add(COL_CAPACITY); aList.add(ContainerTypePeer.CHILD_LABELING_SCHEME.wrap( "childLabelingSchemeName", ContainerLabelingSchemePeer.NAME)); //$NON-NLS-1$ PROPERTIES = Collections.unmodifiableList(aList); UNIQUE_NAME_PROPS = new ArrayList<Property<?, ? super ContainerType>>(); UNIQUE_NAME_PROPS.add(ContainerTypePeer.SITE.to(SitePeer.ID)); UNIQUE_NAME_PROPS.add(ContainerTypePeer.NAME); UNIQUE_NAME_SHORT_PROPS = new ArrayList<Property<?, ? super ContainerType>>(); UNIQUE_NAME_SHORT_PROPS.add(ContainerTypePeer.SITE.to(SitePeer.ID)); UNIQUE_NAME_SHORT_PROPS.add(ContainerTypePeer.NAME_SHORT); }; public ContainerTypeWrapper(WritableApplicationService appService, ContainerType wrappedObject) { super(appService, wrappedObject); } public ContainerTypeWrapper(WritableApplicationService appService) { super(appService); } @Override protected List<Property<?, ? super ContainerType>> getProperties() { return PROPERTIES; } public Collection<ContainerTypeWrapper> getChildrenRecursively() throws ApplicationException { List<ContainerTypeWrapper> allChildren = new ArrayList<ContainerTypeWrapper>(); List<ContainerTypeWrapper> children = getChildContainerTypeCollection(); if (children != null) { for (ContainerTypeWrapper type : children) { allChildren.addAll(type.getChildrenRecursively()); allChildren.add(type); } } return allChildren; } private static final String IS_USED_BY_CONTAINERS_QRY = "select count(c) from " //$NON-NLS-1$ + Container.class.getName() + " as c where c." //$NON-NLS-1$ + ContainerPeer.CONTAINER_TYPE.getName() + "=?"; //$NON-NLS-1$ public boolean isUsedByContainers() throws ApplicationException, BiobankQueryResultSizeException { HQLCriteria c = new HQLCriteria(IS_USED_BY_CONTAINERS_QRY, Arrays.asList(new Object[] { wrappedObject })); return getCountResult(appService, c) > 0; } public List<ContainerTypeWrapper> getParentContainerTypeCollection() { return getParentContainerTypeCollection(false); } public List<SpecimenTypeWrapper> getSpecimenTypeCollection() { return getSpecimenTypeCollection(true); } public Set<SpecimenTypeWrapper> getSpecimenTypesRecursively() throws ApplicationException { Set<SpecimenTypeWrapper> SpecimenTypes = new HashSet<SpecimenTypeWrapper>(); List<SpecimenTypeWrapper> sampleSubSet = getSpecimenTypeCollection(false); if (sampleSubSet != null) SpecimenTypes.addAll(sampleSubSet); for (ContainerTypeWrapper type : getChildContainerTypeCollection()) { SpecimenTypes.addAll(type.getSpecimenTypesRecursively()); } return SpecimenTypes; } public List<ContainerTypeWrapper> getChildContainerTypeCollection() { return getChildContainerTypeCollection(true); } public Integer getRowCapacity() { return getCapacity().getRowCapacity(); } public Integer getColCapacity() { return getCapacity().getColCapacity(); } public void setRowCapacity(Integer maxRows) { getCapacity().setRowCapacity(maxRows); } public void setColCapacity(Integer maxCols) { getCapacity().setColCapacity(maxCols); } public Integer getChildLabelingSchemeId() { return getProperty(getChildLabelingScheme(), ContainerLabelingSchemePeer.ID); } public void setChildLabelingSchemeById(Integer id) throws Exception { ContainerLabelingSchemeWrapper scheme = ContainerLabelingSchemeWrapper .getLabelingSchemeById(appService, id); setChildLabelingScheme(scheme); } public String getChildLabelingSchemeName() { return getProperty(getChildLabelingScheme(), ContainerLabelingSchemePeer.NAME); } public void setChildLabelingSchemeName(String name) throws Exception { for (ContainerLabelingSchemeWrapper scheme : ContainerLabelingSchemeWrapper .getAllLabelingSchemesMap(appService).values()) { if (scheme.getName().equals(name)) { setChildLabelingScheme(scheme); return; } } throw new Exception("labeling scheme with name \"" + name //$NON-NLS-1$ + "\" does not exist"); //$NON-NLS-1$ } private static final String TOP_CONTAINERS_IN_SITE_QRY = "from " //$NON-NLS-1$ + ContainerType.class.getName() + " where " //$NON-NLS-1$ + Property.concatNames(ContainerTypePeer.SITE, SitePeer.ID) + "=? and " //$NON-NLS-1$ + ContainerTypePeer.TOP_LEVEL.getName() + "=true"; //$NON-NLS-1$ public static List<ContainerTypeWrapper> getTopContainerTypesInSite( WritableApplicationService appService, SiteWrapper site) throws ApplicationException { HQLCriteria criteria = new HQLCriteria(TOP_CONTAINERS_IN_SITE_QRY, Arrays.asList(new Object[] { site.getId() })); List<ContainerType> types = appService.query(criteria); return wrapModelCollection(appService, types, ContainerTypeWrapper.class); } private static final String SITE_CONTAINER_TYPES_QRY = "from " //$NON-NLS-1$ + ContainerType.class.getName() + " where " //$NON-NLS-1$ + ContainerTypePeer.SITE.getName() + "=? and "; //$NON-NLS-1$ /** * Get containers types defined in a site. if useStrictName is true, then * the container type name should be exactly containerName, otherwise, it * should contain containerName as a substring in the name. */ public static List<ContainerTypeWrapper> getContainerTypesInSite( WritableApplicationService appService, SiteWrapper siteWrapper, String containerName, boolean useStrictName) throws ApplicationException { String nameComparison = "name ="; //$NON-NLS-1$ String containerNameParameter = containerName; if (!useStrictName) { nameComparison = "lower(name) like"; //$NON-NLS-1$ containerNameParameter = new StringBuilder("%") //$NON-NLS-1$ .append(containerName.toLowerCase()).append("%").toString(); //$NON-NLS-1$ } StringBuilder query = new StringBuilder(SITE_CONTAINER_TYPES_QRY) .append(nameComparison).append(" ?"); //$NON-NLS-1$ HQLCriteria criteria = new HQLCriteria(query.toString(), Arrays.asList(new Object[] { siteWrapper.getWrappedObject(), containerNameParameter.toString() })); List<ContainerType> containerTypes = appService.query(criteria); return wrapModelCollection(appService, containerTypes, ContainerTypeWrapper.class); } private static final String CONTAINER_TYPES_BY_CAPACITY_QRY = "select ct from " //$NON-NLS-1$ + ContainerType.class.getName() + " as ct join ct." //$NON-NLS-1$ + ContainerTypePeer.CAPACITY.getName() + " as cap where ct." //$NON-NLS-1$ + ContainerTypePeer.SITE.getName() + "=? and cap." //$NON-NLS-1$ + CapacityPeer.ROW_CAPACITY.getName() + "=? and cap." //$NON-NLS-1$ + CapacityPeer.COL_CAPACITY.getName() + "=? and ct." //$NON-NLS-1$ + ContainerTypePeer.SPECIMEN_TYPES.getName() + " is not empty and ct." //$NON-NLS-1$ + ContainerTypePeer.CHILD_CONTAINER_TYPES.getName() + " is empty"; //$NON-NLS-1$ /** * Get containers types with the given capacity in the given site. The * container types returned are ones that can only hold specimens. */ public static List<ContainerTypeWrapper> getContainerTypesByCapacity( WritableApplicationService appService, SiteWrapper siteWrapper, int maxRows, int maxCols) throws ApplicationException { HQLCriteria criteria = new HQLCriteria(CONTAINER_TYPES_BY_CAPACITY_QRY, Arrays.asList(new Object[] { siteWrapper.getWrappedObject(), maxRows, maxCols })); List<ContainerType> containerTypes = appService.query(criteria); return wrapModelCollection(appService, containerTypes, ContainerTypeWrapper.class); } public static List<ContainerTypeWrapper> getContainerTypesPallet96( WritableApplicationService appService, SiteWrapper siteWrapper) throws ApplicationException { return getContainerTypesByCapacity(appService, siteWrapper, RowColPos.PALLET_96_ROW_MAX, RowColPos.PALLET_96_COL_MAX); } private static final String CONTAINER_COUNT_QRY = "select count(*) from " //$NON-NLS-1$ + Container.class.getName() + " where containerType.id=?"; //$NON-NLS-1$ /** * get count of container which type is this */ public long getContainersCount() throws ApplicationException, BiobankException { HQLCriteria c = new HQLCriteria(CONTAINER_COUNT_QRY, Arrays.asList(new Object[] { getId() })); return getCountResult(appService, c); } @Override public int compareTo(ModelWrapper<ContainerType> type) { if (type instanceof ContainerTypeWrapper) { String c1Name = wrappedObject.getName(); String c2Name = type.wrappedObject.getName(); return ((c1Name.compareTo(c2Name) > 0) ? 1 : (c1Name.equals(c2Name) ? 0 : -1)); } return 0; } @Override public String toString() { return getName() + " (" + getNameShort() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } public String getPositionString(RowColPos position) { return ContainerLabelingSchemeWrapper.getPositionString(position, getChildLabelingSchemeId(), getRowCapacity(), getColCapacity()); } public RowColPos getRowColFromPositionString(String position) throws Exception { return ContainerLabelingSchemeWrapper.getRowColFromPositionString( getAppService(), position, getChildLabelingSchemeId(), getRowCapacity(), getColCapacity()); } public boolean isPallet96() { return RowColPos.PALLET_96_ROW_MAX.equals(getRowCapacity()) && RowColPos.PALLET_96_COL_MAX.equals(getColCapacity()); } @Deprecated @Override protected void addPersistTasks(TaskList tasks) { tasks.add(check().notNull(ContainerTypePeer.SITE)); tasks.add(check().notNull(ContainerTypePeer.CAPACITY)); tasks.add(check().notNull(ContainerTypePeer.CHILD_LABELING_SCHEME)); tasks.add(check().unique(UNIQUE_NAME_PROPS)); tasks.add(check().unique(UNIQUE_NAME_SHORT_PROPS)); // TODO: note that there are no locks on any tables so there are still // problems where a Container could be added while the checks are being // performed, so the checks would not fail. tasks.add(new ContainerTypePrePersistChecks(this)); tasks.persist(this, ContainerTypePeer.CAPACITY); super.addPersistTasks(tasks); tasks.add(new ContainerTypePostPersistChecks(this)); } @Deprecated @Override protected void addDeleteTasks(TaskList tasks) { String isUsedMsg = MessageFormat.format(CONTAINER_TYPE_IS_USED_MSG, getName()); tasks.add(check().notUsedBy(Container.class, ContainerPeer.CONTAINER_TYPE, isUsedMsg)); // When a ContainerType is deleted, remove it from all parent // ContainerType-s that use it and persist them. This was chosen to be // done because when a parent ContainerType is deleted, it is // automatically removed from all child ContainerType-s that use it. // Done for symmetrical behaviour. for (ContainerTypeWrapper parent : getParentContainerTypeCollection()) { parent.removeFromChildContainerTypeCollection(Arrays.asList(this)); parent.addPersistTasks(tasks); } super.addDeleteTasks(tasks); } }