2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
9 package eu
.etaxonomy
.cdm
.model
.molecular
;
11 import java
.util
.HashSet
;
14 import javax
.persistence
.Column
;
15 import javax
.persistence
.Entity
;
16 import javax
.persistence
.FetchType
;
17 import javax
.persistence
.ManyToOne
;
18 import javax
.persistence
.OneToMany
;
19 import javax
.xml
.bind
.annotation
.XmlAccessType
;
20 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
21 import javax
.xml
.bind
.annotation
.XmlAttribute
;
22 import javax
.xml
.bind
.annotation
.XmlElement
;
23 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
24 import javax
.xml
.bind
.annotation
.XmlIDREF
;
25 import javax
.xml
.bind
.annotation
.XmlRootElement
;
26 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
27 import javax
.xml
.bind
.annotation
.XmlType
;
29 import org
.apache
.log4j
.Logger
;
30 import org
.hibernate
.annotations
.Cascade
;
31 import org
.hibernate
.annotations
.CascadeType
;
32 import org
.hibernate
.envers
.Audited
;
33 import org
.hibernate
.search
.annotations
.Field
;
34 import org
.hibernate
.search
.annotations
.IndexedEmbedded
;
36 import eu
.etaxonomy
.cdm
.model
.common
.AnnotatableEntity
;
37 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTerm
;
38 import eu
.etaxonomy
.cdm
.model
.common
.EventBase
;
39 import eu
.etaxonomy
.cdm
.model
.common
.TermType
;
40 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
41 import eu
.etaxonomy
.cdm
.model
.occurrence
.DerivedUnit
;
44 * The physical process of amplification (also called PCR) extracts and replicates parts of the DNA of
45 * a given {@link #getDnaSample() DNA Sample} . The part of the DNA being replicated is defined by the
46 * {@link Amplification#getDnaMarker() marker} (also called locus) - implemented in CDM as a {@link DefinedTerm}
47 * of term type {@link TermType#DnaMarker}.
50 * To execute the replication {@link Primer primers} (short DNA fractions) are
51 * used. They may work in both directions of the DNA part therefore we do have a
52 * {@link #getForwardPrimer() forward primer} and a {@link #getReversePrimer() reverse primer}.
53 * Most (or all?) amplifications require a {@link #getPurification() purification process}. Additionally
54 * some use {@link #getCloning()} for replication.
56 * <H3>Quality control</H3>
58 * For quality control the resulting product (PCR) is tested using a chromatographic method called
59 * electrophoresis. The parameters (voltage, ladder used, running time, and gel concentration) used
60 * for this electrophoresis as well as the resulting
61 * {@link #getGelPhoto() photo} are also relevant for an amplification.
63 * We have 2 classes to store the core data for an amplification: {@link Amplification} and {@link AmplificationResult}.
65 * In {@link Amplification} we store all data that is equal for an amplification event which includes amplification
66 * of many {@link DnaSample dna samples}. Those data which are relevant only for a specific dna sample are
67 * stored in {@link AmplificationResult}. Theoretically this includes data on the resulting PCR. However, as the
68 * PCR itself is not persistent we do not store further information on it in the CDM and do not handle
69 * {@link AmplificationResult} as a {@link DerivedUnit}.
71 * This may change in future: http://dev.e-taxonomy.eu/trac/ticket/3717.
79 @XmlAccessorType(XmlAccessType
.FIELD
)
80 @XmlType(name
= "AmplificationResult", propOrder
= {
89 @XmlRootElement(name
= "AmplificationResult")
92 public class AmplificationResult
extends AnnotatableEntity
implements Cloneable
{
93 private static final long serialVersionUID
= -8614860617229484621L;
94 private static final Logger logger
= Logger
.getLogger(AmplificationResult
.class);
97 /** @see #getDnaSample() */
98 @XmlElement( name
= "DnaSample")
100 @XmlSchemaType(name
= "IDREF")
101 @ManyToOne(fetch
= FetchType
.LAZY
)
103 private DnaSample dnaSample
;
105 /** @see #getAmplification() */
106 @XmlElement( name
= "Amplification")
108 @XmlSchemaType(name
= "IDREF")
109 @ManyToOne(fetch
= FetchType
.LAZY
)
110 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
112 private Amplification amplification
;
114 @XmlElementWrapper(name
= "SingleReads")
115 @XmlElement(name
= "SingleRead")
117 @XmlSchemaType(name
= "IDREF")
118 @OneToMany(mappedBy
="amplificationResult" , fetch
= FetchType
.LAZY
)
119 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
120 private Set
<SingleRead
> singleReads
= new HashSet
<SingleRead
>();
122 @XmlElement(name
= "Cloning")
124 @XmlSchemaType(name
= "IDREF")
125 @ManyToOne(fetch
=FetchType
.LAZY
)
126 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
127 private Cloning cloning
;
129 /** @see #getSuccessful() */
130 @XmlAttribute(name
= "successful")
131 private Boolean successful
;
133 /** @see #getSuccessText() */
134 @XmlElement(name
= "successText")
137 private String successText
;
139 // /** @see #getGelRunningTime() */
140 // @XmlElement(name = "gelRunningTime")
141 // @Field(analyze = Analyze.NO)
143 // private Double gelRunningTime;
145 @XmlElement(name
= "GelPhoto")
147 @XmlSchemaType(name
= "IDREF")
148 @ManyToOne(fetch
=FetchType
.LAZY
)
149 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
150 private Media gelPhoto
;
153 // ********************* FACTORY METHODS ************************/
155 public static AmplificationResult
NewInstance(DnaSample dnaSample
){
156 AmplificationResult result
= new AmplificationResult();
157 dnaSample
.addAmplificationResult(result
);
161 public static AmplificationResult
NewInstance(SingleRead singleRead
){
162 AmplificationResult result
= new AmplificationResult();
163 result
.addSingleRead(singleRead
);
167 public static AmplificationResult
NewInstance(DnaSample dnaSample
,
168 Amplification amplification
) {
169 AmplificationResult result
= new AmplificationResult();
170 dnaSample
.addAmplificationResult(result
);
171 result
.setAmplification(amplification
);
175 public static AmplificationResult
NewInstance(){
176 return new AmplificationResult();
180 // ******************* CONSTRUCTOR *******************************/
182 protected AmplificationResult(){}
185 //********************* GETTER / SETTER ************/
189 * The {@link DnaSample dna sample} which is the input for this {@link AmplificationResult amplification}.
191 public DnaSample
getDnaSample() {
196 * For use by DnaSample.addAmplification(ampl.) only. For now.
197 * @see #getDnaSample()
199 protected void setDnaSample(DnaSample dnaSample
) {
200 this.dnaSample
= dnaSample
;
204 * The {@link Amplification amplification event} this amplification result resulted from.
205 * @see #setAmplification(Amplification)
207 * @return the amplification event
209 public Amplification
getAmplification() {
210 return amplification
;
213 * {@link #getAmplification()}
214 * @param amplification
216 public void setAmplification(Amplification amplification
) {
217 this.amplification
= amplification
;
221 * The {@link SingleRead single sequences} created by using this amplification's result (PCR).
223 public Set
<SingleRead
> getSingleReads() {
227 public void addSingleRead(SingleRead singleRead
){
228 if (singleRead
.getAmplificationResult() != null){
229 singleRead
.getAmplificationResult().singleReads
.remove(singleRead
);
231 this.singleReads
.add(singleRead
);
232 singleRead
.setAmplificationResult(this);
235 public void removeSingleRead(SingleRead singleRead
){
236 if(this.singleReads
.contains(singleRead
)){
237 this.singleReads
.remove(singleRead
);
238 singleRead
.setAmplificationResult(null);
243 * @see #getSingleReads()
245 //TODO private until it is clear how bidirectionality is handled
246 @SuppressWarnings("unused")
247 private void setSingleReads(Set
<SingleRead
> singleReads
) {
248 this.singleReads
= singleReads
;
252 * Information if this amplification was successful or not. Success may be defined
253 * by the results of the electrophoresis.
255 * @see #getSuccessText()
257 public Boolean
getSuccessful() {
262 * @see #getSuccessful()
263 * @see #getSuccessText()
265 public void setSuccessful(Boolean successful
) {
266 this.successful
= successful
;
270 * Freetext about the success of this amplification explaining
271 * in detail why it is concidered to be successful/unsucessful
273 * @see #getSuccessful()
275 public String
getSuccessText() {
280 * @see #getSuccessText()
281 * @see #getSuccessful()
283 public void setSuccessText(String successText
) {
284 this.successText
= successText
;
288 * The {@link Cloning cloning process} involved in this amplification.
290 public Cloning
getCloning() {
297 public void setCloning(Cloning cloning
) {
298 this.cloning
= cloning
;
302 // * The time for running the electrophoresis quality check.
303 // * Base unit is minutes [min].
305 // public Double getGelRunningTime() {
306 // return gelRunningTime;
310 // * @see #getGelRunningTime()
312 // public void setGelRunningTime(Double gelRunningTime) {
313 // this.gelRunningTime = gelRunningTime;
318 * The photo taken from the electrophoresis result showing the quality of the amplification.
319 * Gelphotos often do show multiple electrophoresis results. One may either cut or mark
320 * the part of the photo that displays <code>this</code> amplification. However, this may make
321 * the concrete media file unusable for other amplifications also represented by the same image.
322 * @see #getElectrophoresisVoltage()
323 * @see #getLadderUsed()
324 * @see #getGelConcentration()
325 * @see #getGelRunningTime()
327 public Media
getGelPhoto() {
333 * @param gelPhoto the gelPhoto to set
335 public void setGelPhoto(Media gelPhoto
) {
336 this.gelPhoto
= gelPhoto
;
340 // ********************** CLONE ***********************************/
342 * Clones <i>this</i> amplification. This is a shortcut that enables to create
343 * a new instance that differs only slightly from <i>this</i> amplification by
344 * modifying only some of the attributes.<BR><BR>
347 * @see EventBase#clone()
348 * @see java.lang.Object#clone()
351 public Object
clone() {
353 AmplificationResult result
= (AmplificationResult
)super.clone();
355 result
.singleReads
= new HashSet
<SingleRead
>();
356 for (SingleRead seq
: this.singleReads
){
357 result
.singleReads
.add(seq
);
361 //don't change dnaSample, marker, successful, successText, forwardPrimer,
362 //reversePrimer, purifiaction, cloning, ladderUsed, electrophoresisVoltage,
363 //gelRunningTime, gelPhoto, gelConcentration
365 }catch (CloneNotSupportedException e
) {
366 logger
.warn("Object does not implement cloneable");