/*
* Copyright (c) 2012. The Genome Analysis Centre, Norwich, UK
* MISO project contacts: Robert Davey, Mario Caccamo @ TGAC
* *********************************************************************
*
* This file is part of MISO.
*
* MISO is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MISO is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MISO. If not, see <http://www.gnu.org/licenses/>.
*
* *********************************************************************
*/
package uk.ac.bbsrc.tgac.miso.core.data;
import com.eaglegenomics.simlims.core.Note;
import com.eaglegenomics.simlims.core.SecurityProfile;
import com.eaglegenomics.simlims.core.User;
import org.w3c.dom.Document;
import uk.ac.bbsrc.tgac.miso.core.exception.MalformedLibraryException;
import uk.ac.bbsrc.tgac.miso.core.exception.MalformedSampleException;
import uk.ac.bbsrc.tgac.miso.core.exception.MalformedSampleQcException;
import uk.ac.bbsrc.tgac.miso.core.security.SecurableByProfile;
import javax.persistence.*;
import java.util.*;
/**
* Skeleton implementation of a Sample
*
* @author Rob Davey
* @since 0.0.2
*/
@Entity
@Table(name = "`Sample`")
public abstract class AbstractSample implements Sample {
public static final Long UNSAVED_ID = 0L;
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long sampleId = AbstractSample.UNSAVED_ID;
private Project project;
@ManyToMany(targetEntity = AbstractExperiment.class, mappedBy = "samples")
private Collection<Experiment> experiments = new HashSet<Experiment>();
private Collection<Library> libraries = new HashSet<Library>();
private Collection<SampleQC> sampleQCs = new TreeSet<SampleQC>();
private Collection<Note> notes = new HashSet<Note>();
private Set<Plate<? extends LinkedList<Sample>, Sample>> plates = new HashSet<Plate<? extends LinkedList<Sample>, Sample>>();
@Transient
public Document submissionDocument;
@OneToOne(cascade = CascadeType.ALL)
private SecurityProfile securityProfile = null;
private String accession;
private String name;
private String description;
private String scientificName;
private String taxonIdentifier;
private String sampleType;
private Date receivedDate;
private Boolean qcPassed;
private String identificationBarcode;
private String locationBarcode;
private String alias;
private Date lastUpdated;
public Project getProject() {
return project;
}
public void setProject(Project project) {
this.project = project;
}
@Deprecated
public Long getSampleId() {
return sampleId;
}
@Deprecated
public void setSampleId(Long sampleId) {
this.sampleId = sampleId;
}
@Override
public long getId() {
return sampleId;
}
@Override
public void setId(long id) {
this.sampleId = id;
}
public String getAccession() {
return accession;
}
public void setAccession(String accession) {
this.accession = accession;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getScientificName() {
return scientificName;
}
public void setScientificName(String scientificName) {
this.scientificName = scientificName;
}
public String getTaxonIdentifier() {
return taxonIdentifier;
}
public void setTaxonIdentifier(String taxonIdentifier) {
this.taxonIdentifier = taxonIdentifier;
}
public String getAlias() {
return alias;
}
public void setAlias(String alias) {
this.alias = alias;
}
public String getIdentificationBarcode() {
return identificationBarcode;
}
public void setIdentificationBarcode(String identificationBarcode) {
this.identificationBarcode = identificationBarcode;
}
public String getLocationBarcode() {
return locationBarcode;
}
public void setLocationBarcode(String locationBarcode) {
this.locationBarcode = locationBarcode;
}
public String getLabelText() {
return getAlias();
}
public void addLibrary(Library l) throws MalformedLibraryException {
this.libraries.add(l);
}
public Collection<Library> getLibraries() {
return libraries;
}
public void addQc(SampleQC sampleQc) throws MalformedSampleQcException {
this.sampleQCs.add(sampleQc);
try {
sampleQc.setSample(this);
}
catch (MalformedSampleException e) {
e.printStackTrace();
}
}
public Collection<SampleQC> getSampleQCs() {
return sampleQCs;
}
public void setQCs(Collection<SampleQC> qcs) {
this.sampleQCs = qcs;
}
public String getSampleType() {
return sampleType;
}
public Date getReceivedDate() {
return receivedDate;
}
public Boolean getQcPassed() {
return qcPassed;
}
public void setSampleType(String sampleType) {
this.sampleType = sampleType;
}
public void setReceivedDate(Date receivedDate) {
this.receivedDate = receivedDate;
}
public void setQcPassed(Boolean qcPassed) {
this.qcPassed = qcPassed;
}
/*
public Document getSubmissionData() {
return submissionDocument;
}
public void accept(SubmittableVisitor v) {
v.visit(this);
}
*/
public Collection<Note> getNotes() {
return notes;
}
public void addNote(Note note) {
this.notes.add(note);
}
public void setNotes(Collection<Note> notes) {
this.notes = notes;
}
@Override
public Set<Plate<? extends LinkedList<Sample>, Sample>> getPlates() {
return plates;
}
public void addPlate(Plate<? extends LinkedList<Sample>, Sample> plate) {
this.plates.add(plate);
}
public void setPlates(Set<Plate<? extends LinkedList<Sample>, Sample>> plates) {
this.plates = plates;
}
public Date getLastUpdated() {
return lastUpdated;
}
public void setLastUpdated(Date lastUpdated) {
this.lastUpdated = lastUpdated;
}
public boolean isDeletable() {
return getId() != AbstractSample.UNSAVED_ID &&
getLibraries().isEmpty() &&
getNotes().isEmpty() &&
getSampleQCs().isEmpty();
}
public SecurityProfile getSecurityProfile() {
return securityProfile;
}
public void setSecurityProfile(SecurityProfile securityProfile) {
this.securityProfile = securityProfile;
}
public void inheritPermissions(SecurableByProfile parent) throws SecurityException {
if (parent.getSecurityProfile().getOwner() != null) {
setSecurityProfile(parent.getSecurityProfile());
}
else {
throw new SecurityException("Cannot inherit permissions when parent object owner is not set!");
}
}
public boolean userCanRead(User user) {
return securityProfile.userCanRead(user);
}
public boolean userCanWrite(User user) {
return securityProfile.userCanWrite(user);
}
public abstract void buildSubmission();
public abstract void buildReport();
/**
* Equivalency is based on getSampleId() if set, otherwise on name, otherwise on alias
*/
@Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (!(obj instanceof Sample))
return false;
Sample them = (Sample) obj;
// If not saved, then compare resolved actual objects. Otherwise
// just compare IDs.
if (getId() == AbstractSample.UNSAVED_ID || them.getId() == AbstractSample.UNSAVED_ID) {
if (getName() != null && them.getName() != null) {
return getName().equals(them.getName());
}
else if (getAlias() != null && them.getAlias() != null) {
return getAlias().equals(them.getAlias());
}
else {
return false;
}
}
else {
return getId() == them.getId();
}
}
@Override
public int hashCode() {
if (getId() != 0L && getId() != AbstractSample.UNSAVED_ID) {
return (int)getId();
}
else {
final int PRIME = 37;
int hashcode = 1;
if (getName() != null) hashcode = PRIME * hashcode + getName().hashCode();
// if (getDescription() != null) hashcode = 37 * hashcode + getDescription().hashCode();
// if (getLibraries() != null && !getLibraries().isEmpty()) hashcode = 37 * hashcode + getLibraries().hashCode();
// if (getSampleQCs() != null && !getSampleQCs().isEmpty()) hashcode = 37 * hashcode + getSampleQCs().hashCode();
if (getAlias() != null) hashcode = PRIME * hashcode + getAlias().hashCode();
return hashcode;
}
}
@Override
public int compareTo(Object o) {
Sample s = (Sample)o;
if (getId() != 0L && s.getId() != 0L) {
if (getId() < s.getId()) return -1;
if (getId() > s.getId()) return 1;
}
else if (getAlias() != null && s.getAlias() != null) {
return getAlias().compareTo(s.getAlias());
}
return 0;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getId());
sb.append(" : ");
sb.append(getName());
sb.append(" : ");
sb.append(getAlias());
sb.append(" : ");
sb.append(getIdentificationBarcode());
sb.append(" : ");
sb.append(getDescription());
sb.append(" : ");
sb.append(getScientificName());
sb.append(" : ");
sb.append(getSampleType());
return sb.toString();
}
}