package edu.ualberta.med.biobank.test; import java.math.BigInteger; import java.util.Date; import java.util.Random; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicInteger; import org.hibernate.Session; import org.hibernate.criterion.Restrictions; import edu.ualberta.med.biobank.model.Capacity; import edu.ualberta.med.biobank.model.Center; import edu.ualberta.med.biobank.model.CollectionEvent; import edu.ualberta.med.biobank.model.Container; import edu.ualberta.med.biobank.model.ContainerLabelingScheme; import edu.ualberta.med.biobank.model.ContainerPosition; import edu.ualberta.med.biobank.model.ContainerType; import edu.ualberta.med.biobank.model.Group; import edu.ualberta.med.biobank.model.Membership; import edu.ualberta.med.biobank.model.OriginInfo; import edu.ualberta.med.biobank.model.Patient; import edu.ualberta.med.biobank.model.PermissionEnum; import edu.ualberta.med.biobank.model.Principal; import edu.ualberta.med.biobank.model.Rank; import edu.ualberta.med.biobank.model.Role; import edu.ualberta.med.biobank.model.Site; import edu.ualberta.med.biobank.model.Specimen; import edu.ualberta.med.biobank.model.SpecimenPosition; import edu.ualberta.med.biobank.model.SpecimenType; import edu.ualberta.med.biobank.model.Study; import edu.ualberta.med.biobank.model.User; /** * Tries to make setting up test data easier by requiring the absolute minimum * amount of data and remembering the last created object and using that as a * default for other objects. * * @author Jonathan Ferland * */ public class Factory { private static final Random R = new Random(); private final ContainerLabelingSchemeGetter schemeGetter; private final NameGenerator nameGenerator; private final Session session; private Site defaultSite; private Center defaultCenter; private ContainerType defaultTopContainerType; private ContainerType defaultContainerType; private SpecimenType defaultSpecimenType; private Container defaultTopContainer; private Container defaultParentContainer; private Container defaultContainer; private Specimen defaultSpecimen; private ContainerLabelingScheme defaultContainerLabelingScheme; private Capacity defaultCapacity = new Capacity(5, 5); private Study defaultStudy; private Patient defaultPatient; private CollectionEvent defaultCollectionEvent; private OriginInfo defaultOriginInfo; private User defaultUser; private Group defaultGroup; private Principal defaultPrincipal; private Membership defaultMembership; private Role defaultRole; public Factory(Session session) { this(session, new BigInteger(130, R).toString(32)); } public Factory(Session session, String root) { this.session = session; this.nameGenerator = new NameGenerator(root); this.schemeGetter = new ContainerLabelingSchemeGetter(); } public Role getDefaultRole() { if (defaultRole == null) { defaultRole = createRole(); } return defaultRole; } public void setDefaultRole(Role defaultRole) { this.defaultRole = defaultRole; } public Center getDefaultCenter() { if (defaultCenter == null) { defaultCenter = createSite(); } return defaultCenter; } public void setDefaultCenter(Center defaultCenter) { this.defaultCenter = defaultCenter; } public Group getDefaultGroup() { if (defaultGroup == null) { defaultGroup = createGroup(); } return defaultGroup; } public void setDefaultGroup(Group defaultGroup) { this.defaultGroup = defaultGroup; } public Principal getDefaultPrincipal() { if (defaultPrincipal == null) { defaultPrincipal = createUser(); } return defaultPrincipal; } public void setDefaultPrincipal(Principal defaultPrincipal) { this.defaultPrincipal = defaultPrincipal; } public User getDefaultUser() { if (defaultUser == null) { defaultUser = createUser(); } return defaultUser; } public void setDefaultUser(User defaultUser) { this.defaultUser = defaultUser; } public Membership getDefaultMembership() { if (defaultMembership == null) { defaultMembership = createMembership(); } return defaultMembership; } public void setDefaultMembership(Membership defaultMembership) { this.defaultMembership = defaultMembership; } public Container getDefaultParentContainer() { return defaultParentContainer; } public void setDefaultParentContainer(Container defaultParentContainer) { this.defaultParentContainer = defaultParentContainer; } public Container getDefaultTopContainer() { if (defaultTopContainer == null) { defaultTopContainer = createTopContainer(); } return defaultTopContainer; } public void setDefaultTopContainer(Container defaultTopContainer) { this.defaultTopContainer = defaultTopContainer; } public ContainerType getDefaultTopContainerType() { if (defaultTopContainerType == null) { defaultTopContainerType = createTopContainerType(); } return defaultTopContainerType; } public void setDefaultTopContainerType(ContainerType defaultTopContainerType) { this.defaultTopContainerType = defaultTopContainerType; } public OriginInfo getDefaultOriginInfo() { if (defaultOriginInfo == null) { defaultOriginInfo = createOriginInfo(); } return defaultOriginInfo; } public void setDefaultOriginInfo(OriginInfo defaultOriginInfo) { this.defaultOriginInfo = defaultOriginInfo; } public Study getDefaultStudy() { if (defaultStudy == null) { defaultStudy = createStudy(); } return defaultStudy; } public void setDefaultStudy(Study defaultStudy) { this.defaultStudy = defaultStudy; } public Patient getDefaultPatient() { if (defaultPatient == null) { defaultPatient = createPatient(); } return defaultPatient; } public void setDefaultPatient(Patient defaultPatient) { this.defaultPatient = defaultPatient; } public CollectionEvent getDefaultCollectionEvent() { if (defaultCollectionEvent == null) { defaultCollectionEvent = createCollectionEvent(); } return defaultCollectionEvent; } public void setDefaultCollectionEvent(CollectionEvent defaultCollectionEvent) { this.defaultCollectionEvent = defaultCollectionEvent; } public Site getDefaultSite() { if (defaultSite == null) { defaultSite = createSite(); } return defaultSite; } public void setDefaultSite(Site defaultSite) { this.defaultSite = defaultSite; } public ContainerType getDefaultContainerType() { if (defaultContainerType == null) { defaultContainerType = createContainerType(); } return defaultContainerType; } public void setDefaultContainerType(ContainerType defaultContainerType) { this.defaultContainerType = defaultContainerType; } public Container getDefaultContainer() { if (defaultContainer == null) { defaultContainer = createContainer(); } return defaultContainer; } public void setDefaultContainer(Container defaultContainer) { this.defaultContainer = defaultContainer; } public ContainerLabelingScheme getDefaultContainerLabelingScheme() { if (defaultContainerLabelingScheme == null) { defaultContainerLabelingScheme = getScheme().getSbs(); } return defaultContainerLabelingScheme; } public void setDefaultContainerLabelingScheme( ContainerLabelingScheme defaultContainerLabelingScheme) { this.defaultContainerLabelingScheme = defaultContainerLabelingScheme; } public Capacity getDefaultCapacity() { return defaultCapacity; } public void setDefaultCapacity(Capacity defaultCapacity) { this.defaultCapacity = defaultCapacity; } public SpecimenType getDefaultSpecimenType() { if (defaultSpecimenType == null) { defaultSpecimenType = createSpecimenType(); } return defaultSpecimenType; } public void setDefaultSpecimenType(SpecimenType defaultSpecimenType) { this.defaultSpecimenType = defaultSpecimenType; } public Specimen getDefaultSpecimen() { if (defaultSpecimen == null) { defaultSpecimen = createSpecimen(); } return defaultSpecimen; } public void setDefaultSpecimen(Specimen defaultSpecimen) { this.defaultSpecimen = defaultSpecimen; } public Site createSite() { String name = nameGenerator.next(Site.class); Site site = new Site(); site.setName(name); site.setNameShort(name); site.getAddress().setCity("testville"); setDefaultSite(site); setDefaultCenter(site); session.save(site); session.flush(); return site; } public ContainerType createContainerType() { String name = nameGenerator.next(ContainerType.class); ContainerType containerType = new ContainerType(); containerType.setName(name); containerType.setNameShort(name); containerType.setSite(getDefaultSite()); containerType.setCapacity(new Capacity(getDefaultCapacity())); containerType .setChildLabelingScheme(getDefaultContainerLabelingScheme()); setDefaultContainerType(containerType); session.save(containerType); session.flush(); return containerType; } public ContainerType createTopContainerType() { ContainerType oldDefaultContainerType = getDefaultContainerType(); ContainerType topContainerType = createContainerType(); topContainerType.setTopLevel(true); // restore the old, non-topLevel ContainerType setDefaultContainerType(oldDefaultContainerType); setDefaultTopContainerType(topContainerType); session.update(topContainerType); session.flush(); return topContainerType; } public Container createContainer() { String label = nameGenerator.next(Container.class); Container container = new Container(); container.setSite(getDefaultSite()); if (!getDefaultTopContainerType().getSite().equals( container.getSite())) { // make sure sites match createTopContainerType(); } container.setContainerType(getDefaultTopContainerType()); container.setLabel(label); container.setTopContainer(container); Container parentContainer = getDefaultParentContainer(); if (parentContainer != null) { ContainerType containerType = getDefaultContainerType(); if (!containerType.getSite().equals(container.getSite())) { // make sure sites match containerType = createContainerType(); } container.setContainerType(containerType); ContainerType parentCt = parentContainer.getContainerType(); parentCt.getChildContainerTypes().add(containerType); containerType.getParentContainerTypes().add(parentCt); session.update(parentCt); session.flush(); Integer numChildren = parentContainer.getChildPositions().size(); Integer row = numChildren / parentCt.getRowCapacity(); Integer col = numChildren % parentCt.getColCapacity(); ContainerPosition cp = new ContainerPosition(); cp.setRow(row); cp.setCol(col); cp.setContainer(container); container.setPosition(cp); cp.setParentContainer(parentContainer); parentContainer.getChildPositions().add(cp); container.setTopContainer(parentContainer.getTopContainer()); } setDefaultContainer(container); session.save(container); session.flush(); return container; } public Container createTopContainer() { setDefaultParentContainer(null); Container topContainer = createContainer(); setDefaultTopContainer(topContainer); setDefaultParentContainer(topContainer); session.update(topContainer); session.flush(); return topContainer; } public Container createParentContainer() { Container parentContainer = createContainer(); setDefaultParentContainer(parentContainer); session.update(parentContainer); session.flush(); return parentContainer; } public SpecimenType createSpecimenType() { String name = nameGenerator.next(SpecimenType.class); SpecimenType specimenType = new SpecimenType(); specimenType.setName(name); specimenType.setNameShort(name); setDefaultSpecimenType(specimenType); session.save(specimenType); session.flush(); return specimenType; } public Specimen createSpecimen() { String name = nameGenerator.next(Specimen.class); Specimen specimen = new Specimen(); specimen.setInventoryId(name); specimen.setSpecimenType(getDefaultSpecimenType()); specimen.setCurrentCenter(getDefaultSite()); specimen.setCollectionEvent(getDefaultCollectionEvent()); specimen.setOriginInfo(getDefaultOriginInfo()); specimen.setCreatedAt(new Date()); setDefaultSpecimen(specimen); session.save(specimen); session.flush(); return specimen; } public Specimen createPositionedSpecimen() { Specimen assignedSpecimen = createSpecimen(); Container parentContainer = getDefaultContainer(); ContainerType parentCt = parentContainer.getContainerType(); parentCt.getSpecimenTypes().add(assignedSpecimen.getSpecimenType()); session.update(parentCt); session.flush(); Integer numSpecimens = parentContainer.getSpecimenPositions().size(); Integer row = numSpecimens / parentCt.getRowCapacity(); Integer col = numSpecimens % parentCt.getColCapacity(); SpecimenPosition sp = new SpecimenPosition(); sp.setRow(row); sp.setCol(col); sp.setPositionString("asdf"); // TODO: set this right sp.setSpecimen(assignedSpecimen); assignedSpecimen.setSpecimenPosition(sp); sp.setContainer(parentContainer); parentContainer.getSpecimenPositions().add(sp); session.update(assignedSpecimen); session.flush(); return assignedSpecimen; } public Study createStudy() { String name = nameGenerator.next(Study.class); Study study = new Study(); study.setName(name); study.setNameShort(name); setDefaultStudy(study); session.save(study); session.flush(); return study; } public CollectionEvent createCollectionEvent() { CollectionEvent collectionEvent = new CollectionEvent(); // make sure the patient has this collection events so we can use the // set to generate a sensible default visit number. Patient patient = getDefaultPatient(); collectionEvent.setPatient(patient); patient.getCollectionEvents().add(collectionEvent); int numCEs = patient.getCollectionEvents().size(); collectionEvent.setVisitNumber(numCEs + 1); setDefaultCollectionEvent(collectionEvent); session.save(collectionEvent); session.update(patient); session.flush(); return collectionEvent; } public Patient createPatient() { String name = nameGenerator.next(Patient.class); Patient patient = new Patient(); patient.setPnumber(name); patient.setStudy(getDefaultStudy()); patient.setCreatedAt(new Date()); setDefaultPatient(patient); session.save(patient); session.flush(); return patient; } public OriginInfo createOriginInfo() { OriginInfo originInfo = new OriginInfo(); originInfo.setCenter(getDefaultSite()); // TODO: what about ShippingInfo? setDefaultOriginInfo(originInfo); session.save(originInfo); session.flush(); return originInfo; } public User createUser() { String name = nameGenerator.next(User.class); User user = new User(); user.setLogin(name); user.setEmail(name); user.setFullName("joe testonson"); // cheap fix to avoid actually having to create a CSM user user.setCsmUserId(-Math.abs(R.nextLong())); // temporary membership, for creating Membership m = new Membership(); m.setPrincipal(user); user.getMemberships().add(m); setDefaultUser(user); setDefaultPrincipal(user); session.save(user); session.flush(); // remove membership user.getMemberships().clear(); session.delete(m); session.update(user); session.flush(); return user; } public Group createGroup() { String name = nameGenerator.next(Group.class); Group group = new Group(); group.setName(name); group.setDescription(name); // temporary membership, for creating Membership m = new Membership(); m.setPrincipal(group); group.getMemberships().add(m); setDefaultGroup(group); setDefaultPrincipal(group); session.save(group); session.flush(); // remove membership group.getMemberships().clear(); session.delete(m); session.update(group); session.flush(); return group; } public Membership createMembership() { return createMembership(Domain.CENTER_STUDY, Rank.NORMAL); } public enum Domain { GLOBAL, CENTER, STUDY, CENTER_STUDY; } public Membership createMembership(Domain domain, Rank rank) { Membership membership = new Membership(); if (domain == Domain.CENTER || domain == Domain.CENTER_STUDY) { membership.getDomain().getCenters().add(getDefaultCenter()); } if (domain == Domain.STUDY || domain == Domain.CENTER_STUDY) { membership.getDomain().getStudies().add(getDefaultStudy()); } Principal p = getDefaultPrincipal(); p.getMemberships().add(membership); membership.setPrincipal(p); membership.setUserManager(rank.isGe(Rank.MANAGER) ? true : false); membership.setEveryPermission(rank.isGe(Rank.ADMINISTRATOR) ? true : false); if (Rank.MANAGER.equals(rank)) { // needs at least one permission or role to manage membership.getPermissions().add(PermissionEnum.CLINIC_READ); } setDefaultMembership(membership); session.save(membership); session.flush(); return membership; } public Role createRole() { String name = nameGenerator.next(Role.class); Role role = new Role(); role.setName(name); setDefaultRole(role); session.save(role); session.flush(); return role; } public ContainerLabelingSchemeGetter getScheme() { return schemeGetter; } public class ContainerLabelingSchemeGetter { public ContainerLabelingScheme getSbs() { return (ContainerLabelingScheme) session .createCriteria(ContainerLabelingScheme.class) .add(Restrictions.idEq(1)) .uniqueResult(); } public ContainerLabelingScheme get2CharAlphabetic() { return (ContainerLabelingScheme) session .createCriteria(ContainerLabelingScheme.class) .add(Restrictions.idEq(6)) .uniqueResult(); } } public String getName(Class<?> klazz) { return nameGenerator.next(klazz); } public class NameGenerator { private static final String DELIMITER = "_"; private final String root; private final ConcurrentHashMap<Class<?>, AtomicInteger> suffixes = new ConcurrentHashMap<Class<?>, AtomicInteger>(); private NameGenerator(String root) { this.root = root; } String next(Class<?> klazz) { suffixes.putIfAbsent(klazz, new AtomicInteger(1)); StringBuilder sb = new StringBuilder(); sb.append(root); sb.append(DELIMITER); sb.append(suffixes.get(klazz).incrementAndGet()); return sb.toString(); } } }