Project

General

Profile

Download (27.7 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.text.ParseException;
13
import java.util.Arrays;
14
import java.util.HashMap;
15
import java.util.HashSet;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19
import java.util.UUID;
20

    
21
import javax.persistence.Entity;
22
import javax.persistence.Transient;
23
import javax.xml.bind.annotation.XmlAccessType;
24
import javax.xml.bind.annotation.XmlAccessorType;
25
import javax.xml.bind.annotation.XmlAttribute;
26
import javax.xml.bind.annotation.XmlRootElement;
27
import javax.xml.bind.annotation.XmlType;
28

    
29
import org.apache.commons.lang3.StringUtils;
30
import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
31
import org.hibernate.envers.Audited;
32

    
33
import eu.etaxonomy.cdm.common.CdmUtils;
34
import eu.etaxonomy.cdm.model.common.Language;
35
import eu.etaxonomy.cdm.model.location.NamedArea;
36
import eu.etaxonomy.cdm.model.taxon.Taxon;
37
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
38
import eu.etaxonomy.cdm.model.term.OrderedTermBase;
39
import eu.etaxonomy.cdm.model.term.TermType;
40
import eu.etaxonomy.cdm.model.term.TermVocabulary;
41

    
42

    
43
/**
44
 * This class represents terms describing the {@link AbsenceTerm absence}
45
 * (like "extinct") or the {@link PresenceTerm presence} (like "cultivated") of a
46
 * {@link Taxon taxon} in an {@link NamedArea area}. These terms are only
47
 * used for {@link Distribution distributions}.
48
 *
49
 * The current implementation includes multiple qualities of distribution status:<BR><BR>
50
 *
51
 *  1. Degree of "presence": present, presence questionable, reported in error, absent, ...<BR>
52
 *  2. Nativeness/naturalization/...: native, alien (introduced), naturalized, cultivated, invasive, ... <BR>
53
 *  <BR>
54
 *  There might be further qualities like adventive(unwanted)<->introduced(wanted - for cultivation)
55
 * <BR>
56
 * For an interesting discussion of these status see Pyšek & al.: Alien plants in checklists and floras;
57
 * Taxon 53(1), Feb. 2004: 131-143 <BR>
58
 *
59
 * Pyšek et al. distinguises<BR>
60
 *  native - alien<BR>
61
 *  alien => cultivated-outside cultivation<BR>
62
 *  outside cultivation=>casual - naturalized<BR>
63
 *  naturalized => non invasive - invasive<BR>
64
 *  invasive => not harmful - transformers - weeds
65
 *
66
 * @see https://dev.e-taxonomy.eu/redmine/issues/6000
67
 *
68
 * @author m.doering
69
 * @since 08-Nov-2007 13:06:44
70
 * @author a.mueller
71
 */
72
@XmlAccessorType(XmlAccessType.FIELD)
73
@XmlType(name = "PresenceAbsenceTerm")
74
@XmlRootElement(name = "PresenceAbsenceTerm")
75
@Entity
76
//@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
77
//@Indexed(index = "eu.etaxonomy.cdm.model.term.DefinedTermBase")
78
@Audited
79
public class PresenceAbsenceTerm extends OrderedTermBase<PresenceAbsenceTerm> {
80

    
81
    private static final long serialVersionUID = 1036807546935584396L;
82
	private static final Logger logger = LogManager.getLogger(PresenceAbsenceTerm.class);
83

    
84
	//presence base
85
	public static final UUID uuidPresent = UUID.fromString("cef81d25-501c-48d8-bbea-542ec50de2c2");
86
	private static final UUID uuidPresentDoubfully = UUID.fromString("75a60279-a4c2-4f53-bc57-466028a4b3db");
87

    
88
	//presence
89
	public static final UUID uuidNative = UUID.fromString("ddeac4f2-d8fa-43b8-ad7e-ca13abdd32c7");
90
	private static final UUID uuidNativeDoubtfullyNative = UUID.fromString("310373bf-7df4-4d02-8cb3-bcc7448805fc");
91
	public static final UUID uuidCultivated = UUID.fromString("9eb99fe6-59e2-4445-8e6a-478365bd0fa9");
92
	public static final UUID uuidIntroduced = UUID.fromString("643cf9d1-a5f1-4622-9837-82ef961e880b");
93
	private static final UUID uuidIntroducedDoubtfullyIntroduced = UUID.fromString("0c54761e-4887-4788-9dfa-7190c88746e3");
94
	public static final UUID uuidIntroducedUncertainDegreeNaturalisation = UUID.fromString("da159544-b0dd-4599-a9c9-640826af8c17");
95
	public static final UUID uuidIntroducedAdventitious = UUID.fromString("42946bd6-9c22-45ad-a910-7427e8f60bfd");
96
	public static final UUID uuidNaturalised = UUID.fromString("e191e89a-a751-4b0c-b883-7f1de70915c9");
97
	private static final UUID uuidIntroducedCultiated = UUID.fromString("fac8c347-8262-44a1-b0a4-db4de451c021");
98
	private static final UUID uuidEndemic = UUID.fromString("c3ee7048-15b7-4be1-b687-9ce9c1a669d6");
99

    
100
	private static final UUID uuidNotEndemic = UUID.fromString("2fda5393-7423-4076-814c-1fa7678d7d33");
101
	private static final UUID uuidUnknownEndemism = UUID.fromString("094aa2e4-8048-4086-aca1-2d671a05a86e");
102

    
103
	//	private static final UUID uuidNa=UUID.fromString("4e04990a-66fe-4fdf-856c-f40772fbcf0a");
104
	//invasive
105
	private static final UUID uuidInvasive = UUID.fromString("dc536e3d-a753-4bbe-a386-dd8aff35c234");
106
	private static final UUID uuidNonInvasive = UUID.fromString("1b025e8b-901a-42e8-9739-119b410c6f03");
107

    
108
	//presents questionable
109
	public static final UUID uuidNativePresenceQuestionable = UUID.fromString("925662c1-bb10-459a-8c53-da5a738ac770");
110
	private static final UUID uuidCultivatedPresenceQuestionable = UUID.fromString("4f31bfc8-3058-4d83-aea5-3a1fe9773f9f");
111
	private static final UUID uuidIntroducedPresenceQuestionable = UUID.fromString("83eb0aa0-1a45-495a-a3ca-bf6958b74366");
112
	private static final UUID uuidEndedmicPresenceQuestionable = UUID.fromString("5f954f08-267a-4928-b073-12328f74c187");
113
	//intr. naturalized questionable
114
	private static final UUID uuidNaturalisedPresenceQuestionable = UUID.fromString("9e0b413b-5a68-4e5b-91f2-227b4f832466");
115
	//natur. invasive questionable
116
	private static final UUID uuidInvasivePresenceQuestionable = UUID.fromString("ac429d5f-e8ad-49ae-a41c-e4779b58b96a");
117
	//natur. non-invasive questionable
118
    private static final UUID uuidNonInvasivePresenceQuestionable = UUID.fromString("11f56e2f-c16c-4b3d-a870-bb5d3b20e624");
119

    
120
	//absence
121
	private static final UUID uuidAbsence=UUID.fromString("59709861-f7d9-41f9-bb21-92559cedd598");
122
	private static final UUID uuidReportedInError = UUID.fromString("38604788-cf05-4607-b155-86db456f7680");
123

    
124
	public static final UUID uuidNativeError = UUID.fromString("61cee840-801e-41d8-bead-015ad866c2f1");
125
	private static final UUID uuidIntroducedReportedError = UUID.fromString("aeec2947-2700-4623-8e32-9e3a430569d1");
126
	private static final UUID uuidCultivatedReportedError = UUID.fromString("9d4d3431-177a-4abe-8e4b-1558573169d6");
127
	private static final UUID uuidNativeFormerlyNative = UUID.fromString("5c397f7b-59ef-4c11-a33c-45691ceda91b");
128
	private static final UUID uuidNativeDoubtfullyNativeReportedError = UUID.fromString("71b72e24-c2b6-44a5-bdab-39f083bf0f06");
129
	private static final UUID uuidIntroducedFormerlyIntroduced = UUID.fromString("b74dc30b-ee93-496d-8c00-4d00abae1ec7");
130
	private static final UUID uuidEndemicReportedError = UUID.fromString("679b215d-c231-4ee2-ae12-3ffc3dd528ad");
131
	private static final UUID uuidNaturalisedReportedError = UUID.fromString("8d918a37-3add-4e1c-a233-c37dbee209aa");
132
	private static final UUID uuidCasualPresenceQuestionable = UUID.fromString("73f75493-1185-4a3e-af1e-9a1f2e8dadb7");
133
	private static final UUID uuidCasualReportedError = UUID.fromString("9b910b7b-43e3-4260-961c-6063b11cb7dc");
134

    
135
	//undefined
136
	public static final UUID uuidUndefined = UUID.fromString("bdb46487-01f8-451d-bf7b-d3e0fd44938e");
137

    
138

    
139
	protected static Map<UUID, PresenceAbsenceTerm> termMap = null;
140

    
141
    private String defaultColor = "000000";
142

    
143
    @XmlAttribute(name = "absenceTerm")
144
    private boolean absenceTerm = false;
145

    
146
	//********* METHODS **************************************/
147
	/**
148
	 * Creates a new empty presence term.
149
	 *
150
	 * @see #NewInstance(String, String, String)
151
	 */
152
	public static PresenceAbsenceTerm NewInstance(){
153
		return new PresenceAbsenceTerm();
154
	}
155

    
156
	/**
157
	 * Creates a new presence term with a description (in the {@link Language#DEFAULT() default language}),
158
	 * a label and a label abbreviation.
159
	 *
160
	 * @param	term  		 the string (in the default language) describing the
161
	 * 						 new presence term to be created
162
	 * @param	label  		 the string identifying the new presence term to be created
163
	 * @param	labelAbbrev  the string identifying (in abbreviated form) the
164
	 * 						 new presence term to be created
165
	 * @see 				 #NewInstance()
166
	 */
167
	public static PresenceAbsenceTerm NewPresenceInstance(String term, String label, String labelAbbrev){
168
		return new PresenceAbsenceTerm(term, label, labelAbbrev, false);
169
	}
170

    
171
	/**
172
	 * Creates a new absence term with a description (in the {@link Language#DEFAULT() default language}),
173
	 * a label and a label abbreviation.
174
	 *
175
	 * @param	term  		 the string (in the default language) describing the
176
	 * 						 new presence term to be created
177
	 * @param	label  		 the string identifying the new presence term to be created
178
	 * @param	labelAbbrev  the string identifying (in abbreviated form) the
179
	 * 						 new presence term to be created
180
	 * @see 				 #NewInstance()
181
	 */
182
	public static PresenceAbsenceTerm NewAbsenceInstance(String term, String label, String labelAbbrev){
183
		return new PresenceAbsenceTerm(term, label, labelAbbrev, true);
184
	}
185

    
186

    
187
//********************************** Constructor *******************************************************************/
188

    
189
  	//for hibernate use only
190
  	@Deprecated
191
  	protected PresenceAbsenceTerm() {
192
    	super(TermType.PresenceAbsenceTerm);
193
    }
194

    
195
    /**
196
     * Class constructor: creates a new presence or absence term with a description
197
     * (in the {@link Language#DEFAULT() default language}), a label and a label abbreviation.
198
     *
199
     * @param	term  		 the string (in the default language) describing the
200
     * 						 new presence or absence term to be created
201
     * @param	label  		 the string identifying the new presence or absence term to be created
202
     * @param	labelAbbrev  the string identifying (in abbreviated form) the
203
     * 						 new presence or absence term to be created
204
     * @param   isAbsenceTerm  boolean value indicating if this term represents an absence or not
205
     * @see 				 #PresenceAbsenceTermBase()
206
     */
207
    protected PresenceAbsenceTerm(String term, String label, String labelAbbrev, boolean isAbsenceTerm) {
208
        super(TermType.PresenceAbsenceTerm, term, label, labelAbbrev);
209
        this.setAbsenceTerm(isAbsenceTerm);
210
    }
211

    
212

    
213
  //******************************* STATIC METHODS *****************************************
214

    
215
  	protected static PresenceAbsenceTerm getTermByUuid(UUID uuid){
216
        if (termMap == null || termMap.isEmpty()){
217
            return getTermByClassAndUUID(PresenceAbsenceTerm.class, uuid);
218
        } else {
219
  			return termMap.get(uuid);
220
  		}
221
  	}
222

    
223
   	//TODO read from label(abbrevs) like in TDWGArea
224
  	public static PresenceAbsenceTerm getPresenceAbsenceTermByAbbreviation(String abbrev) {
225
  		if (abbrev == null) { throw new NullPointerException("abbrev is 'null' in getPresenceTermByAbbreviation");
226
  		} else if (abbrev.equalsIgnoreCase("c"))  { return PresenceAbsenceTerm.CULTIVATED();
227
  		} else if (abbrev.equalsIgnoreCase("e"))  { return PresenceAbsenceTerm.ENDEMIC_FOR_THE_RELEVANT_AREA();
228
  		} else if (abbrev.equalsIgnoreCase("i"))  { return PresenceAbsenceTerm.INTRODUCED();
229
  		} else if (abbrev.equalsIgnoreCase("ia")) { return PresenceAbsenceTerm.CASUAL();
230
  		} else if (abbrev.equalsIgnoreCase("ic")) { return PresenceAbsenceTerm.INTRODUCED_CULTIVATED();
231
  		} else if (abbrev.equalsIgnoreCase("id")) { return PresenceAbsenceTerm.INTRODUCED_DOUBTFULLY_INTRODUCED();
232
  		} else if (abbrev.equalsIgnoreCase("in")) { return PresenceAbsenceTerm.NATURALISED();
233
  		} else if (abbrev.equalsIgnoreCase("ip")) { return PresenceAbsenceTerm.INTRODUCED_UNCERTAIN_DEGREE_OF_NATURALISATION();
234
  		} else if (abbrev.equalsIgnoreCase("iq")) { return PresenceAbsenceTerm.INTRODUCED_PRESENCE_QUESTIONABLE();
235
  		} else if (abbrev.equalsIgnoreCase("n"))  { return PresenceAbsenceTerm.NATIVE();
236
  		} else if (abbrev.equalsIgnoreCase("nd")) { return PresenceAbsenceTerm.NATIVE_DOUBTFULLY_NATIVE();
237
  		} else if (abbrev.equalsIgnoreCase("nq")) { return PresenceAbsenceTerm.NATIVE_PRESENCE_QUESTIONABLE();
238
  		} else if (abbrev.equalsIgnoreCase("p"))  { return PresenceAbsenceTerm.PRESENT();
239
  		} else if (abbrev.equalsIgnoreCase("na"))  { return PresenceAbsenceTerm.NATURALISED();
240
  		} else if (abbrev.equalsIgnoreCase("iv"))  { return PresenceAbsenceTerm.INVASIVE();
241
  		//absence
242
		} else if (abbrev.equalsIgnoreCase("cf")) { return PresenceAbsenceTerm.CULTIVATED_REPORTED_IN_ERROR();
243
		} else if (abbrev.equalsIgnoreCase("if")) { return PresenceAbsenceTerm.INTRODUCED_REPORTED_IN_ERROR();
244
		} else if (abbrev.equalsIgnoreCase("nf")) { return PresenceAbsenceTerm.NATIVE_REPORTED_IN_ERROR();
245
		} else if (abbrev.equalsIgnoreCase("ne")) { return PresenceAbsenceTerm.NATIVE_FORMERLY_NATIVE();
246
		} else if (abbrev.equalsIgnoreCase("ie")) { return PresenceAbsenceTerm.INTRODUCED_FORMERLY_INTRODUCED();
247
		} else {
248
			logger.warn("Unknown presence or absence status term abbreviation: " + abbrev);
249
			return null;
250
		}
251
  	}
252

    
253
    /**
254
     * The taxon is endemic for the given area.
255
     * @see #PRESENT()
256
     * @see #NATIVE()
257
     * @see #ENDEMIC_DOUBTFULLY_PRESENT()
258
     * @see #ENDEMIC_REPORTED_IN_ERROR()
259
     */
260
    public static final PresenceAbsenceTerm ENDEMIC_FOR_THE_RELEVANT_AREA(){
261
        return getTermByUuid(uuidEndemic);
262
    }
263

    
264
    /**
265
     * The taxon is present but not endemic for the given area.
266
     * @see #PRESENT()
267
     * @see #NATIVE()
268
     * @see #ENDEMIC_FOR_THE_RELEVANT_AREA()
269
     * @see #ENDEMIC_DOUBTFULLY_PRESENT()
270
     * @see #ENDEMIC_REPORTED_IN_ERROR()
271
     */
272
    public static final PresenceAbsenceTerm NOT_ENDEMIC_FOR_THE_RELEVANT_AREA(){
273
        return getTermByUuid(uuidNotEndemic);
274
    }
275

    
276
    /**
277
     * The taxon is present but with unknown endemism for the given area.
278
     * @see #PRESENT()
279
     * @see #NATIVE()
280
     * @see #ENDEMIC_FOR_THE_RELEVANT_AREA()
281
     * @see #ENDEMIC_DOUBTFULLY_PRESENT()
282
     * @see #ENDEMIC_REPORTED_IN_ERROR()
283
     * @see #NOT_ENDEMIC_FOR_THE_RELEVANT_AREA()
284
     */
285
    public static final PresenceAbsenceTerm ENDEMISM_UNKNOWN(){
286
        return getTermByUuid(uuidUnknownEndemism);
287
    }
288

    
289
    /**
290
     * The taxon is endemic for the given area but doubtfully present.
291
     * @see #ENDEMIC_FOR_THE_RELEVANT_AREA()
292
     * @see #ENDEMIC_REPORTED_IN_ERROR()
293
     * @see #PRESENT_DOUBTFULLY()
294
     * @see #NATIVE_PRESENCE_QUESTIONABLE()
295
     */
296
    public static final PresenceAbsenceTerm ENDEMIC_DOUBTFULLY_PRESENT(){
297
        return getTermByUuid(uuidEndedmicPresenceQuestionable);
298
    }
299

    
300
    /**
301
     * The taxon if it exists is endemic for the given area but was only
302
     * erroneously reported.
303
     * So it either does not exist or it is unclear where it was originally found.
304
     * @see #ENDEMIC_FOR_THE_RELEVANT_AREA()
305
     * @see #ENDEMIC_DOUBTFULLY_PRESENT()
306
     * @see #REPORTED_IN_ERROR()
307
     * @see #NATIVE_REPORTED_IN_ERROR()
308
     */
309
    public static final PresenceAbsenceTerm ENDEMIC_REPORTED_IN_ERROR(){
310
        return getTermByUuid(uuidEndemicReportedError);
311
    }
312

    
313

    
314
	/**
315
	 * The taxon is present in the given area. No information given about
316
	 * nativeness/establishment means.
317
	 *
318
	 * @see #PRESENT_DOUBTFULLY()
319
	 * @see #ABSENT()
320
	 */
321
	public static final PresenceAbsenceTerm PRESENT(){
322
		return getTermByUuid(uuidPresent);
323
	}
324

    
325
	/**
326
     * Presence of the taxon in the given area is doubtful. No information given about
327
     * nativeness/establishment means.
328
     *
329
     * @see #PRESENT()
330
     * @see #ABSENT()
331
     */
332
	public static final PresenceAbsenceTerm PRESENT_DOUBTFULLY(){
333
		return getTermByUuid(uuidPresentDoubfully);
334
	}
335

    
336
	/**
337
	 * The taxon is not native but cultivated.
338
	 *
339
	 * @see #CULTIVATED_PRESENCE_QUESTIONABLE()
340
	 * @see #CULTIVATED_REPORTED_IN_ERROR()
341
	 */
342
	public static final PresenceAbsenceTerm CULTIVATED(){
343
		return getTermByUuid(uuidCultivated);
344
	}
345

    
346
	/**
347
     * The taxon is cultivated but presence is questionable.
348
     *
349
     * @see #CULTIVATED()
350
     * @see #CULTIVATED_REPORTED_IN_ERROR()
351
     */
352
    public static final PresenceAbsenceTerm CULTIVATED_PRESENCE_QUESTIONABLE(){
353
        return getTermByUuid(uuidCultivatedPresenceQuestionable);
354
    }
355

    
356
    /**
357
     * The taxon is erroneously reported as cultivated.
358
     *
359
     * @see #CULTIVATED()
360
     * @see #CULTIVATED_REPORTED_IN_ERROR()
361
     */
362
    public static final PresenceAbsenceTerm CULTIVATED_REPORTED_IN_ERROR(){
363
        return getTermByUuid(uuidCultivatedReportedError);
364
    }
365

    
366

    
367
	public static final PresenceAbsenceTerm INTRODUCED(){
368
		return getTermByUuid(uuidIntroduced);
369
	}
370

    
371
    /**
372
     * Casual alien or introduced: adventive (casual)
373
     *
374
     * @see #CASUAL_REPORTED_IN_ERROR()
375
     * @see #CASUAL_PRESENCE_QUESTIONABLE()
376
     * @see #INTRODUCED_ADVENTITIOUS()
377
     */
378
    public static final PresenceAbsenceTerm CASUAL(){
379
        return getTermByUuid(uuidIntroducedAdventitious);
380
    }
381
    /**
382
     * Casual alien, presence questionable
383
     *
384
     * @see #CASUAL()
385
     * @see #CASUAL_REPORTED_IN_ERROR()
386
     * @see #PRESENT_DOUBTFULLY()
387
     */
388
    public static final PresenceAbsenceTerm CASUAL_PRESENCE_QUESTIONABLE(){
389
        return getTermByUuid(uuidCasualPresenceQuestionable);
390
    }
391
    /**
392
     * Casual alien, reported in error
393
     *
394
     * @see #CASUAL()
395
     * @see #CASUAL_PRESENCE_QUESTIONABLE()
396
     * @see #REPORTED_IN_ERROR()
397
     */
398
    public static final PresenceAbsenceTerm CASUAL_REPORTED_IN_ERROR(){
399
        return getTermByUuid(uuidCasualReportedError);
400
    }
401

    
402

    
403
	/**
404
	 * This term is of questional value. Introduced often is handled as opposite
405
	 * of adventitious/adventive and describes how the alien species came
406
	 * - on purpose for cultivation (introduced) or not (adventive).
407
	 * Adventitious or better adventive is often a synonym for casual which might
408
	 * be the better term here.
409
	 *
410
	 * @deprecated better use {@link #CASUAL()}, which has the same result (same semantics, but more precise)
411
	 */
412
	@Deprecated
413
	public static final PresenceAbsenceTerm INTRODUCED_ADVENTITIOUS(){
414
		return getTermByUuid(uuidIntroducedAdventitious);
415
	}
416

    
417
	public static final PresenceAbsenceTerm INTRODUCED_CULTIVATED(){
418
		return getTermByUuid(uuidIntroducedCultiated);
419
	}
420

    
421
	public static final PresenceAbsenceTerm INTRODUCED_DOUBTFULLY_INTRODUCED(){
422
		return getTermByUuid(uuidIntroducedDoubtfullyIntroduced);
423
	}
424

    
425

    
426
    public static final PresenceAbsenceTerm INTRODUCED_UNCERTAIN_DEGREE_OF_NATURALISATION(){
427
        return getTermByUuid(uuidIntroducedUncertainDegreeNaturalisation);
428
    }
429

    
430
	public static final PresenceAbsenceTerm INTRODUCED_PRESENCE_QUESTIONABLE(){
431
		return getTermByUuid(uuidIntroducedPresenceQuestionable);
432
	}
433

    
434
    public static final PresenceAbsenceTerm INTRODUCED_FORMERLY_INTRODUCED(){
435
        return getTermByUuid(uuidIntroducedFormerlyIntroduced);
436
    }
437

    
438
    public static final PresenceAbsenceTerm INTRODUCED_REPORTED_IN_ERROR(){
439
        return getTermByUuid(uuidIntroducedReportedError);
440
    }
441

    
442
	/**
443
	 * Use native if the taxon is native in the according area. Native and indigenous
444
	 * have the same meaning. Native might be problematic because the abbreviation
445
	 * N is already used for naturalised.
446
	 *
447
	 * @see #NATIVE_DOUBTFULLY_NATIVE()
448
     * @see #NATIVE_PRESENCE_QUESTIONABLE()
449
     * @see #NATIVE_REPORTED_IN_ERROR()
450
	 */
451
	public static final PresenceAbsenceTerm NATIVE(){
452
		return getTermByUuid(uuidNative);
453
	}
454

    
455
    /**
456
     * Same as {@link #NATIVE()} but presence is questionable
457
     * @see #NATIVE()
458
     * @see #NATIVE_DOUBTFULLY_NATIVE()
459
     * @see #NATIVE_REPORTED_IN_ERROR()
460
     */
461
    public static final PresenceAbsenceTerm NATIVE_PRESENCE_QUESTIONABLE(){
462
        return getTermByUuid(uuidNativePresenceQuestionable);
463
    }
464

    
465
    /**
466
     * The taxon was formerly native, but is extinct now in the given area.
467
     *
468
     * @see #NATIVE()
469
     * @see #ABSENT()
470
     */
471
    public static final PresenceAbsenceTerm NATIVE_FORMERLY_NATIVE(){
472
        return getTermByUuid(uuidNativeFormerlyNative);
473
    }
474

    
475
    /**
476
     * Same as {@link #NATIVE()} but presence was reported in error, so
477
     * finally it is not native.
478
     * @see #NATIVE()
479
     * @see #NATIVE_PRESENCE_QUESTIONABLE()
480
     * @see #NATIVE_DOUBTFULLY_NATIVE()
481
     */
482
    public static final PresenceAbsenceTerm NATIVE_REPORTED_IN_ERROR(){
483
        return getTermByUuid(uuidNativeError );
484
    }
485

    
486
	/**
487
	 * Same as {@link #NATIVE()} but the nativeness is doubtful, while presence
488
	 * is NOT questionable
489
	 * @see #NATIVE()
490
	 * @see #NATIVE_PRESENCE_QUESTIONABLE()
491
	 * @see #NATIVE_REPORTED_IN_ERROR()
492
	 */
493
	public static final PresenceAbsenceTerm NATIVE_DOUBTFULLY_NATIVE(){
494
		return getTermByUuid(uuidNativeDoubtfullyNative);
495
	}
496

    
497
    /**
498
     * Same as {@link #NATIVE()} but the nativeness is doubtful, while presence
499
     * is NOT questionable
500
     * @see #NATIVE_DOUBTFULLY_NATIVE()
501
     * @see #NATIVE()
502
     * @see #NATIVE_PRESENCE_QUESTIONABLE()
503
     */
504
    public static final PresenceAbsenceTerm NATIVE_DOUBTFULLY_NATIVE_REPORTED_IN_ERROR(){
505
        return getTermByUuid(uuidNativeDoubtfullyNativeReportedError);
506
    }
507

    
508

    
509
    /**
510
     * Naturalized (or introduced: naturalized). Further distinction can be made by
511
     * distinguishing invasive / non-invasive
512
     * @see #NATURALISED_PRESENCE_QUESTIONABLE()
513
     * @see #NATURALISED_REPORTED_IN_ERROR()
514
     * @see #INVASIVE()
515
     * @see #NON_INVASIVE
516
     */
517
    public static final PresenceAbsenceTerm NATURALISED(){
518
        return getTermByUuid(uuidNaturalised);
519
    }
520

    
521
    /**
522
    *
523
    * @see #NATURALISED()
524
    */
525
   public static final PresenceAbsenceTerm NATURALISED_PRESENCE_QUESTIONABLE(){
526
       return getTermByUuid(uuidNaturalisedPresenceQuestionable);
527
   }
528

    
529
    public static final PresenceAbsenceTerm NATURALISED_REPORTED_IN_ERROR(){
530
        return getTermByUuid(uuidNaturalisedReportedError);
531
    }
532

    
533
	/**
534
	 * Naturalized invasive. <BR>
535
	 * The taxon is present but not native in the given area. Additionally
536
	 * it is spreading fast.
537
	 *
538
	 * @see #INVASIVE_PRESENCE_QUESTIONABLE()
539
	 * @see #NON_INVASIVE()
540
	 * @see #NON_INVASIVE_PRESENCE_QUESTIONABLE()
541
	 */
542
	public static final PresenceAbsenceTerm INVASIVE(){
543
		return getTermByUuid(uuidInvasive);
544
	}
545
    /**
546
     * Invasive, presence questionable.
547
     *
548
     * @see #INVASIVE()
549
     * @see #NON_INVASIVE()
550
     * @see #NON_INVASIVE_PRESENCE_QUESTIONABLE()
551
     */
552
    public static final PresenceAbsenceTerm INVASIVE_PRESENCE_QUESTIONABLE(){
553
        return getTermByUuid(uuidInvasivePresenceQuestionable);
554
    }
555
    /**
556
     * The taxon is present but not native in the given area (naturalized).
557
     * Additionally it is spreading not so fast.
558
     *
559
     * @see #INVASIVE()
560
     * @see #INVASIVE_PRESENCE_QUESTIONABLE()
561
     * @see #NON_INVASIVE_PRESENCE_QUESTIONABLE()
562
     */
563
    public static final PresenceAbsenceTerm NON_INVASIVE(){
564
        return getTermByUuid(uuidNonInvasive);
565
    }
566
    /**
567
     * The taxon is questionable present and not native in the given area (naturalized).
568
     * Additionally it is spreading not so fast
569
     *
570
     * @see #NON_INVASIVE()
571
     * @see #INVASIVE()
572
     * @see #INVASIVE_PRESENCE_QUESTIONABLE()
573
     */
574
    public static final PresenceAbsenceTerm NON_INVASIVE_PRESENCE_QUESTIONABLE(){
575
        return getTermByUuid(uuidNonInvasivePresenceQuestionable);
576
    }
577

    
578

    
579
	/**
580
	 * @see #PRESENT()
581
	 * @see #REPORTED_IN_ERROR()
582
	 */
583
	public static final PresenceAbsenceTerm ABSENT(){
584
		return getTermByUuid(uuidAbsence);
585
	}
586

    
587
	/**
588
	 * The taxon is {@link #ABSENT() absent} in the given area
589
	 * but was erroneously reported as present.
590
	 *
591
	 * @see #ABSENT()
592
	 * @see #NATIVE_REPORTED_IN_ERROR()
593
	 * @see #INTRODUCED_REPORTED_IN_ERROR()
594
	 */
595
	public static final PresenceAbsenceTerm REPORTED_IN_ERROR(){
596
        return getTermByUuid(uuidReportedInError);
597
    }
598

    
599
	/**
600
	 * The status of the taxon in the given area is not defined
601
	 * for whatever reason.
602
	 */
603
	public static final PresenceAbsenceTerm UNDEFINED(){
604
	    return getTermByUuid(uuidUndefined);
605
	}
606

    
607

    
608
//******************************** METHODS ****************************/
609

    
610
	@Override
611
	public void resetTerms(){
612
		termMap = null;
613
	}
614

    
615
	@Override
616
	protected void setDefaultTerms(TermVocabulary<PresenceAbsenceTerm> termVocabulary) {
617
		termMap = new HashMap<>();
618
		for (PresenceAbsenceTerm term : termVocabulary.getTerms()){
619
			termMap.put(term.getUuid(), term);
620
		}
621
	}
622

    
623
    @Override
624
    public PresenceAbsenceTerm readCsvLine(Class<PresenceAbsenceTerm> termClass, List<String> csvLine, TermType termType,
625
            Map<UUID,DefinedTermBase> terms, boolean abbrevAsId){
626
    	PresenceAbsenceTerm newInstance = super.readCsvLine(termClass, csvLine, termType, terms, abbrevAsId);
627
        String abbreviatedLabel = csvLine.get(4);
628
//		String uuid = (String)csvLine.get(0);
629
//		map.put(abbreviatedLabel, UUID.fromString(uuid));
630
        String symbol = csvLine.get(5);
631
        newInstance.setSymbol(symbol);
632
        String color = csvLine.get(6);
633
        try {
634
			newInstance.setDefaultColor(color);
635
		} catch (ParseException e) {
636
			throw new RuntimeException(e);
637
		}
638
        boolean isAbsence = csvLine.get(7).equals("1") ? true : false;
639
        newInstance.setAbsenceTerm(isAbsence);
640

    
641
        newInstance.getRepresentation(Language.DEFAULT()).setAbbreviatedLabel(abbreviatedLabel);
642
        return newInstance;
643
    }
644

    
645
    /**
646
     * @return the defaultColor
647
     */
648
    public String getDefaultColor() {
649
        return defaultColor;
650
    }
651

    
652
    /**
653
     * @param defaultColor the defaultColor to set
654
     * @throws ParseException
655
     */
656
    //TODO make format checking a hibernate validation rule
657
    public void setDefaultColor(String defaultColor) throws ParseException  {
658
    	String regEx = "[0-9a-fA-F]{6}";
659
    	if (StringUtils.isEmpty(defaultColor)){
660
    		this.defaultColor = null;
661
    	}else if (StringUtils.isEmpty(defaultColor) || defaultColor.matches(regEx)){
662
        		this.defaultColor = defaultColor;
663
    	}else{
664
    		throw new java.text.ParseException("Default color is not of correct format. Required is 'FFFFFF'", -1);
665
    	}
666
    }
667

    
668
    /**
669
     * Includes presence/absence compare instead of pure uuid compare
670
     */
671
    @Override
672
    protected int compareVocabularies(PresenceAbsenceTerm thatTerm) {
673
        UUID thisVocUuid = this.vocabulary == null? null:this.vocabulary.getUuid();
674
        UUID thatVocUuid = thatTerm.getVocabulary() == null? null:thatTerm.getVocabulary().getUuid();
675
        int vocCompare = CdmUtils.nullSafeCompareTo(thisVocUuid, thatVocUuid);
676
        if (vocCompare != 0 && thatTerm.isAbsenceTerm() != this.isAbsenceTerm() ){
677
            if (thatTerm.isAbsenceTerm()){
678
                return 1;
679
            }else{
680
                return -1;
681
            }
682
        }
683
        return vocCompare;
684
    }
685

    
686
    /**
687
     * {@inheritDoc}
688
     *
689
     * For {@link PresenceAbsenceTerm} there is an additional rule that before comparing vocabulary uuid
690
     * presence terms are preferred to absence terms.
691
     */
692
    @Override
693
    public int compareTo(PresenceAbsenceTerm presenceAbsenceTerm) {
694
        return performCompareTo(presenceAbsenceTerm, true);
695
    }
696

    
697
	public boolean isAbsenceTerm() {
698
		return absenceTerm;
699
	}
700

    
701
	public void setAbsenceTerm(boolean isAbsenceTerm) {
702
		this.absenceTerm = isAbsenceTerm;
703
	}
704

    
705
	@Transient
706
	private Set<UUID> isAnyIntroduced;
707
    public boolean isAnyIntroduced() {
708
        if (isAnyIntroduced == null){
709
            isAnyIntroduced = new HashSet<>(Arrays.asList(new UUID[]{
710
                   uuidCasualPresenceQuestionable, uuidCasualReportedError,
711
                   uuidCultivated, uuidCultivatedPresenceQuestionable, uuidCultivatedReportedError,
712
                   uuidIntroduced, uuidIntroducedCultiated, uuidIntroducedDoubtfullyIntroduced,
713
                   uuidIntroducedFormerlyIntroduced, uuidIntroducedPresenceQuestionable,
714
                   uuidIntroducedReportedError, uuidIntroducedUncertainDegreeNaturalisation,
715
                   uuidIntroducedAdventitious,
716
                   uuidInvasive, uuidInvasivePresenceQuestionable,
717
                   uuidNaturalised, uuidNaturalisedPresenceQuestionable, uuidNaturalisedReportedError,
718
                   uuidIntroducedUncertainDegreeNaturalisation,
719
                   uuidInvasive, uuidInvasivePresenceQuestionable, uuidNonInvasive, uuidNonInvasivePresenceQuestionable
720
            }));
721
        }
722
        return isAnyIntroduced.contains(uuid);
723
    }
724
}
(24-24/38)