Merge branch 'release/5.45.0'
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / name / HybridRelationship.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.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.hibernate.envers.Audited;
26
27 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
28 import eu.etaxonomy.cdm.model.common.RelationshipBase;
29 import eu.etaxonomy.cdm.model.reference.Reference;
30
31 /**
32 * The class representing a hybrid relationship between one of the {@link BotanicalName parents}
33 * of a hybrid taxon name and the hybrid taxon name itself. A hybrid taxon name
34 * is a {@link BotanicalName botanical taxon name} assigned to a hybrid plant following
35 * the {@link NomenclaturalCode#ICBN() ICBN} (Appendix I). A hybrid taxon name must have one
36 * of the hybrid flags set. The hybrid relationship includes a {@link HybridRelationshipType hybrid relationship type}
37 * (for instance "first parent" or "female parent") and the article of the ICBN
38 * on which the hybrid taxon name relies.
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 * @since 08-Nov-2007 13:06:26
47 */
48 @XmlAccessorType(XmlAccessType.FIELD)
49 @XmlType(name = "HybridRelationship", propOrder = {
50 "relatedFrom",
51 "relatedTo",
52 "type",
53 "ruleConsidered"
54 })
55 @Entity
56 @Audited
57 public class HybridRelationship
58 extends RelationshipBase<INonViralName, INonViralName, HybridRelationshipType>
59 implements Comparable<HybridRelationship>, IRuleConsidered{
60
61 private static final long serialVersionUID = -78515930138896939L;
62 private static final Logger logger = LogManager.getLogger();
63
64 // //The nomenclatural code rule considered. The article/note/recommendation in the code in question that is commented on in
65 // //the note property.
66 // @XmlElement(name = "RuleConsidered")
67 // private String ruleConsidered;
68
69 private RuleConsidered ruleConsidered;
70
71 @XmlElement(name = "RelatedFrom")
72 @XmlIDREF
73 @XmlSchemaType(name = "IDREF")
74 @ManyToOne(fetch=FetchType.LAZY)
75 // @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
76 private TaxonName relatedFrom;
77
78 @XmlElement(name = "RelatedTo")
79 @XmlIDREF
80 @XmlSchemaType(name = "IDREF")
81 @ManyToOne(fetch=FetchType.LAZY)
82 // @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
83 private TaxonName relatedTo;
84
85 @XmlElement(name = "Type")
86 @XmlIDREF
87 @XmlSchemaType(name = "IDREF")
88 @ManyToOne(fetch=FetchType.LAZY)
89 private HybridRelationshipType type;
90
91 /**
92 * @deprecated for hibernate use only, don't use
93 */
94 @Deprecated
95 private HybridRelationship(){
96 super();
97 }
98
99
100 // ************* CONSTRUCTORS *************/
101 /**
102 * Class constructor: creates a new hybrid relationship instance with no
103 * reference and adds it to the respective
104 * {@link BotanicalName#getHybridRelationships() botanical taxon name relation sets} of both involved names.
105 *
106 * @param toName the taxon name to be set as target for the new hybrid relationship
107 * @param fromName the taxon name to be set as source for the new hybrid relationship
108 * @param type the relationship type to be assigned to the new hybrid relationship
109 * @param ruleConsidered the string indicating the article of the ICBN for the hybrid taxon name
110 * @see #HybridRelationship(BotanicalName, BotanicalName, HybridRelationshipType, Reference, String, String)
111 * @see TaxonName#addHybridRelationship(HybridRelationship)
112 */
113 protected HybridRelationship(INonViralName hybridName, INonViralName parentName, HybridRelationshipType type, String ruleConsidered) {
114 this(hybridName, parentName, type, null, null, ruleConsidered, null);
115 }
116
117 /**
118 * Class constructor: creates a new hybrid relationship instance including
119 * its {@link eu.etaxonomy.cdm.model.reference.Reference reference source} and adds it to the respective
120 *{@link BotanicalName#getHybridRelationships() botanical taxon name relation sets} of both involved names.
121 *
122 * @param toName the taxon name to be set as target for the new hybrid relationship
123 * @param fromName the taxon name to be set as source for the new hybrid relationship
124 * @param type the relationship type to be assigned to the new hybrid relationship
125 * @param citation the reference source for the new hybrid relationship
126 * @param citationMicroReference the string with the details describing the exact localisation within the reference
127 * @param ruleConsidered the string indicating the article of the ICBN for the hybrid taxon name
128 * @see #HybridRelationship(BotanicalName, BotanicalName, HybridRelationshipType, String)
129 * @see TaxonName#addHybridRelationship(HybridRelationship)
130 */
131 protected HybridRelationship(INonViralName hybridName, INonViralName parentName, HybridRelationshipType type, Reference citation,
132 String citationMicroReference, String ruleConsidered, NomenclaturalCodeEdition codeEdition) {
133 super(parentName, hybridName, type, citation, citationMicroReference);
134 this.setRuleConsidered(ruleConsidered);
135 this.setCodeEdition(codeEdition);
136 }
137
138 //********* METHODS **************************************/
139
140 /**
141 * Returns the {@link BotanicalName botanical taxon name} that plays the parent role
142 * in <i>this</i> hybrid relationship.
143 *
144 * @see #getHybridName()
145 * @see eu.etaxonomy.cdm.model.common.RelationshipBase#getRelatedFrom()
146 */
147 @Transient
148 public TaxonName getParentName(){
149 return this.getRelatedFrom();
150 }
151 /**
152 * @see #getParentName()
153 */
154 public void setParentName(INonViralName parentName){
155 this.setRelatedFrom(parentName);
156 }
157
158 /**
159 * Returns the {@link BotanicalName botanical taxon name} that plays the child role
160 * (the child is actually the hybrid taxon name) in <i>this</i> hybrid relationship.
161 *
162 * @see #getParentName()
163 * @see eu.etaxonomy.cdm.model.common.RelationshipBase#getRelatedTo()
164 */
165 @Transient
166 public TaxonName getHybridName(){
167 return this.getRelatedTo();
168 }
169 /**
170 * @see #getHybridName()
171 */
172 public void setHybridName(INonViralName hybridName){
173 this.setRelatedTo(hybridName);
174 }
175
176 /**
177 * Returns the ICBN rule considered (that is the
178 * article/note/recommendation in the nomenclatural code) for building
179 * the string representing the (child) hybrid {@link BotanicalName taxon name}
180 * within <i>this</i> hybrid relationship.
181 */
182 @Override
183 public String getRuleConsidered(){
184 return this.ruleConsidered().getText();
185 }
186 /**
187 * @see #getRuleConsidered()
188 */
189 @Override
190 public void setRuleConsidered(String ruleConsidered){
191 this.ruleConsidered().setText(ruleConsidered);
192 }
193 /**
194 * The {@link NomenclaturalCodeEdition code edition} for the {@link #getRuleConsidered() rule considered}.
195 */
196 @Override
197 public NomenclaturalCodeEdition getCodeEdition() {
198 return ruleConsidered().getCodeEdition();
199 }
200 @Override
201 public void setCodeEdition(NomenclaturalCodeEdition codeEdition) {
202 ruleConsidered().setCodeEdition(codeEdition);
203 }
204 @Override
205 public IdentifiableSource getCodeEditionSource() {
206 NomenclaturalCodeEdition codeEdition = ruleConsidered().getCodeEdition();
207 return codeEdition == null ? null : codeEdition.getSource();
208 }
209 private RuleConsidered ruleConsidered(){
210 if(this.ruleConsidered==null){
211 ruleConsidered = new RuleConsidered();
212 }
213 return ruleConsidered;
214 }
215
216 @Override
217 protected TaxonName getRelatedFrom() {
218 return relatedFrom;
219 }
220
221 @Override
222 protected TaxonName getRelatedTo() {
223 return relatedTo;
224 }
225
226 @Override
227 public HybridRelationshipType getType() {
228 return type;
229 }
230
231 @Override
232 protected void setRelatedFrom(INonViralName relatedFrom) {
233 this.relatedFrom = TaxonName.castAndDeproxy(relatedFrom);
234 }
235
236 @Override
237 protected void setRelatedTo(INonViralName relatedTo) {
238 this.relatedTo = TaxonName.castAndDeproxy(relatedTo);
239 }
240
241 @Override
242 public void setType(HybridRelationshipType type) {
243 this.type = type;
244 }
245
246 // ************************ compareTo *************************************************
247
248 @Override
249 public int compareTo(HybridRelationship rel2) {
250 HybridRelationshipType type1 = this.getType();
251 HybridRelationshipType type2 = rel2.getType();
252 int compareType = type1.compareTo(type2);
253 if (compareType != 0){
254 return compareType;
255 }else{
256 TaxonName related1 = this.getRelatedFrom();
257 TaxonName related2 = rel2.getRelatedFrom();
258 if (related1 != related2){
259 related1 = this.getRelatedTo();
260 related2 = rel2.getRelatedTo();
261 }
262 if (related1.equals(related2)){
263 return 0;
264 }
265
266 String title1 = related1.getTitleCache();
267 String title2 = related2.getTitleCache();
268 return title1.compareTo(title2);
269 }
270 }
271
272 //*********************** CLONE ********************************************************/
273
274 /**
275 * Clones <i>this</i> hybrid relationship. This is a shortcut that enables to create
276 * a new instance that differs only slightly from <i>this</i> hybrid relationship by
277 * modifying only some of the attributes.<BR>
278 * CAUTION: Cloning a relationship will not add the relationship to the according
279 * {@link #relatedFrom} and {@link #relatedTo} objects. The method is meant to be used
280 * mainly for internal purposes (e.g. used within {@link TaxonName#clone()}
281 *
282 * @see eu.etaxonomy.cdm.model.common.RelationshipBase#clone()
283 * @see java.lang.Object#clone()
284 */
285 @Override
286 public HybridRelationship clone() {
287 HybridRelationship result;
288 try {
289 result = (HybridRelationship)super.clone();
290 result.ruleConsidered = this.ruleConsidered == null? null : this.ruleConsidered.clone();
291 //no changes to: relatedFrom, relatedTo, type
292 return result;
293 } catch (CloneNotSupportedException e) {
294 logger.warn("Object does not implement cloneable");
295 e.printStackTrace();
296 return null;
297 }
298 }
299 }