improve to better fulfill the Comparator contract
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / NameRelationship.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
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.
8 */
9
10 package eu.etaxonomy.cdm.model.name;
11
12 import javax.persistence.Entity;
13 import javax.persistence.FetchType;
14 import javax.persistence.ManyToOne;
15 import javax.persistence.Transient;
16 import javax.xml.bind.annotation.XmlAccessType;
17 import javax.xml.bind.annotation.XmlAccessorType;
18 import javax.xml.bind.annotation.XmlElement;
19 import javax.xml.bind.annotation.XmlIDREF;
20 import javax.xml.bind.annotation.XmlSchemaType;
21 import javax.xml.bind.annotation.XmlType;
22
23 import org.apache.log4j.Logger;
24 import org.hibernate.annotations.Cascade;
25 import org.hibernate.annotations.CascadeType;
26 import org.hibernate.envers.Audited;
27
28 import eu.etaxonomy.cdm.model.common.RelationshipBase;
29 import eu.etaxonomy.cdm.model.reference.Reference;
30 import eu.etaxonomy.cdm.validation.Level3;
31 import eu.etaxonomy.cdm.validation.annotation.NamesWithHomotypicRelationshipsMustBelongToSameGroup;
32
33 /**
34 * The class representing a relationship between two {@link TaxonNameBase taxon names} according
35 * to the {@link NomenclaturalCode nomenclatural code} which governs both of them.
36 * This includes a {@link NameRelationshipType name relationship type} (for instance "later homonym" or
37 * "orthographic variant") and the article of the corresponding nomenclatural
38 * code on which the assignation of the relationship type is based.
39 * <P>
40 * This class corresponds partially to: <ul>
41 * <li> Relationship according to the TDWG ontology
42 * <li> TaxonRelationship according to the TCS
43 * </ul>
44 *
45 * @author m.doering
46 * @version 1.0
47 * @created 08-Nov-2007 13:06:37
48 */
49 @XmlAccessorType(XmlAccessType.FIELD)
50 @XmlType(name = "NameRelationship", propOrder = {
51 "relatedFrom",
52 "relatedTo",
53 "type",
54 "ruleConsidered"
55 })
56 @Entity
57 @Audited
58 @NamesWithHomotypicRelationshipsMustBelongToSameGroup(groups = {Level3.class})
59 public class NameRelationship extends RelationshipBase<TaxonNameBase, TaxonNameBase, NameRelationshipType> implements Cloneable{
60 private static final long serialVersionUID = -615987333520172043L;
61 private static final Logger logger = Logger.getLogger(NameRelationship.class);
62
63 //The nomenclatural code rule considered. The article/note/recommendation in the code in question that is commented on in
64 //the note property.
65 @XmlElement(name = "RuleConsidered")
66 private String ruleConsidered;
67
68 @XmlElement(name = "RelatedFrom")
69 @XmlIDREF
70 @XmlSchemaType(name = "IDREF")
71 @ManyToOne(fetch=FetchType.LAZY)
72 @Cascade({CascadeType.SAVE_UPDATE})
73 private TaxonNameBase relatedFrom;
74
75 @XmlElement(name = "RelatedTo")
76 @XmlIDREF
77 @XmlSchemaType(name = "IDREF")
78 @ManyToOne(fetch=FetchType.LAZY)
79 @Cascade(CascadeType.SAVE_UPDATE)
80 private TaxonNameBase relatedTo;
81
82 @XmlElement(name = "Type")
83 @XmlIDREF
84 @XmlSchemaType(name = "IDREF")
85 @ManyToOne(fetch = FetchType.LAZY)
86 private NameRelationshipType type;
87
88 /**
89 * @deprecated for hibernate use only, don't use
90 */
91 @Deprecated
92 private NameRelationship(){
93 super();
94 }
95
96
97 // ************* CONSTRUCTORS *************/
98 /**
99 * Class constructor: creates a new name relationship instance with no
100 * reference and adds it to the respective
101 * {@link TaxonNameBase#getNameRelations() taxon name relation sets} of both involved names.
102 *
103 * @param toName the taxon name to be set as target for the new name relationship
104 * @param fromName the taxon name to be set as source for the new name relationship
105 * @param type the relationship type to be assigned to the new name relationship
106 * @param ruleConsidered the string indicating the article of the nomenclatural code for the new name relationship
107 * @see #NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, Reference, String, String)
108 * @see TaxonNameBase#addNameRelationship(NameRelationship)
109 * @see TaxonNameBase#addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
110 * @see TaxonNameBase#addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
111 */
112 protected NameRelationship(TaxonNameBase toName, TaxonNameBase fromName, NameRelationshipType type, String ruleConsidered) {
113 this(toName, fromName, type, null, null, ruleConsidered);
114 }
115
116 /**
117 * Class constructor: creates a new name relationship instance including
118 * its {@link eu.etaxonomy.cdm.model.reference.Reference reference source} and adds it to the respective
119 *{@link TaxonNameBase#getNameRelations() taxon name relation sets} of both involved names.
120 *
121 * @param toName the taxon name to be set as target for the new name relationship
122 * @param fromName the taxon name to be set as source for the new name relationship
123 * @param type the relationship type to be assigned to the new name relationship
124 * @param citation the reference source for the new name relationship
125 * @param citationMicroReference the string with the details describing the exact localisation within the reference
126 * @param ruleConsidered the string indicating the article of the nomenclatural code justifying the new name relationship
127 * @see #NameRelationship(TaxonNameBase, TaxonNameBase, NameRelationshipType, String)
128 * @see TaxonNameBase#addNameRelationship(NameRelationship)
129 * @see TaxonNameBase#addRelationshipFromName(TaxonNameBase, NameRelationshipType, String)
130 * @see TaxonNameBase#addRelationshipToName(TaxonNameBase, NameRelationshipType, String)
131 */
132 protected NameRelationship(TaxonNameBase toName, TaxonNameBase fromName, NameRelationshipType type, Reference citation, String citationMicroReference, String ruleConsidered) {
133 super(fromName, toName, type, citation, citationMicroReference);
134 this.setRuleConsidered(ruleConsidered);
135 }
136
137 //********* METHODS **************************************/
138
139 /**
140 * Returns the {@link TaxonNameBase taxon name} that plays the source role
141 * in <i>this</i> taxon name relationship.
142 *
143 * @see #getToName()
144 * @see eu.etaxonomy.cdm.model.common.RelationshipBase#getRelatedFrom()
145 */
146 @Transient
147 public TaxonNameBase getFromName(){
148 return this.getRelatedFrom();
149 }
150
151 /**
152 * @see #getFromName()
153 */
154 void setFromName(TaxonNameBase fromName){
155 this.setRelatedFrom(fromName);
156 }
157
158 /**
159 * Returns the {@link TaxonNameBase taxon name} that plays the target role
160 * in <i>this</i> taxon name relationship.
161 *
162 * @see #getFromName()
163 * @see eu.etaxonomy.cdm.model.common.RelationshipBase#getRelatedTo()
164 */
165 @Transient
166 public TaxonNameBase getToName(){
167 return this.getRelatedTo();
168 }
169
170 /**
171 * @see #getToName()
172 */
173 void setToName(TaxonNameBase toName){
174 this.setRelatedTo(toName);
175 }
176
177 /**
178 * Returns the nomenclatural code rule considered (that is the
179 * article/note/recommendation in the nomenclatural code ruling
180 * the taxon name(s) of this nomenclatural status).
181 * The considered rule gives the reason why the
182 * {@link NomenclaturalStatusType nomenclatural status type} has been
183 * assigned to the {@link TaxonNameBase taxon name(s)}.
184 */
185 public String getRuleConsidered(){
186 return this.ruleConsidered;
187 }
188
189 /**
190 * @see #getRuleConsidered()
191 */
192 public void setRuleConsidered(String ruleConsidered){
193 this.ruleConsidered = ruleConsidered;
194 }
195
196 // for extra-package access to relatedFrom use getFromName instead
197 protected TaxonNameBase getRelatedFrom() {
198 return relatedFrom;
199 }
200
201 // for extra-package access to relatedFrom use getToName instead
202 protected TaxonNameBase getRelatedTo() {
203 return relatedTo;
204 }
205
206 public NameRelationshipType getType() {
207 return type;
208 }
209
210 protected void setRelatedFrom(TaxonNameBase relatedFrom) {
211 if (relatedFrom == null){
212 this.deletedObjects.add(this.relatedFrom);
213 }
214 this.relatedFrom = relatedFrom;
215 }
216
217 protected void setRelatedTo(TaxonNameBase relatedTo) {
218 if (relatedTo == null){
219 this.deletedObjects.add(this.relatedTo);
220 }
221 this.relatedTo = relatedTo;
222 }
223
224 public void setType(NameRelationshipType type) {
225 this.type = type;
226 }
227
228
229 //*********************** CLONE ********************************************************/
230
231 /**
232 * Clones <i>this</i> name relationship. This is a shortcut that enables to create
233 * a new instance that differs only slightly from <i>this</i> name relationship by
234 * modifying only some of the attributes.<BR>
235 * CAUTION: Cloning a relationship will not add the relationship to the according
236 * {@link #relatedFrom} and {@link #relatedTo} objects. The method is meant to be used
237 * mainly for internal purposes (e.g. used within {@link TaxonNameBase#clone()}
238 *
239 * @see eu.etaxonomy.cdm.model.common.RelationshipBase#clone()
240 * @see java.lang.Object#clone()
241 */
242 @Override
243 public Object clone() {
244 NameRelationship result;
245 try {
246 result = (NameRelationship)super.clone();
247 //no changes to: relatedFrom, relatedTo, type
248 return result;
249 } catch (CloneNotSupportedException e) {
250 logger.warn("Object does not implement cloneable");
251 e.printStackTrace();
252 return null;
253 }
254 }
255 }