Merge branch 'release/5.45.0'
[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.xml.bind.annotation.XmlAccessType;
16 import javax.xml.bind.annotation.XmlAccessorType;
17 import javax.xml.bind.annotation.XmlElement;
18 import javax.xml.bind.annotation.XmlIDREF;
19 import javax.xml.bind.annotation.XmlSchemaType;
20 import javax.xml.bind.annotation.XmlType;
21
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.log4j.Logger;
24 import org.hibernate.envers.Audited;
25
26 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
27 import eu.etaxonomy.cdm.model.common.RelationshipBase;
28 import eu.etaxonomy.cdm.model.reference.NamedSource;
29 import eu.etaxonomy.cdm.model.reference.Reference;
30 import eu.etaxonomy.cdm.validation.Level3;
31 import eu.etaxonomy.cdm.validation.annotation.BasionymsMustShareEpithetsAndAuthors;
32 import eu.etaxonomy.cdm.validation.annotation.NamesWithHomotypicRelationshipsMustBelongToSameGroup;
33
34 /**
35 * The class representing a relationship between two {@link TaxonName taxon names} according
36 * to the {@link NomenclaturalCode nomenclatural code} which governs both of them.
37 * This includes a {@link NameRelationshipType name relationship type} (for instance "later homonym" or
38 * "orthographic variant") and the article of the corresponding nomenclatural
39 * code on which the assignation of the relationship type is based.
40 * <P>
41 * This class corresponds partially to: <ul>
42 * <li> Relationship according to the TDWG ontology
43 * <li> TaxonRelationship according to the TCS
44 * </ul>
45 *
46 * @author m.doering
47 * @since 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 @BasionymsMustShareEpithetsAndAuthors(groups = Level3.class)
60 public class NameRelationship
61 extends RelationshipBase<TaxonName, TaxonName, NameRelationshipType>
62 implements IRuleConsidered{
63
64 private static final long serialVersionUID = -615987333520172043L;
65 private static final Logger logger = LogManager.getLogger();
66
67 // //The nomenclatural code rule considered. The article/note/recommendation in the code in question that is commented on in
68 // //the note property.
69 // @XmlElement(name = "RuleConsidered")
70 // private String ruleConsidered;
71
72 private RuleConsidered ruleConsidered;
73
74 @XmlElement(name = "RelatedFrom")
75 @XmlIDREF
76 @XmlSchemaType(name = "IDREF")
77 @ManyToOne(fetch=FetchType.LAZY)
78 // @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
79 private TaxonName relatedFrom;
80
81 @XmlElement(name = "RelatedTo")
82 @XmlIDREF
83 @XmlSchemaType(name = "IDREF")
84 @ManyToOne(fetch=FetchType.LAZY)
85 // @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE})
86 private TaxonName relatedTo;
87
88 @XmlElement(name = "Type")
89 @XmlIDREF
90 @XmlSchemaType(name = "IDREF")
91 @ManyToOne(fetch = FetchType.LAZY)
92 private NameRelationshipType type;
93
94 /**
95 * @deprecated for hibernate use only, don't use
96 */
97 @Deprecated
98 private NameRelationship(){
99 super();
100 }
101
102
103 // ************* CONSTRUCTORS *************/
104 /**
105 * Class constructor: creates a new name relationship instance with no
106 * reference and adds it to the respective
107 * {@link TaxonName#getNameRelations() taxon name relation sets} of both involved names.
108 *
109 * @param toName the taxon name to be set as target for the new name relationship
110 * @param fromName the taxon name to be set as source for the new name relationship
111 * @param type the relationship type to be assigned to the new name relationship
112 * @param ruleConsidered the string indicating the article of the nomenclatural code for the new name relationship
113 * @param codeEdition the edition of the nomenclatural code where the <code>ruleConsidered</code> has been published.
114 * @see #NameRelationship(TaxonName, TaxonName, NameRelationshipType, Reference, String, String)
115 * @see TaxonName#addNameRelationship(NameRelationship)
116 * @see TaxonName#addRelationshipFromName(TaxonName, NameRelationshipType, String)
117 * @see TaxonName#addRelationshipToName(TaxonName, NameRelationshipType, String)
118 */
119 protected NameRelationship(TaxonName toName, TaxonName fromName, NameRelationshipType type, String ruleConsidered, NomenclaturalCodeEdition codeEdition) {
120 this(toName, fromName, type, null, null, ruleConsidered, codeEdition);
121 }
122
123 /**
124 * Class constructor: creates a new name relationship instance including
125 * its {@link eu.etaxonomy.cdm.model.reference.Reference reference source} and adds it to the respective
126 *{@link TaxonName#getNameRelations() taxon name relation sets} of both involved names.
127 *
128 * @param toName the taxon name to be set as target for the new name relationship
129 * @param fromName the taxon name to be set as source for the new name relationship
130 * @param type the relationship type to be assigned to the new name relationship
131 * @param citation the reference source for the new name relationship
132 * @param citationMicroReference the string with the details describing the exact localisation within the reference
133 * @param ruleConsidered the string indicating the article of the nomenclatural code justifying the new name relationship
134 * @param codeEdition the edition of the nomenclatural code where the <code>ruleConsidered</code> has been published.
135 * @see #NameRelationship(TaxonName, TaxonName, NameRelationshipType, String)
136 * @see TaxonName#addNameRelationship(NameRelationship)
137 * @see TaxonName#addRelationshipFromName(TaxonName, NameRelationshipType, String)
138 * @see TaxonName#addRelationshipToName(TaxonName, NameRelationshipType, String)
139 */
140 protected NameRelationship(TaxonName toName, TaxonName fromName, NameRelationshipType type, Reference citation, String citationMicroReference, String ruleConsidered, NomenclaturalCodeEdition codeEdition) {
141 super(fromName, toName, type, citation, citationMicroReference);
142 this.setRuleConsidered(ruleConsidered);
143 this.setCodeEdition(codeEdition);
144 }
145
146 /**
147 * Class constructor: creates a new name relationship instance including
148 * its {@link eu.etaxonomy.cdm.model.description.DescriptionElementSource reference source} and adds it to the respective
149 *{@link TaxonName#getNameRelations() taxon name relation sets} of both involved names.
150 *
151 * @param toName the taxon name to be set as target for the new name relationship
152 * @param fromName the taxon name to be set as source for the new name relationship
153 * @param type the relationship type to be assigned to the new name relationship
154 * @param source the source for the new name relationship
155 * @param ruleConsidered the string indicating the article of the nomenclatural code justifying the new name relationship
156 * @param codeEdition the edition of the nomenclatural code where the <code>ruleConsidered</code> has been published.
157 * @see #NameRelationship(TaxonName, TaxonName, NameRelationshipType, String)
158 * @see TaxonName#addNameRelationship(NameRelationship)
159 * @see TaxonName#addRelationshipFromName(TaxonName, NameRelationshipType, String)
160 * @see TaxonName#addRelationshipToName(TaxonName, NameRelationshipType, String)
161 */
162 protected NameRelationship(TaxonName toName, TaxonName fromName, NameRelationshipType type, NamedSource source, String ruleConsidered, NomenclaturalCodeEdition codeEdition) {
163 super(fromName, toName, type, source);
164 this.setRuleConsidered(ruleConsidered);
165 this.setCodeEdition(codeEdition);
166 }
167
168
169 //********* METHODS **************************************/
170
171 /**
172 * Returns the {@link TaxonName taxon name} that plays the source role
173 * in <i>this</i> taxon name relationship.
174 *
175 * @see #getToName()
176 * @see eu.etaxonomy.cdm.model.common.RelationshipBase#getRelatedFrom()
177 */
178 public TaxonName getFromName(){
179 return this.getRelatedFrom();
180 }
181
182 /**
183 * @see #getFromName()
184 */
185 void setFromName(TaxonName fromName){
186 this.setRelatedFrom(fromName);
187 }
188
189 /**
190 * Returns the {@link TaxonName taxon name} that plays the target role
191 * in <i>this</i> taxon name relationship.
192 *
193 * @see #getFromName()
194 * @see eu.etaxonomy.cdm.model.common.RelationshipBase#getRelatedTo()
195 */
196 public TaxonName getToName(){
197 return this.getRelatedTo();
198 }
199
200 /**
201 * @see #getToName()
202 */
203 void setToName(TaxonName toName){
204 this.setRelatedTo(toName);
205 }
206
207 // *********** RULE CONSIDERED **********************/
208
209 /**
210 * Returns the nomenclatural code rule considered (that is the
211 * article/note/recommendation in the nomenclatural code ruling
212 * the taxon name(s) of this nomenclatural status).
213 * The considered rule gives the reason why the
214 * {@link NameRelationshipType name relationship type} has been
215 * assigned to this name relation.
216 */
217 @Override
218 public String getRuleConsidered(){
219 return this.ruleConsidered().getText();
220 }
221 /**
222 * @see #getRuleConsidered()
223 */
224 @Override
225 public void setRuleConsidered(String ruleConsidered){
226 this.ruleConsidered().setText(ruleConsidered);
227 }
228 /**
229 * The {@link NomenclaturalCodeEdition code edition} for the {@link #getRuleConsidered() rule considered}.
230 */
231 @Override
232 public NomenclaturalCodeEdition getCodeEdition() {
233 return ruleConsidered().getCodeEdition();
234 }
235 @Override
236 public void setCodeEdition(NomenclaturalCodeEdition codeEdition) {
237 ruleConsidered().setCodeEdition(codeEdition);
238 }
239 @Override
240 public IdentifiableSource getCodeEditionSource() {
241 NomenclaturalCodeEdition codeEdition = ruleConsidered().getCodeEdition();
242 return codeEdition == null ? null : codeEdition.getSource();
243 }
244 private RuleConsidered ruleConsidered(){
245 if(this.ruleConsidered==null){
246 ruleConsidered = new RuleConsidered();
247 }
248 return ruleConsidered;
249 }
250
251 // for extra-package access to relatedFrom use getFromName instead
252 @Override
253 protected TaxonName getRelatedFrom() {
254 return relatedFrom;
255 }
256
257 // for extra-package access to relatedFrom use getToName instead
258 @Override
259 protected TaxonName getRelatedTo() {
260 return relatedTo;
261 }
262
263 @Override
264 public NameRelationshipType getType() {
265 return type;
266 }
267
268 @Override
269 protected void setRelatedFrom(TaxonName relatedFrom) {
270 this.relatedFrom = relatedFrom;
271 }
272
273 @Override
274 protected void setRelatedTo(TaxonName relatedTo) {
275 this.relatedTo = relatedTo;
276 }
277
278 @Override
279 public void setType(NameRelationshipType type) {
280 this.type = type;
281 }
282
283
284 //*********************** CLONE ********************************************************/
285
286 /**
287 * Clones <i>this</i> name relationship. This is a shortcut that enables to create
288 * a new instance that differs only slightly from <i>this</i> name relationship by
289 * modifying only some of the attributes.<BR>
290 * CAUTION: Cloning a relationship will not add the relationship to the according
291 * {@link #relatedFrom} and {@link #relatedTo} objects. The method is meant to be used
292 * mainly for internal purposes (e.g. used within {@link TaxonName#clone()}
293 *
294 * @see eu.etaxonomy.cdm.model.common.RelationshipBase#clone()
295 * @see java.lang.Object#clone()
296 */
297 @Override
298 public NameRelationship clone() {
299 NameRelationship result;
300 try {
301 result = (NameRelationship)super.clone();
302 result.ruleConsidered = this.ruleConsidered == null? null : this.ruleConsidered.clone();
303 //no changes to: relatedFrom, relatedTo, type
304 return result;
305 } catch (CloneNotSupportedException e) {
306 logger.warn("Object does not implement cloneable");
307 e.printStackTrace();
308 return null;
309 }
310 }
311 }