Added clone() to all TaxonNameBase classes (including some descriptive and common...
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / description / StateData.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.description;
11
12
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.Map;
16 import java.util.Set;
17
18 import javax.persistence.Entity;
19 import javax.persistence.FetchType;
20 import javax.persistence.ManyToMany;
21 import javax.persistence.ManyToOne;
22 import javax.persistence.OneToMany;
23 import javax.validation.constraints.NotNull;
24 import javax.xml.bind.annotation.XmlAccessType;
25 import javax.xml.bind.annotation.XmlAccessorType;
26 import javax.xml.bind.annotation.XmlElement;
27 import javax.xml.bind.annotation.XmlElementWrapper;
28 import javax.xml.bind.annotation.XmlIDREF;
29 import javax.xml.bind.annotation.XmlRootElement;
30 import javax.xml.bind.annotation.XmlSchemaType;
31 import javax.xml.bind.annotation.XmlType;
32 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
33
34 import org.apache.log4j.Logger;
35 import org.hibernate.annotations.Cascade;
36 import org.hibernate.annotations.CascadeType;
37 import org.hibernate.envers.Audited;
38
39 import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
40 import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
41 import eu.etaxonomy.cdm.model.common.Language;
42 import eu.etaxonomy.cdm.model.common.LanguageString;
43 import eu.etaxonomy.cdm.model.common.MultilanguageText;
44 import eu.etaxonomy.cdm.model.common.TermVocabulary;
45 import eu.etaxonomy.cdm.model.common.VersionableEntity;
46
47 /**
48 * This class represents the assignment of values ({@link State state terms}) to {@link Feature features}
49 * corresponding to {@link CategoricalData categorical data}. A state data instance
50 * constitutes an atomized part of an information piece (categorical data) so
51 * that several state data instances may belong to one categorical data
52 * instance.
53 * <P>
54 * This class corresponds to CharacterStateDataType according to the SDD schema.
55 *
56 * @author m.doering
57 * @version 1.0
58 * @created 08-Nov-2007 13:06:53
59 */
60 @XmlAccessorType(XmlAccessType.FIELD)
61 @XmlType(name = "StateData", propOrder = {
62 "state",
63 "modifiers",
64 "modifyingText"
65 })
66 @XmlRootElement(name = "StateData")
67 @Entity
68 @Audited
69 public class StateData extends VersionableEntity implements IModifiable, IMultiLanguageTextHolder, Cloneable{
70 private static final long serialVersionUID = -4380314126624505415L;
71 @SuppressWarnings("unused")
72 private static final Logger logger = Logger.getLogger(StateData.class);
73
74 @XmlElement(name = "State")
75 @XmlIDREF
76 @XmlSchemaType(name = "IDREF")
77 @ManyToOne(fetch = FetchType.LAZY)
78 private State state;
79
80 @XmlElementWrapper(name = "Modifiers")
81 @XmlElement(name = "Modifier")
82 @ManyToMany(fetch = FetchType.LAZY)
83 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
84 @NotNull // avoids creating a UNIQUE key for this field
85 private Set<Modifier> modifiers = new HashSet<Modifier>();
86
87 @XmlElement(name = "ModifyingText")
88 @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
89 @OneToMany(fetch = FetchType.LAZY)
90 private Map<Language,LanguageString> modifyingText = new HashMap<Language,LanguageString>();
91
92 /**
93 * Class constructor: creates a new empty state data instance.
94 */
95 public StateData() {
96 super();
97 }
98
99 /**
100 * Creates a new empty state data instance.
101 */
102 public static StateData NewInstance(){
103 return new StateData();
104 }
105
106 /**
107 * Returns the {@link State state term} used in <i>this</i> state data.
108 */
109 public State getState(){
110 return this.state;
111 }
112 /**
113 * @see #getState()
114 */
115 public void setState(State state){
116 this.state = state;
117 }
118
119
120 /**
121 * Returns the set of {@link Modifier modifiers} used to qualify the validity
122 * of <i>this</i> state data. This is only metainformation.
123 */
124 public Set<Modifier> getModifiers(){
125 return this.modifiers;
126 }
127
128 /**
129 * Adds a {@link Modifier modifier} to the set of {@link #getModifiers() modifiers}
130 * used to qualify the validity of <i>this</i> state data.
131 *
132 * @param modifier the modifier to be added to <i>this</i> state data
133 * @see #getModifiers()
134 */
135 public void addModifier(Modifier modifier){
136 this.modifiers.add(modifier);
137 }
138 /**
139 * Removes one element from the set of {@link #getModifiers() modifiers}
140 * used to qualify the validity of <i>this</i> state data.
141 *
142 * @param modifier the modifier which should be removed
143 * @see #getModifiers()
144 * @see #addModifier(Modifier)
145 */
146 public void removeModifier(Modifier modifier){
147 this.modifiers.remove(modifier);
148 }
149
150
151 /**
152 * Returns the {@link MultilanguageText multilanguage text} used to qualify the validity
153 * of <i>this</i> state data. The different {@link LanguageString language strings}
154 * contained in the multilanguage text should all have the same meaning.<BR>
155 * A multilanguage text does not belong to a controlled {@link TermVocabulary term vocabulary}
156 * as a {@link Modifier modifier} does.
157 * <P>
158 * NOTE: the actual content of <i>this</i> state data is NOT
159 * stored in the modifying text. This is only metainformation
160 * (like "Some experts express doubt about this assertion").
161 */
162 public Map<Language,LanguageString> getModifyingText(){
163 return this.modifyingText;
164 }
165
166 /**
167 * Creates a {@link LanguageString language string} based on the given text string
168 * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
169 * used to qualify the validity of <i>this</i> state data.
170 *
171 * @param text the string describing the validity
172 * in a particular language
173 * @param language the language in which the text string is formulated
174 * @see #getModifyingText()
175 * @see #addModifyingText(LanguageString)
176 */
177 public LanguageString addModifyingText(String text, Language language){
178 return this.modifyingText.put(language, LanguageString.NewInstance(text, language));
179 }
180 /**
181 * Adds a translated {@link LanguageString text in a particular language}
182 * to the {@link MultilanguageText multilanguage text} used to qualify the validity
183 * of <i>this</i> state data.
184 *
185 * @param text the language string describing the validity
186 * in a particular language
187 * @see #getModifyingText()
188 * @see #addModifyingText(String, Language)
189 */
190 public LanguageString addModifyingText(LanguageString text){
191 return this.modifyingText.put(text.getLanguage(),text);
192 }
193 /**
194 * Removes from the {@link MultilanguageText multilanguage text} used to qualify the validity
195 * of <i>this</i> state data the one {@link LanguageString language string}
196 * with the given {@link Language language}.
197 *
198 * @param lang the language in which the language string to be removed
199 * has been formulated
200 * @see #getModifyingText()
201 */
202 public LanguageString removeModifyingText(Language lang){
203 return this.modifyingText.remove(lang);
204 }
205
206 //*********************************** CLONE *****************************************/
207
208 /**
209 * Clones <i>this</i> state data. This is a shortcut that enables to create
210 * a new instance that differs only slightly from <i>this</i> state data by
211 * modifying only some of the attributes.
212 *
213 * @see eu.etaxonomy.cdm.model.common.VersionableEntity#clone()
214 * @see java.lang.Object#clone()
215 */
216 @Override
217 public Object clone() {
218
219 try {
220 StateData result = (StateData)super.clone();
221
222 //modifiers
223 result.modifiers = new HashSet<Modifier>();
224 for (Modifier modifier : getModifiers()){
225 result.modifiers.add(modifier);
226 }
227
228 //modifying text
229 result.modifyingText = new HashMap<Language, LanguageString>();
230 for (Language language : getModifyingText().keySet()){
231 //TODO clone needed? See also IndividualsAssociation
232 LanguageString newLanguageString = (LanguageString)getModifyingText().get(language).clone();
233 result.modifyingText.put(language, newLanguageString);
234 }
235
236 return result;
237 //no changes to: state
238 } catch (CloneNotSupportedException e) {
239 logger.warn("Object does not implement cloneable");
240 e.printStackTrace();
241 return null;
242 }
243 }
244 }