Merge branch 'release/5.45.0'
[cdmlib.git] / cdmlib-model / src / main / java / eu / etaxonomy / cdm / model / description / KeyStatement.java
1 /**
2 *
3 */
4 package eu.etaxonomy.cdm.model.description;
5
6 import java.util.Arrays;
7 import java.util.HashMap;
8 import java.util.List;
9 import java.util.Map;
10
11 import javax.persistence.Entity;
12 import javax.persistence.FetchType;
13 import javax.persistence.MapKeyJoinColumn;
14 import javax.persistence.OneToMany;
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.XmlRootElement;
19 import javax.xml.bind.annotation.XmlType;
20 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
21
22 import org.apache.logging.log4j.LogManager;
23 import org.apache.logging.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.jaxb.MultilanguageTextAdapter;
29 import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
30 import eu.etaxonomy.cdm.model.common.Language;
31 import eu.etaxonomy.cdm.model.common.LanguageString;
32 import eu.etaxonomy.cdm.model.common.MultilanguageTextHelper;
33 import eu.etaxonomy.cdm.model.common.VersionableEntity;
34 import eu.etaxonomy.cdm.model.term.TermBase;
35
36 /**
37 * This class represents a statement or a question within a (polytomous) key.
38 * Compare with SDD SimpleRepresentation.
39 *
40 * @author a.mueller
41 *
42 */
43 @XmlAccessorType(XmlAccessType.FIELD)
44 @XmlType(name = "KeyStatement", propOrder = {
45 "label"
46 // ,"mediaObject"
47 })
48 @XmlRootElement(name = "KeyStatement")
49 @Entity
50 @Audited
51 public class KeyStatement extends VersionableEntity implements IMultiLanguageTextHolder{
52
53 private static final long serialVersionUID = 3771323100914695139L;
54 private static final Logger logger = LogManager.getLogger();
55
56
57 @XmlElement(name = "MultiLanguageText")
58 @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
59 @OneToMany (fetch= FetchType.LAZY, orphanRemoval=true)
60 @MapKeyJoinColumn(name="label_mapkey_id")
61 @Cascade({CascadeType.SAVE_UPDATE,CascadeType.MERGE, CascadeType.DELETE })
62 // @IndexedEmbedded
63 private Map<Language, LanguageString> label = new HashMap<>();
64
65 //private mediaObjects needs to be discussed (how to implement the role of the media)
66
67 public static KeyStatement NewInstance(){
68 KeyStatement result = new KeyStatement();
69 return result;
70 }
71
72 public static KeyStatement NewInstance(String defaultLanguageLabel){
73 KeyStatement result = new KeyStatement();
74 result.putLabel(Language.DEFAULT(), defaultLanguageLabel);
75 return result;
76 }
77
78 /**
79 * Factory method for a key statement.
80 * @param language the language of the first representation of the statement. Must not be <code>null</code>.
81 * @param label the text of statement in the given language.
82 * @return
83 */
84 public static KeyStatement NewInstance(Language language, String label){
85 assert language != null : "Language for KeyStatement must not be null";
86 KeyStatement result = new KeyStatement();
87 result.putLabel(language, label);
88 return result;
89 }
90
91 //*************************** CONSTRUCTOR ***********************************/
92
93 public KeyStatement() {
94 }
95
96 // ********************************* METHODS ***************************/
97
98 /**
99 * Returns the label with the content of <i>this</i> key statement.
100 * The different {@link LanguageString language strings} (texts) contained in the
101 * label should all have the same meaning.
102 *
103 * @see #getText(Language)
104 */
105 public Map<Language, LanguageString> getLabel() {
106 return label;
107 }
108
109 /**
110 * Returns the label with the content of <i>this</i> key statement for
111 * a specific language.
112 *
113 * @param language the language in which the label is formulated
114 * @return
115 */
116 public LanguageString getLabel(Language language){
117 return label.get(language);
118 }
119
120 public void setLabel(Map<Language,LanguageString> label) {
121 this.label = label;
122 }
123
124 /**
125 * Returns the text string in the given {@link Language language} with the content
126 * of <i>this</i> key statement.
127 *
128 * @param language the language in which the label is formulated
129 * @see #getLabel(Language)
130 */
131 public String getLabelText(Language language) {
132 LanguageString languageString = label.get(language);
133 if (languageString == null){
134 return null;
135 }else{
136 return languageString.getText();
137 }
138 }
139
140 /**
141 * Returns the LanguageString in the preferred language. Preferred languages
142 * are specified by the parameter languages, which receives a list of
143 * Language instances in the order of preference. If no representation in
144 * any preferred languages is found the method falls back to return the
145 * Representation in Language.DEFAULT() and if necessary further falls back
146 * to return the first element found if any.
147 *
148 * TODO think about this fall-back strategy &
149 * see also {@link TermBase#getPreferredRepresentation(List)}
150 *
151 * @param languages
152 * @return
153 */
154 public LanguageString getPreferredLanguageString(List<Language> languages) {
155 return MultilanguageTextHelper.getPreferredLanguageString(label, languages);
156 }
157
158 /**
159 * @see #getPreferredLanguageString(List)
160 */
161 public LanguageString getPreferredLanguageString(Language language) {
162 return MultilanguageTextHelper.getPreferredLanguageString(label, Arrays.asList(language));
163 }
164
165 /**
166 * Creates a {@link LanguageString language string} based on the given text string
167 * and the given {@link Language language}, returns it and adds it to the multilanguage
168 * text representing the content of <i>this</i> text data.
169 *
170 * @param language the language in which the text string is formulated
171 * @param text the string representing the content of the text data
172 * in a particular language
173 *
174 * @return the language string
175 * @see #getLabel()
176 * @see #putLabel(LanguageString)
177 *
178 */
179 public LanguageString putLabel(Language language, String label) {
180 LanguageString result = this.label.put(language , LanguageString.NewInstance(label, language));
181 return (result == null ? null : result);
182 }
183 /**
184 * Adds a translated {@link LanguageString text in a particular language}
185 * to the label.
186 * The given language string will be returned.
187 *
188 * @param languageString the language string representing the content of
189 * the text data in a particular language
190 * @return the language string
191 * @see #getLabel()
192 * @see #putLabel(String, Language)
193 */
194 public LanguageString putLabel(LanguageString languageString) {
195 if (languageString == null){
196 return null;
197 }else{
198 Language language = languageString.getLanguage();
199 return this.label.put(language, languageString);
200 }
201 }
202
203 /**
204 * Removes from label the one {@link LanguageString language string}
205 * with the given {@link Language language}. Returns the removed
206 * language string.
207 *
208 * @param language the language in which the language string to be removed
209 * has been formulated
210 * @return the language string associated with the given language
211 * @see #getLabelText()
212 */
213 public LanguageString removeLabel(Language language) {
214 return this.label.remove(language);
215 }
216
217
218 /**
219 * Returns the number of {@link Language languages} in which the label
220 * of <i>this</i> key statement has been formulated.
221 *
222 * @see #getMultilanguageText()
223 */
224 public int countLanguages(){
225 return label.size();
226 }
227
228 //*********************** CLONE ********************************************************/
229
230 /**
231 * Clones <i>this</i> KeyStatement. This is a shortcut that enables to create
232 * a new instance that differs only slightly from <i>this</i> KeyStatement by
233 * modifying only some of the attributes.
234 *
235 * @see eu.etaxonomy.cdm.model.common.VersionableEntitity#clone()
236 * @see java.lang.Object#clone()
237 */
238 @Override
239 public KeyStatement clone() {
240
241 KeyStatement result;
242 try {
243 result = (KeyStatement) super.clone();
244
245 result.label = cloneLanguageString(this.label);
246
247 return result;
248 }catch (CloneNotSupportedException e) {
249 logger.warn("Object does not implement cloneable");
250 e.printStackTrace();
251 return null;
252 }
253 }
254
255 //********************* toString() *************************************/
256
257 @Override
258 public String toString(){
259 if (label != null && ! label.isEmpty()){
260 String result = label.values().iterator().next().getText();
261 return result;
262 }else{
263 return super.toString();
264 }
265 }
266 }