edu.harvard.med.screensaver.model.libraries.SilencingReagent.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.med.screensaver.model.libraries.SilencingReagent.java

Source

// $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.libraries;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Transient;

import com.google.common.base.Function;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Sets;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.Immutable;
import org.hibernate.annotations.IndexColumn;
import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption;

import edu.harvard.med.screensaver.model.AbstractEntityVisitor;
import edu.harvard.med.screensaver.model.annotations.ContainedEntity;
import edu.harvard.med.screensaver.model.annotations.ToMany;
import edu.harvard.med.screensaver.model.annotations.ToOne;
import edu.harvard.med.screensaver.model.meta.Cardinality;
import edu.harvard.med.screensaver.model.meta.RelationshipPath;

/**
 * Silencing reagent of an RNAi library.
 *
 * @author <a mailto="andrew_tolopko@hms.harvard.edu">Andrew Tolopko</a>
 * @author <a mailto="john_sullivan@hms.harvard.edu">John Sullivan</a>
 */
@Entity
@Immutable
@ContainedEntity(containingEntityClass = Well.class)
public class SilencingReagent extends Reagent {
    private static final long serialVersionUID = 0L;

    public static final RelationshipPath<SilencingReagent> vendorGenes = RelationshipPath
            .from(SilencingReagent.class).to("vendorGenes", Cardinality.TO_MANY);
    public static final RelationshipPath<SilencingReagent> facilityGenes = RelationshipPath
            .from(SilencingReagent.class).to("facilityGenes", Cardinality.TO_MANY);
    public static final RelationshipPath<SilencingReagent> duplexWells = RelationshipPath
            .from(SilencingReagent.class).to("duplexWells");

    private static final Function<Well, SilencingReagent> wellToReagentTransformer = new Function<Well, SilencingReagent>() {
        public SilencingReagent apply(Well well) {
            return well.<SilencingReagent>getLatestReleasedReagent();
        }
    };

    private SilencingReagentType _silencingReagentType;
    private String _sequence;
    private String _antisenseSequence;
    private List<Gene> _vendorGenes;
    private List<Gene> _facilityGenes;
    private Set<Well> _duplexWells = Sets.newHashSet();
    private boolean _isRestrictedSequence;

    /**
     * Construct an uninitialized <code>SilencingReagent</code>.
     * @motivation for hibernate and proxy/concrete subclass constructors
     */
    protected SilencingReagent() {
    }

    /**
     * Construct a <code>SilencingReagent</code>.
     *
     * @motivation for use of {@link Well#createSilencingReagent} methods only
     */
    SilencingReagent(ReagentVendorIdentifier rvi, Well well, LibraryContentsVersion libraryContentsVersion,
            SilencingReagentType silencingReagentType, String sequence, String antiSequence) {
        super(rvi, well, libraryContentsVersion);
        _silencingReagentType = silencingReagentType;
        _sequence = sequence;
        _antisenseSequence = antiSequence;
        _vendorGenes = new ArrayList<Gene>();
        _facilityGenes = new ArrayList<Gene>();
    }

    @Override
    public Object acceptVisitor(AbstractEntityVisitor visitor) {
        return visitor.visit(this);
    }

    @Column(nullable = true)
    @org.hibernate.annotations.Type(type = "edu.harvard.med.screensaver.model.libraries.SilencingReagentType$UserType")
    public SilencingReagentType getSilencingReagentType() {
        return _silencingReagentType;
    }

    private void setSilencingReagentType(SilencingReagentType silencingReagentType) {
        _silencingReagentType = silencingReagentType;
    }

    /**
     * The genetic sequence of the silencing reagent. For pool wells, this may be
     * null (or empty), or can be a delimited list of the sequences of the
     * constituent duplexes. If left null/empty, it is still possible to find the
     * duplex sequences via {@link #getDuplexWells}.{@link Well#getLatestReleasedReagent}.
     */
    @Column(nullable = true)
    @org.hibernate.annotations.Type(type = "text")
    public String getSequence() {
        return _sequence;
    }

    private void setSequence(String sequence) {
        _sequence = sequence;
    }

    /**
     * The genetic anti-sense sequence of the silencing reagent. For pool wells, this may be
     * null (or empty), or can be a delimited list of the sequences of the
     * constituent duplexes. If left null/empty, it is still possible to find the
     * duplex sequences via {@link #getDuplexWells}.{@link Well#getLatestReleasedReagent}.
     */
    @Column(nullable = true)
    @org.hibernate.annotations.Type(type = "text")
    @edu.harvard.med.screensaver.model.annotations.Column(hasNonconventionalSetterMethod = true)
    public String getAntiSenseSequence() {
        return _antisenseSequence;
    }

    private void setAntiSenseSequence(String sequence) {
        _antisenseSequence = sequence;
    }

    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.LAZY)
    @JoinTable(name = "reagentVendorGenes", joinColumns = @JoinColumn(name = "reagentId"), inverseJoinColumns = @JoinColumn(name = "geneId"))
    @IndexColumn(name = "ordinal")
    @org.hibernate.annotations.Cascade(value = { org.hibernate.annotations.CascadeType.SAVE_UPDATE,
            org.hibernate.annotations.CascadeType.DELETE })
    @org.hibernate.annotations.ForeignKey(name = "fk_vendor_genes_to_reagent")
    @ToMany(hasNonconventionalMutation = true)
    public List<Gene> getVendorGenes() {
        return _vendorGenes;
    }

    private void setVendorGenes(List<Gene> vendorGenes) {
        _vendorGenes = vendorGenes;
    }

    @Transient
    public Gene getVendorGene() {
        if (_vendorGenes == null) {
            _vendorGenes = new ArrayList<Gene>();
        }

        if (_vendorGenes.size() == 0 && getEntityId() == null) {
            _vendorGenes.add(new Gene());
        }

        return _vendorGenes.size() == 0 ? null : _vendorGenes.get(0);
    }

    /**
     * Optional gene information provided by the screening facility, which can
     * differ from the vendor-provided gene information ({@link #getVendorGene()}).
     * In particular if updated gene information is available (names, symbols,
     * etc.), this can be reflected here, without affecting the original gene
     * information provided by the vendor. Also, if it is determined that this
     * silencing reagent in fact targets a different gene than expected, the
     * facility gene information can be used reflect this fact.
     */
    @OneToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE }, fetch = FetchType.LAZY)
    @JoinTable(name = "reagentFacilityGenes", joinColumns = @JoinColumn(name = "reagentId"), inverseJoinColumns = @JoinColumn(name = "geneId"))
    @IndexColumn(name = "ordinal")
    @org.hibernate.annotations.Cascade(value = { org.hibernate.annotations.CascadeType.SAVE_UPDATE,
            org.hibernate.annotations.CascadeType.DELETE })
    @org.hibernate.annotations.ForeignKey(name = "fk_facility_genes_to_reagent")
    @ToMany(hasNonconventionalMutation = true)
    public List<Gene> getFacilityGenes() {
        return _facilityGenes;
    }

    private void setFacilityGenes(List<Gene> facilityGenes) {
        _facilityGenes = facilityGenes;
    }

    @Transient
    public Gene getFacilityGene() {
        if (_facilityGenes == null) {
            _facilityGenes = new ArrayList<Gene>();
        }

        if (_facilityGenes.size() == 0 && getEntityId() == null) {
            _facilityGenes.add(new Gene());
        }

        return _facilityGenes.size() == 0 ? null : _facilityGenes.get(0);
    }

    @ManyToMany(cascade = {}, fetch = FetchType.LAZY)
    @JoinTable(joinColumns = @JoinColumn(name = "silencing_reagent_id"), inverseJoinColumns = @JoinColumn(name = "wellId"))
    @Cascade({})
    @LazyCollection(LazyCollectionOption.TRUE)
    @ToMany(unidirectional = true, hasNonconventionalMutation = true)
    public Set<Well> getDuplexWells() {
        return _duplexWells;
    }

    private void setDuplexWells(Set<Well> duplexWells) {
        _duplexWells = duplexWells;
    }

    /**
     * Builder method when creating a new SilencingReagent, prior to being
     * persisted. Note: it is up to the client code to validate that the duplex
     * well targets the same gene as the pool (e.g., entrezgene IDs match, or
     * whatever "similarity" criteria is deemed appropriate for determining that
     * targeted gene is the same); the model allows for real-world errors, where a
     * pool well is erroneously contains silencing reagents that target different
     * genes.
     */
    public SilencingReagent withDuplexWell(Well duplexWell) {
        validateImmutablePropertyInitialization();
        _duplexWells.add(duplexWell);
        return this;
    }

    @Transient
    public Set<SilencingReagent> getDuplexSilencingReagents() {
        Iterable<SilencingReagent> reagents = Iterables.transform(getDuplexWells(), wellToReagentTransformer);
        reagents = Iterables.filter(reagents, Predicates.notNull());
        return ImmutableSet.copyOf(reagents);
    }

    @Column(name = "is_restricted_sequence", nullable = false)
    public boolean isRestrictedSequence() {
        return _isRestrictedSequence;
    }

    private void setRestrictedSequence(boolean isRestrictedSequence) {
        _isRestrictedSequence = isRestrictedSequence;
    }

    public SilencingReagent withRestrictedSequence(boolean isRestrictedSequence) {
        validateImmutablePropertyInitialization();
        setRestrictedSequence(isRestrictedSequence);
        return this;
    }
}