Project

General

Profile

Download (9.91 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
import java.util.ArrayList;
13
import java.util.Arrays;
14
import java.util.List;
15

    
16
import javax.persistence.Entity;
17
import javax.persistence.FetchType;
18
import javax.persistence.OneToMany;
19
import javax.persistence.Transient;
20
import javax.validation.constraints.NotEmpty;
21
import javax.xml.bind.annotation.XmlAccessType;
22
import javax.xml.bind.annotation.XmlAccessorType;
23
import javax.xml.bind.annotation.XmlElement;
24
import javax.xml.bind.annotation.XmlElementWrapper;
25
import javax.xml.bind.annotation.XmlRootElement;
26
import javax.xml.bind.annotation.XmlTransient;
27
import javax.xml.bind.annotation.XmlType;
28

    
29
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
30
import org.hibernate.annotations.Cascade;
31
import org.hibernate.annotations.CascadeType;
32
import org.hibernate.envers.Audited;
33
import org.hibernate.search.annotations.Indexed;
34
import org.hibernate.search.annotations.IndexedEmbedded;
35

    
36
import eu.etaxonomy.cdm.validation.Level2;
37

    
38
/**
39
 * This class represents information pieces expressed in categorical type of
40
 * data (in opposition to {@link QuantitativeData quantitative data} on one side and to literal data on
41
 * the other side). Only {@link TaxonDescription taxon descriptions} and
42
 * {@link SpecimenDescription specimen descriptions} may contain categorical data.<BR>
43
 * The "color of petals" {@link Feature feature} for instance can be described with
44
 * {@link State state terms} such as "blue" or "white". If the color of petals of a
45
 * particular tree is described as "mostly blue" and "exceptionally white" two
46
 * {@link StateData state data} instances must be assigned to an instance of the
47
 * present class: the first one with the state "blue" and the {@link Modifier modifier}
48
 * "mostly" and the second one with the state "white" and the modifier "exceptionally".
49
 * Whenever more than one state data belongs to a categorical data they should be
50
 * interpreted as being related by the inclusive disjunction "or".
51
 * <P>
52
 * This class corresponds partially to CodedDescriptionType according to
53
 * the SDD schema.
54
 *
55
 * @author m.doering
56
 * @since 08-Nov-2007 13:06:15
57
 */
58
@XmlAccessorType(XmlAccessType.FIELD)
59
@XmlType(name = "CategoricalData", propOrder = {
60
    "orderRelevant",
61
    "stateData",
62
    "unknownData"
63
})
64
@XmlRootElement(name = "CategoricalData")
65
@Entity
66
@Audited
67
@Indexed(index = "eu.etaxonomy.cdm.model.description.DescriptionElementBase")
68
public class CategoricalData extends DescriptionElementBase {
69

    
70
    private static final long serialVersionUID = -6298361966947668998L;
71
    private static final Logger logger = LogManager.getLogger(CategoricalData.class);
72

    
73
    //whether the sequence of ordered states is important
74
    @XmlElement(name = "OrderRelevant")
75
    private boolean orderRelevant;
76

    
77
    @XmlElementWrapper(name = "States")
78
    @XmlElement(name = "State")
79
    @OneToMany(fetch = FetchType.LAZY, mappedBy="categoricalData", orphanRemoval=true)
80
    @Cascade({ CascadeType.SAVE_UPDATE, CascadeType.MERGE, CascadeType.DELETE})
81
    @IndexedEmbedded(depth = 3)
82
    @NotEmpty(groups = Level2.class)
83
    private List<StateData> stateData = new ArrayList<>();
84

    
85
    @XmlElement(name = "UnknownData")
86
    private final Boolean unknownData = false;
87

    
88
//****************************** FACTORY METHOD *******************************/
89

    
90
    /**
91
     * Creates a new empty categorical data instance.
92
     */
93
    public static CategoricalData NewInstance(){
94
        return new CategoricalData();
95
    }
96

    
97

    
98
    /**
99
     * @param habitat
100
     * @return
101
     */
102
    public static CategoricalData NewInstance(Feature feature) {
103
        return new CategoricalData( new ArrayList<>() , feature);
104
    }
105

    
106
    /**
107
     * Creates a new empty categorical data instance.
108
     */
109
    public static CategoricalData NewInstance(State state, Feature feature){
110
        return new CategoricalData( Arrays.asList( new State[]{state}) , feature);
111
    }
112

    
113
//*******************  CONSTRUCTOR *********************************************/
114

    
115
    /**
116
     * Class constructor: creates a new empty categorical data instance.
117
     */
118
    protected CategoricalData() {
119
        super(null);
120
    }
121

    
122
    /**
123
     * Class constructor: creates a new empty categorical data instance.
124
     */
125
    protected CategoricalData(List<State> states, Feature feature) {
126
        super(feature);
127
        for (State state : states){
128
            addStateData(state);
129
        }
130

    
131
    }
132

    
133
// ****************** GETTER / SETTER *********************************************/
134

    
135
    /**
136
     * Returns the (ordered) list of {@link State states} describing the {@link Feature feature}
137
     * corresponding to <i>this</i> categorical data.
138
     */
139

    
140
    public List<StateData> getStateData(){
141
        return this.stateData;
142
    }
143

    
144
    @Deprecated
145
    protected void setStateData(List<StateData> stateData){
146
        this.stateData = stateData;
147
    }
148

    
149
    /**
150
     * Adds a {@link State state} to the list of {@link #getStateData() states}
151
     * describing the {@link Feature feature} corresponding to <i>this</i> categorical data.
152
     *
153
     * @param state	the state to be added to <i>this</i> categorical data
154
     * @see    	   	#getStateData()
155
     */
156
    @SuppressWarnings("deprecation")
157
    public void addStateData(StateData stateData){
158
        this.stateData.add(stateData);
159
        stateData.setCategoricalData(this);
160
    }
161

    
162
    /**
163
     * Convenience method which creates a state data from a given state with no modifiers
164
     * and adds it to the list of state data
165
     * @see #addStateData(StateData)
166
     * @param state
167
     */
168
    public StateData addStateData(State state){
169
        StateData stateData = StateData.NewInstance(state);
170
        addStateData(stateData);
171
        return stateData;
172
    }
173

    
174

    
175
    /**
176
     * Removes one element from the set of {@link #getStateData() states}
177
     * describing the {@link Feature feature} corresponding to <i>this</i> categorical data.
178
     *
179
     * @param  state	the state which should be removed
180
     * @see     		#getStateData()
181
     * @see     		#addStateData(State)
182
     */
183
    @SuppressWarnings("deprecation")
184
    public void removeStateData(StateData stateData){
185
        this.stateData.remove(stateData);
186
        stateData.setCategoricalData(null);
187
    }
188

    
189
    //rename to isStateSequenceIntentional ??
190
    /**
191
     * Returns the boolean value of the flag indicating whether the sequence of
192
     * {@link StateData state data} belonging to <i>this</i> categorical data is intentional
193
     * (true) and therefore relevant for interpretation or analysis or not (false).
194
     * The use of this flag depends mostly on the {@link Feature feature} of <i>this</i> categorical data.
195
     *
196
     * @return  the boolean value of the orderRelevant flag
197
     */
198
    public boolean getOrderRelevant(){
199
        return this.orderRelevant;
200
    }
201
    /**
202
     * @see	#getOrderRelevant()
203
     */
204
    public void setOrderRelevant(boolean orderRelevant){
205
        this.orderRelevant = orderRelevant;
206
    }
207

    
208
// ********************* CONVENIENCE ******************************************/
209

    
210
    /**
211
     * Convenience method to test the existence of a given state in the state data.
212
     * Note: the method ignores modifiers so state data having the state may still be
213
     * modified by its modifiers.
214
     *
215
     * @param state the given {@link State}
216
     * @return <code>true</code> if the state exists
217
     */
218
    public boolean hasState(State state) {
219
        return getStatesOnly().contains(state);
220
    }
221

    
222
    /**
223
     * Convenience method returning only the list of states. Leaving out modifiers and modifying text.
224
     */
225
    @Transient
226
    public List<State> getStatesOnly(){
227
        List<State> result = new ArrayList<>();
228
        for (StateData stateData : getStateData()){
229
            State state = stateData.getState();
230
            if (state != null){
231
                result.add(state);
232
            }
233
        }
234
        return result;
235
    }
236

    
237
    /**
238
     * Convenience method which to set the list of states (no modifiers or modifying text allowed).
239
     * All existing state data are removed.
240
     * @return
241
     */
242
    public List<StateData> setStateDataOnly(List<State> states){
243
        List<StateData> stateDataList = new ArrayList<>(getStateData());
244
        for (StateData stateData : stateDataList) {
245
            removeStateData(stateData);
246
        }
247
        for (State state : states) {
248
            addStateData(state);
249
        }
250
        return this.stateData;
251
    }
252

    
253
    @Transient
254
    @XmlTransient
255
    @Override
256
    public boolean isCharacterData() {
257
        return true;
258
    }
259

    
260
//********************************** toString **************************************/
261

    
262
    @Override
263
    public String toString() {
264
        return (getFeature()!=null ? getFeature().getLabel(): "") +
265
                "[" + stateData +
266
                    (orderRelevant? ", orderRelevant=" + orderRelevant:"") +
267
                    (unknownData? ", unknownData=" + unknownData:"")
268
                + "]";
269
    }
270

    
271

    
272
//*********************************** CLONE *****************************************/
273

    
274
    /**
275
     * Clones <i>this</i> categorical data. This is a shortcut that enables to create
276
     * a new instance that differs only slightly from <i>this</i> categorical data by
277
     * modifying only some of the attributes.
278
     * @throws CloneNotSupportedException
279
     *
280
     * @see eu.etaxonomy.cdm.model.description.DescriptionElementBase#clone()
281
     * @see java.lang.Object#clone()
282
     */
283
    @Override
284
    public CategoricalData clone() {
285

    
286
        CategoricalData result = (CategoricalData)super.clone();
287

    
288
        //states
289
        result.stateData = new ArrayList<>();
290
        for (StateData stateData : getStateData()){
291
            StateData newState = stateData.clone();
292
            result.addStateData(newState);
293
        }
294

    
295
        //no changes to: orderRelevant
296
        return result;
297
    }
298
}
(1-1/38)