// $HeadURL$ // $Id$ // // Copyright © 2006, 2010, 2011, 2012 by the President and Fellows of Harvard College. // // Screensaver is an open-source project developed by the ICCB-L and NSRB labs // at Harvard Medical School. This software is distributed under the terms of // the GNU General Public License. package edu.harvard.med.screensaver.model.screenresults; import java.util.HashMap; import java.util.Map; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; import javax.persistence.UniqueConstraint; import javax.persistence.Version; import com.google.common.base.Function; import org.apache.log4j.Logger; import edu.harvard.med.screensaver.model.AbstractEntity; import edu.harvard.med.screensaver.model.AbstractEntityVisitor; import edu.harvard.med.screensaver.model.DataModelViolationException; import edu.harvard.med.screensaver.model.annotations.ContainedEntity; import edu.harvard.med.screensaver.model.annotations.ToOne; import edu.harvard.med.screensaver.model.libraries.AssayWellControlTypeException; import edu.harvard.med.screensaver.model.libraries.LibraryWellType; import edu.harvard.med.screensaver.model.libraries.Well; import edu.harvard.med.screensaver.model.meta.Cardinality; import edu.harvard.med.screensaver.model.meta.RelationshipPath; import edu.harvard.med.screensaver.model.screens.Screen; /** * Groups {@link ResultValue} data generated for a library {@link Well} by a {@link Screen}. * An <code>AssayWell</code> can be thought of as a "row" of a {@link ScreenResult}. * * @author <a mailto="andrew_tolopko@hms.harvard.edu">Andrew Tolopko</a> */ @Entity @org.hibernate.annotations.Proxy @Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "screenResultId", "well_id" }) }) @ContainedEntity(containingEntityClass=ScreenResult.class) public class AssayWell extends AbstractEntity<Integer> implements Comparable<AssayWell> { private static final long serialVersionUID = 1L; private static final Logger log = Logger.getLogger(AssayWell.class); public static final RelationshipPath<AssayWell> screenResult = RelationshipPath.from(AssayWell.class).to("screenResult", Cardinality.TO_ONE); public static final RelationshipPath<AssayWell> libraryWell = RelationshipPath.from(AssayWell.class).to("libraryWell", Cardinality.TO_ONE); public static final Function<AssayWell,Integer> ToPlateNumber = new Function<AssayWell,Integer>() { public Integer apply(AssayWell aw) { return aw.getLibraryWell().getPlateNumber(); } }; private Integer _version; private ScreenResult _screenResult; private Well _libraryWell; private AssayWellControlType _assayWellControlType; private boolean _isPositive; private ConfirmedPositiveValue _confirmedPositiveValue; private Map<DataColumn,ResultValue> _resultValues = new HashMap<DataColumn,ResultValue>(); /*public*/ AssayWell(ScreenResult screenResult, Well libraryWell) { if (screenResult == null) { throw new DataModelViolationException("screenResult is required"); } if (libraryWell == null) { throw new DataModelViolationException("screenResult is required"); } _screenResult = screenResult; _libraryWell = libraryWell; // // TODO: remove, for performance of screen result import // _libraryWell.getAssayWells().put(_screenResult, this); } @Override public Object acceptVisitor(AbstractEntityVisitor visitor) { return visitor.visit(this); } @Id @org.hibernate.annotations.GenericGenerator( name="assay_well_id_seq", strategy="seqhilo", parameters = { @org.hibernate.annotations.Parameter(name="sequence", value="assay_well_id_seq"), @org.hibernate.annotations.Parameter(name="max_lo", value="384") } ) @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="assay_well_id_seq") public Integer getAssayWellId() { return getEntityId(); } /** * Get the version number of the screen result. * @return the version number of the screen result * @motivation for hibernate */ @Column(nullable=false) @Version private Integer getVersion() { return _version; } /** * Set the version number of the screen result. * @param version the new version number of the screen result * @motivation for hibernate */ private void setVersion(Integer version) { _version = version; } public int compareTo(AssayWell other) { return getLibraryWell().getWellKey().compareTo(((AssayWell) other).getLibraryWell().getWellKey()); } @ManyToOne(fetch=FetchType.LAZY, cascade={}) @JoinColumn(name="screenResultId", nullable=false, updatable=false) @org.hibernate.annotations.ForeignKey(name="fk_assay_well_to_screen_result") @org.hibernate.annotations.LazyToOne(value=org.hibernate.annotations.LazyToOneOption.PROXY) public ScreenResult getScreenResult() { return _screenResult; } private void setScreenResult(ScreenResult screenResult) { _screenResult = screenResult; } /** * Get the well. * @return the well */ @ManyToOne(fetch=FetchType.LAZY, cascade={} /*Well is owned by Library.wells*/) @JoinColumn(name="well_id", nullable=false, updatable=false) @org.hibernate.annotations.ForeignKey(name="fk_assay_well_to_well") @org.hibernate.annotations.LazyToOne(value=org.hibernate.annotations.LazyToOneOption.PROXY) @ToOne(unidirectional=true) public Well getLibraryWell() { return _libraryWell; } /** * @motivation for hibernate */ private void setLibraryWell(Well libraryWell) { _libraryWell = libraryWell; } /** * Get whether the screen has determined that the reagent in the tested well is a positive result. * * @return true if at least one the assay well's {@link ResultValue}s is a {@link ResultValue#isPositive() positive}. */ @Column(nullable=false, name="isPositive") // Note: for improved performance (in PostgreSQL) this index should be created as a partial index using "where is_positive" @org.hibernate.annotations.Index(name="assay_well_well_positives_only_index") public boolean isPositive() { return _isPositive; } // TODO // private void setResultValues(Map<DataColumn,ResultValue> resultValues) // { // _resultValues = resultValues; // } // // /** // * Get the set of result values. // * @return the set of result values // */ // @OneToMany(fetch=FetchType.LAZY, mappedBy="assayWell") // @MapKeyManyToMany(joinColumns={ @JoinColumn(name="dataColumnId") }, targetEntity=DataColumn.class) // public Map<DataColumn,ResultValue> getResultValues() // { // return _resultValues; // } public void setPositive(boolean isPositive) { _isPositive = isPositive; } @org.hibernate.annotations.Type(type = "edu.harvard.med.screensaver.model.screenresults.ConfirmedPositiveValueUserType") // Note: for improved performance (in PostgreSQL) this index should be created as a partial index using "where confirmed_positive_value is not null" @org.hibernate.annotations.Index(name = "assay_well_confirmed_positives_data_only_index") public ConfirmedPositiveValue getConfirmedPositiveValue() { return _confirmedPositiveValue; } public void setConfirmedPositiveValue(ConfirmedPositiveValue confirmedPositiveValue) { _confirmedPositiveValue = confirmedPositiveValue; } /** * Get the assay well's type. * * @return the assay well's type */ @Column(nullable=true) @org.hibernate.annotations.Type(type="edu.harvard.med.screensaver.model.screenresults.AssayWellControlType$UserType") @edu.harvard.med.screensaver.model.annotations.Column(hasNonconventionalSetterMethod = true) public AssayWellControlType getAssayWellControlType() { return _assayWellControlType; } public void setAssayWellControlType(AssayWellControlType assayWellControlType) { if (!isHibernateCaller() && assayWellControlType != null && !AssayWellControlType.isControlAllowed(_libraryWell.getLibraryWellType())) { throw new AssayWellControlTypeException(_libraryWell.getWellKey()); } _assayWellControlType = assayWellControlType; } /** * @motivation for hibernate */ protected AssayWell() {} /** * Set the well id for the well. * @param wellId the new well id for the well * @motivation for hibernate */ private void setAssayWellId(Integer assayWellId) { setEntityId(assayWellId); } }