Project

General

Profile

Download (12.1 KB) Statistics
| Branch: | Tag: | Revision:
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.Column;
19
import javax.persistence.Entity;
20
import javax.persistence.FetchType;
21
import javax.persistence.ManyToMany;
22
import javax.persistence.ManyToOne;
23
import javax.persistence.MapKeyJoinColumn;
24
import javax.persistence.OneToMany;
25
import javax.xml.bind.annotation.XmlAccessType;
26
import javax.xml.bind.annotation.XmlAccessorType;
27
import javax.xml.bind.annotation.XmlElement;
28
import javax.xml.bind.annotation.XmlElementWrapper;
29
import javax.xml.bind.annotation.XmlIDREF;
30
import javax.xml.bind.annotation.XmlRootElement;
31
import javax.xml.bind.annotation.XmlSchemaType;
32
import javax.xml.bind.annotation.XmlType;
33
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
34

    
35
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
36
import org.hibernate.annotations.Cascade;
37
import org.hibernate.annotations.CascadeType;
38
import org.hibernate.envers.Audited;
39
import org.hibernate.search.annotations.Field;
40
import org.hibernate.search.annotations.FieldBridge;
41
import org.hibernate.search.annotations.IndexedEmbedded;
42

    
43
import eu.etaxonomy.cdm.hibernate.search.MultilanguageTextFieldBridge;
44
import eu.etaxonomy.cdm.jaxb.MultilanguageTextAdapter;
45
import eu.etaxonomy.cdm.model.common.IMultiLanguageTextHolder;
46
import eu.etaxonomy.cdm.model.common.Language;
47
import eu.etaxonomy.cdm.model.common.LanguageString;
48
import eu.etaxonomy.cdm.model.common.MultilanguageText;
49
import eu.etaxonomy.cdm.model.common.VersionableEntity;
50
import eu.etaxonomy.cdm.model.term.DefinedTerm;
51
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
52
import eu.etaxonomy.cdm.model.term.TermVocabulary;
53

    
54
/**
55
 * This class represents the assignment of values ({@link State state terms}) to {@link Feature features}
56
 * corresponding to {@link CategoricalData categorical data}. A state data instance
57
 * constitutes an atomized part of an information piece (categorical data) so
58
 * that several state data instances may belong to one categorical data
59
 * instance.
60
 * <P>
61
 * This class corresponds to CharacterStateDataType according to the SDD schema.
62
 *
63
 * @author m.doering
64
 * @since 08-Nov-2007 13:06:53
65
 */
66
@XmlAccessorType(XmlAccessType.FIELD)
67
@XmlType(name = "StateData", propOrder = {
68
    "categoricalData",
69
    "state",
70
    "count",
71
    "modifiers",
72
    "modifyingText"
73
})
74
@XmlRootElement(name = "StateData")
75
@Entity
76
@Audited
77
public class StateData
78
        extends VersionableEntity
79
        implements IModifiable, IMultiLanguageTextHolder{
80

    
81
    private static final long serialVersionUID = -4380314126624505415L;
82
    private static final Logger logger = LogManager.getLogger(StateData.class);
83

    
84
    @XmlElement(name = "CategoricalData")
85
    @XmlIDREF
86
    @XmlSchemaType(name = "IDREF")
87
    @ManyToOne(fetch = FetchType.LAZY)
88
    @IndexedEmbedded(depth=1)
89
    private CategoricalData categoricalData;
90

    
91
    @XmlElement(name = "State")
92
    @XmlIDREF
93
    @XmlSchemaType(name = "IDREF")
94
    @ManyToOne(fetch = FetchType.LAZY)
95
    @IndexedEmbedded(depth=1)
96
    private State state;
97

    
98
    //#8625 for statistically counting aggregated state data
99
    @Column(name="number")  //rename to avoid conflicts with SQL syntax
100
    private Integer count;
101

    
102
    @XmlElementWrapper(name = "Modifiers")
103
    @XmlElement(name = "Modifier")
104
    @ManyToMany(fetch = FetchType.LAZY)
105
//    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})   remove cascade #5755
106
    @IndexedEmbedded(depth=1)
107
//	@NotNull // avoids creating a UNIQUE key for this field -> not needed for ManyToMany
108
    private Set<DefinedTerm> modifiers = new HashSet<>();
109

    
110
    @XmlElement(name = "ModifyingText")
111
    @XmlJavaTypeAdapter(MultilanguageTextAdapter.class)
112
    @OneToMany(fetch = FetchType.LAZY)
113
    @MapKeyJoinColumn(name="modifyingtext_mapkey_id")
114
    @Cascade({CascadeType.SAVE_UPDATE, CascadeType.MERGE})
115
    @Field(name="modifyingText")
116
    @FieldBridge(impl=MultilanguageTextFieldBridge.class)
117
    private Map<Language,LanguageString> modifyingText = new HashMap<>();
118

    
119
//********************* FACTORY METHODS ************************\
120

    
121
    /**
122
     * Creates a new empty state data instance.
123
     */
124
    public static StateData NewInstance(){
125
        return new StateData();
126
    }
127

    
128
    /**
129
     * Creates a new empty state data instance.
130
     *
131
     * <b>NOTE:</b> {@link State}  is a sub class of {@link DefinedTermBase}.
132
     * If the state passed as parameter has been created newly it <b>has to be persisted before</b> it is possible to save the StateData.
133
     */
134
    public static StateData NewInstance(State state){
135
        StateData stateData = new StateData();
136
        stateData.setState(state);
137
        return stateData;
138
    }
139

    
140
//*************************** CONSTRUCTOR ************************\
141

    
142
    /**
143
     * Class constructor: creates a new empty state data instance.
144
     */
145
    public StateData() {
146
        super();
147
    }
148

    
149
//************************** GETTER /SETTER *************************\
150

    
151
    /**
152
     * Returns the {@link State state term} used in <i>this</i> state data.
153
     */
154
    public State getState(){
155
        return this.state;
156
    }
157
    /**
158
     * @see	#getState()
159
     */
160
    public void setState(State state){
161
        this.state = state;
162
    }
163

    
164
    /**
165
     * Returns the number of single data using this state if <B>this</B>
166
     * StateData was created by aggregation.
167
     */
168
    public Integer getCount() {
169
        return count;
170
    }
171
    /**
172
     * @see #getCount()
173
     */
174
    public void setCount(Integer count) {
175
        this.count = count;
176
    }
177
    /**
178
     * Increments the count by 1.
179
     * @see #getCount()
180
     */
181
    public void incrementCount(){
182
        if(count==null){
183
            count = 0;
184
        }
185
        count++;
186
    }
187

    
188
    /**
189
     * Returns the {@link CategoricalData state term} <i>this</i> state data
190
     * belongs to.
191
     */
192
    public CategoricalData getCategoricalData(){
193
        return this.categoricalData;
194
    }
195
    //for bidirectional use only
196
    @Deprecated
197
    protected void setCategoricalData(CategoricalData categoricalData) {
198
        this.categoricalData = categoricalData;
199
    }
200

    
201
    /**
202
     * Returns the set of {@link Modifier modifiers} used to qualify the validity
203
     * of <i>this</i> state data. This is only metainformation.
204
     */
205
    @Override
206
    public Set<DefinedTerm> getModifiers(){
207
        return this.modifiers;
208
    }
209

    
210
    /**
211
     * Adds a {@link Modifier modifier} to the set of {@link #getModifiers() modifiers}
212
     * used to qualify the validity of <i>this</i> state data.
213
     *
214
     * @param modifier	the modifier to be added to <i>this</i> state data
215
     * @see    	   		#getModifiers()
216
     */
217
    @Override
218
    public void addModifier(DefinedTerm modifier){
219
        this.modifiers.add(modifier);
220
    }
221
    /**
222
     * Removes one element from the set of {@link #getModifiers() modifiers}
223
     * used to qualify the validity of <i>this</i> state data.
224
     *
225
     * @param  modifier	the modifier which should be removed
226
     * @see     		#getModifiers()
227
     * @see     		#addModifier(Modifier)
228
     */
229
    @Override
230
    public void removeModifier(DefinedTerm modifier){
231
        this.modifiers.remove(modifier);
232
    }
233

    
234
    /**
235
     * Returns the {@link MultilanguageText multilanguage text} used to qualify the validity
236
     * of <i>this</i> state data.  The different {@link LanguageString language strings}
237
     * contained in the multilanguage text should all have the same meaning.<BR>
238
     * A multilanguage text does not belong to a controlled {@link TermVocabulary term vocabulary}
239
     * as a {@link Modifier modifier} does.
240
     * <P>
241
     * NOTE: the actual content of <i>this</i> state data is NOT
242
     * stored in the modifying text. This is only metainformation
243
     * (like "Some experts express doubt about this assertion").
244
     */
245
    public Map<Language,LanguageString> getModifyingText(){
246
        return this.modifyingText;
247
    }
248

    
249
    /**
250
     * Creates a {@link LanguageString language string} based on the given text string
251
     * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
252
     * used to qualify the validity of <i>this</i> state data.
253
     *
254
     *
255
     * @param text		the string describing the validity
256
     * 					in a particular language
257
     * @param language	the language in which the text string is formulated
258
     *
259
     * @see    	   		#getModifyingText()
260
     * @see    	   		#putModifyingText(LanguageString)
261
     * @deprecated 		should follow the put semantic of maps, this method will be removed in v4.0
262
     * 					Use the {@link #putModifyingText(Language, String) putModifyingText} method instead
263
     */
264
    @Deprecated
265
    public LanguageString addModifyingText(String text, Language language){
266
        return this.putModifyingText(language, text);
267
    }
268

    
269
    /**
270
     * Creates a {@link LanguageString language string} based on the given text string
271
     * and the given {@link Language language} and adds it to the {@link MultilanguageText multilanguage text}
272
     * used to qualify the validity of <i>this</i> state data.
273
     *
274
     * @param language	the language in which the text string is formulated
275
     * @param text		the string describing the validity
276
     * 					in a particular language
277
     *
278
     * @see    	   		#getModifyingText()
279
     * @see    	   		#addModifyingText(LanguageString)
280
     */
281
    public LanguageString putModifyingText(Language language, String text){
282
        return this.modifyingText.put(language, LanguageString.NewInstance(text, language));
283
    }
284

    
285
    /**
286
     * Adds a translated {@link LanguageString text in a particular language}
287
     * to the {@link MultilanguageText multilanguage text} used to qualify the validity
288
     * of <i>this</i> state data.
289
     *
290
     * @param text	the language string describing the validity
291
     * 				in a particular language
292
     * @see    	   	#getModifyingText()
293
     * @see    	   	#putModifyingText(Language, String)
294
     */
295
    public LanguageString putModifyingText(LanguageString text){
296
        return this.modifyingText.put(text.getLanguage(),text);
297
    }
298
    /**
299
     * Removes from the {@link MultilanguageText multilanguage text} used to qualify the validity
300
     * of <i>this</i> state data the one {@link LanguageString language string}
301
     * with the given {@link Language language}.
302
     *
303
     * @param  lang	the language in which the language string to be removed
304
     * 				has been formulated
305
     * @see     	#getModifyingText()
306
     */
307
    public LanguageString removeModifyingText(Language lang){
308
        return this.modifyingText.remove(lang);
309
    }
310

    
311
//*********************************** TO STRING *****************************************/
312

    
313

    
314
    @Override
315
    public String toString() {
316
        return "[" + state
317
                + (modifiers.isEmpty() ? "" : ", modifiers=" + modifiers)
318
                + (modifyingText.isEmpty() ? "" : ", modifyingText=" + modifyingText)
319
                + (count==null?"": "("+count+")")
320
                + "]";
321
    }
322

    
323
//*********************************** CLONE *****************************************/
324

    
325
    /**
326
     * Clones <i>this</i> state data. This is a shortcut that enables to create
327
     * a new instance that differs only slightly from <i>this</i> state data by
328
     * modifying only some of the attributes.
329
     *
330
     * @see eu.etaxonomy.cdm.model.common.VersionableEntity#clone()
331
     * @see java.lang.Object#clone()
332
     */
333
    @Override
334
    public StateData clone() {
335

    
336
        try {
337
            StateData result = (StateData)super.clone();
338

    
339
            //modifiers
340
            result.modifiers = new HashSet<>();
341
            for (DefinedTerm modifier : getModifiers()){
342
                result.modifiers.add(modifier);
343
            }
344

    
345
            //modifying text
346
            result.modifyingText = cloneLanguageString(this.modifyingText);
347

    
348
            return result;
349
            //no changes to: state
350
        } catch (CloneNotSupportedException e) {
351
            logger.warn("Object does not implement cloneable");
352
            e.printStackTrace();
353
            return null;
354
        }
355
    }
356
}
(28-28/38)