Project

General

Profile

Download (14.6 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.location;
11

    
12
import java.util.ArrayList;
13
import java.util.HashMap;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Map;
17
import java.util.Set;
18
import java.util.UUID;
19

    
20
import javax.persistence.Entity;
21
import javax.persistence.FetchType;
22
import javax.persistence.JoinTable;
23
import javax.persistence.ManyToMany;
24
import javax.persistence.ManyToOne;
25
import javax.persistence.Transient;
26
import javax.xml.bind.annotation.XmlAccessType;
27
import javax.xml.bind.annotation.XmlAccessorType;
28
import javax.xml.bind.annotation.XmlElement;
29
import javax.xml.bind.annotation.XmlElementWrapper;
30
import javax.xml.bind.annotation.XmlIDREF;
31
import javax.xml.bind.annotation.XmlRootElement;
32
import javax.xml.bind.annotation.XmlSchemaType;
33
import javax.xml.bind.annotation.XmlSeeAlso;
34
import javax.xml.bind.annotation.XmlType;
35

    
36
import org.apache.log4j.Logger;
37
import org.hibernate.annotations.Cascade;
38
import org.hibernate.annotations.CascadeType;
39
import org.hibernate.envers.Audited;
40
import org.hibernate.search.annotations.Indexed;
41

    
42
import eu.etaxonomy.cdm.common.CdmUtils;
43
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
44
import eu.etaxonomy.cdm.model.common.DefinedTermBase;
45
import eu.etaxonomy.cdm.model.common.Language;
46
import eu.etaxonomy.cdm.model.common.OrderedTermBase;
47
import eu.etaxonomy.cdm.model.common.Representation;
48
import eu.etaxonomy.cdm.model.common.TermVocabulary;
49
import eu.etaxonomy.cdm.model.common.TimePeriod;
50
import eu.etaxonomy.cdm.model.media.Media;
51

    
52
/**
53
 * @author m.doering
54
 * @version 1.0
55
 * @created 08-Nov-2007 13:06:36
56
 */
57
@XmlAccessorType(XmlAccessType.PROPERTY)
58
@XmlType(name = "NamedArea", propOrder = {
59
	"kindOf",
60
	"generalizationOf",
61
	"partOf",
62
	"includes",
63
    "validPeriod",
64
    "shape",
65
    "pointApproximation",
66
    "waterbodiesOrCountries",
67
    "type",
68
    "level"
69
})
70
@XmlRootElement(name = "NamedArea")
71
@XmlSeeAlso({
72
	TdwgArea.class,
73
	Continent.class,
74
	WaterbodyOrCountry.class
75
})
76
@Entity
77
@Indexed(index = "eu.etaxonomy.cdm.model.common.DefinedTermBase")
78
@Audited
79
public class NamedArea extends OrderedTermBase<NamedArea> implements Cloneable {
80
	private static final long serialVersionUID = 6248434369557403036L;
81
	@SuppressWarnings("unused")
82
	private static final Logger logger = Logger.getLogger(NamedArea.class);
83
	
84
	private static Map<UUID, NamedArea> termMap = null;		
85

    
86
//************************* FACTORY METHODS ****************************************/
87
	
88
	/**
89
	 * Factory method
90
	 * @return
91
	 */
92
	public static NamedArea NewInstance(){
93
		return new NamedArea();
94
	}
95

    
96
	/**
97
	 * Factory method
98
	 * @return
99
	 */
100
	public static NamedArea NewInstance(String term, String label, String labelAbbrev){
101
		return new NamedArea(term, label, labelAbbrev);
102
	}
103
	
104
//**************************** VARIABLES *******************************/
105
	
106
	//description of time valid context of this area. e.g. year range
107
	private TimePeriod validPeriod = TimePeriod.NewInstance();
108
	
109
	//Binary shape definition for user's defined area as polygon
110
	@ManyToOne(fetch = FetchType.LAZY)
111
	@Cascade(CascadeType.SAVE_UPDATE)
112
	private Media shape;
113
	
114
	private Point pointApproximation;
115
	
116
	@ManyToMany(fetch = FetchType.LAZY)
117
    @JoinTable(name="DefinedTermBase_WaterbodyOrCountry")
118
	private Set<WaterbodyOrCountry> waterbodiesOrCountries = new HashSet<WaterbodyOrCountry>();
119
	
120
	@ManyToOne(fetch = FetchType.LAZY)
121
	private NamedAreaType type;
122
	
123
	@ManyToOne(fetch = FetchType.LAZY)
124
	private NamedAreaLevel level;
125

    
126
//*************************** CONSTRUCTOR ******************************************/
127
	
128
	/**
129
	 * Constructor
130
	 */
131
	public NamedArea() {
132
	}
133
	
134
	public NamedArea(String term, String label, String labelAbbrev) {
135
		super(term, label, labelAbbrev);
136
	}
137
	
138
//********************************* GETTER /SETTER *********************************************/	
139

    
140
	@XmlElement(name = "NamedAreaType")
141
	@XmlIDREF
142
	@XmlSchemaType(name = "IDREF")
143
	public NamedAreaType getType(){
144
		return this.type;
145
	}
146
	
147
	public void setType(NamedAreaType type){
148
		this.type = type;
149
	}
150

    
151
	@XmlElement(name = "NamedAreaLevel")
152
	@XmlIDREF
153
	@XmlSchemaType(name = "IDREF")
154
	public NamedAreaLevel getLevel(){
155
		return this.level;
156
	}
157
	
158
	public void setLevel(NamedAreaLevel level){
159
		this.level = level;
160
	}
161

    
162
	@XmlElement(name = "ValidPeriod")
163
	public TimePeriod getValidPeriod(){
164
		return this.validPeriod;
165
	}
166
	
167
	public void setValidPeriod(TimePeriod validPeriod){
168
		this.validPeriod = validPeriod;
169
	}
170

    
171
	@XmlElement(name = "Shape")
172
	@XmlIDREF
173
	@XmlSchemaType(name = "IDREF")
174
	public Media getShape(){
175
		return this.shape;
176
	}
177
	public void setShape(Media shape){
178
		this.shape = shape;
179
	}
180

    
181
	@XmlElementWrapper(name = "WaterbodiesOrCountries")
182
	@XmlElement(name = "WaterbodiesOrCountry")
183
	@XmlIDREF
184
	@XmlSchemaType(name = "IDREF")
185
	public Set<WaterbodyOrCountry> getWaterbodiesOrCountries() {
186
		return waterbodiesOrCountries;
187
	}
188
	
189
	public void addWaterbodyOrCountry(WaterbodyOrCountry waterbodyOrCountry) {
190
		this.waterbodiesOrCountries.add(waterbodyOrCountry);
191
	}
192
	
193
	public void removeWaterbodyOrCountry(WaterbodyOrCountry waterbodyOrCountry) {
194
		this.waterbodiesOrCountries.remove(waterbodyOrCountry);
195
	}
196
	
197
	@XmlElement(name = "PointApproximation")
198
	public Point getPointApproximation() {
199
		return pointApproximation;
200
	}
201
	public void setPointApproximation(Point pointApproximation) {
202
		this.pointApproximation = pointApproximation;
203
	}
204
	
205
	@XmlElement(name = "KindOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
206
    @XmlIDREF
207
    @XmlSchemaType(name = "IDREF")
208
	public NamedArea getKindOf(){
209
		return super.getKindOf();
210
	}
211

    
212
	public void setKindOf(NamedArea kindOf){
213
		super.setKindOf(kindOf);
214
	}
215
	
216
	@XmlElement(name = "PartOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
217
	@XmlIDREF
218
    @XmlSchemaType(name = "IDREF")
219
    @Override
220
	public NamedArea getPartOf(){
221
		return super.getPartOf();
222
	}
223
	
224
	/**
225
	 * FIXME this method is a workaround for a casting problem in the getPartOf implementation
226
	 * 
227
	 * the partOf instance variable is typically a proxy object of type DefinedTermBase, thus
228
	 * does not coincide with the return value of NamedArea and a ClassCastException is thrown.
229
	 * 
230
	 * It is not clear why this only occurs in the editor and not in the webservice where the same
231
	 * method gets called and should lead to the same results.
232
	 * 
233
	 * Seems to be a bigger problem although its origin is buggy behaviour of the javassist implementation.
234
	 */
235
	@Deprecated
236
	@Transient
237
	public NamedArea getPartOfWorkaround(){
238
		Object area = super.getPartOf();
239
		
240
		if(!(area instanceof NamedArea)){
241
			area = HibernateProxyHelper.deproxy(area, NamedArea.class);
242
		}
243
		
244
		return (NamedArea) area;
245
	}
246
	
247
	public void setPartOf(NamedArea partOf){
248
		this.partOf = partOf;
249
	}
250
	
251
	@XmlElementWrapper(name = "Generalizations", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
252
	@XmlElement(name = "GeneralizationOf", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
253
    @XmlIDREF
254
    @XmlSchemaType(name = "IDREF")
255
	public Set<NamedArea> getGeneralizationOf(){
256
		return super.getGeneralizationOf();
257
	}
258
	
259
	protected void setGeneralizationOf(Set<NamedArea> value){
260
		super.setGeneralizationOf(value);
261
	}
262
	
263
	@XmlElementWrapper(name = "Includes", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
264
	@XmlElement(name = "Include", namespace = "http://etaxonomy.eu/cdm/model/common/1.0")
265
	@XmlIDREF
266
    @XmlSchemaType(name = "IDREF")
267
	public Set<NamedArea> getIncludes(){
268
		return super.getIncludes();
269
	}
270
	
271
	protected void setIncludes(Set<NamedArea> includes) {
272
		super.setIncludes(includes);
273
	}
274
	
275

    
276
	/* (non-Javadoc)
277
	 * @see eu.etaxonomy.cdm.model.common.DefinedTermBase#readCsvLine(java.util.List)
278
	 */
279
	@Override
280
	public NamedArea readCsvLine(Class<NamedArea> termClass, List<String> csvLine, Map<UUID,DefinedTermBase> terms) {
281
		NamedArea newInstance = super.readCsvLine(termClass, csvLine, terms);
282
		
283
		String levelString = (String)csvLine.get(6);
284
		
285
		if(levelString != null && levelString.length() != 0) {
286
			UUID levelUuid = UUID.fromString(levelString);
287
			NamedAreaLevel level = (NamedAreaLevel)terms.get(levelUuid);
288
			newInstance.setLevel(level);
289
		}
290
		
291
		String partOfString = (String)csvLine.get(7);
292
	
293
		if(partOfString != null && partOfString.length() != 0) {
294
			UUID partOfUuid = UUID.fromString(partOfString);
295
			NamedArea partOf = (NamedArea)terms.get(partOfUuid);
296
			partOf.addIncludes(newInstance);
297
		} 
298
		return newInstance;
299
	}
300
	
301

    
302
	
303
	
304
	/* (non-Javadoc)
305
	 * @see eu.etaxonomy.cdm.model.common.DefinedTermBase#resetTerms()
306
	 */
307
	@Override
308
	public void resetTerms(){
309
		termMap = null;
310
	}
311

    
312
	
313
	@Override
314
	protected void setDefaultTerms(TermVocabulary<NamedArea> termVocabulary) {
315
		termMap = new HashMap<UUID, NamedArea>();
316
		for (NamedArea term : termVocabulary.getTerms()){
317
			termMap.put(term.getUuid(), term);
318
		}
319
	}
320
	
321
// ************** Hierarchie List ****************************	
322
	
323
/*	public boolean equals(NamedArea area){
324
		boolean result = false;
325
		if (this.getLabel().toString().compareTo(area.getLabel().toString()) == 0){
326
			result = true;
327
		}
328
		return result;
329
	}*/
330
	
331
//	public int compareTo(NamedArea area){
332
//		return getLabel().compareTo(area.getLabel());
333
//	}
334
	
335
	
336
	
337
	public NamedAreaNode getHiearchieList(List<NamedArea> areaList){
338
		NamedAreaNode result = new NamedAreaNode();
339
		for (NamedArea area : areaList){
340
			List<NamedArea> areaHierarchie  = area.getAllLevelList();
341
			mergeIntoResult(result, areaHierarchie);
342
		}
343
		return result;
344
	}
345
	
346
	
347
	public class LevelNode {
348
		NamedAreaLevel level;
349
		List<NamedAreaNode> areaList = new ArrayList<NamedAreaNode>();
350

    
351
		public NamedAreaNode add(NamedArea area) {
352
			NamedAreaNode node = new NamedAreaNode();
353
			node.area = area;
354
			areaList.add(node);
355
			return node;
356

    
357
		}
358

    
359
		public NamedAreaNode getNamedAreaNode(NamedArea area) {
360
			for (NamedAreaNode node : areaList) {
361
				if (node.area.equals(area)) {
362
					return node;
363
				}
364
			}
365
			return null;
366
		}
367

    
368
		public String toString() {
369
			return level.getTitleCache();
370
		}
371

    
372
	}
373

    
374
	public class NamedAreaNode {
375
		NamedArea area;
376
		List<LevelNode> levelList = new ArrayList<LevelNode>();
377
		
378
		public LevelNode getLevelNode(NamedAreaLevel level) {
379
			for (LevelNode node : levelList) {
380
				if (node.level.equals(level)) {
381
					return node;
382
				}
383
			}
384
			return null;
385
		}
386

    
387
		public List<NamedAreaNode> getList(NamedAreaLevel level) {
388
			LevelNode node = getLevelNode(level);
389
			if (node == null) {
390
				return new ArrayList<NamedAreaNode>();
391
			} else {
392
				return node.areaList;
393
			}
394
		};
395

    
396
		public boolean contains(NamedAreaLevel level) {
397
			if (getList(level).size() > 0) {
398
				return true;
399
			} else {
400
				return false;
401
			}
402
		}
403

    
404
		public LevelNode add(NamedAreaLevel level) {
405
			LevelNode node = new LevelNode();
406
			node.level = level;
407
			levelList.add(node);
408
			return node;
409
		}
410

    
411
		public String toString() {
412
			if (area == null) {
413
				return "";
414
			}
415
			return area.getTitleCache();
416
		}
417
	}
418

    
419
	private void mergeIntoResult(NamedAreaNode root,
420
			List<NamedArea> areaHierarchie) {
421
		if (areaHierarchie.isEmpty()) {
422
			return;
423
		}
424
		NamedArea highestArea = areaHierarchie.get(0);
425
		NamedAreaLevel level = highestArea.getLevel();
426
		NamedAreaNode namedAreaNode;
427
		if (!root.contains(level)) {
428
			LevelNode node = root.add(level);
429
			namedAreaNode = node.add(highestArea);
430
		} else {
431
			LevelNode levelNode = root.getLevelNode(level);
432
			namedAreaNode = levelNode.getNamedAreaNode(highestArea);
433
			if (namedAreaNode == null) {
434
				namedAreaNode = levelNode.add(highestArea);
435
			}
436
		}
437
		List<NamedArea> newList = areaHierarchie.subList(1, areaHierarchie
438
				.size());
439
		mergeIntoResult(namedAreaNode, newList);
440

    
441
	}
442

    
443
	@Transient
444
	public List<NamedArea> getAllLevelList() {
445
		List<NamedArea> result = new ArrayList<NamedArea>();
446
		NamedArea copyArea = this;
447
		result.add(copyArea);		
448
		while (copyArea.getPartOf() != null) {
449
			copyArea = copyArea.getPartOf();
450
			result.add(0, copyArea);
451
		}
452
		return result;
453
	}
454
	
455
// ******************* toString **********************************/	
456

    
457
	/* (non-Javadoc)
458
	 * @see eu.etaxonomy.cdm.model.common.TermBase#toString()
459
	 */
460
	public String toString(){
461
		String result, label, level = "";
462
		
463
		if (this.level != null){
464
			level = this.level.getLabel();
465
		}else{
466
			level = "no level";
467
		}
468
		label = this.getLabel();
469
		result = "[" + level + ", " + label + "]";
470
		
471
		return result;
472
	}
473
	
474
	
475

    
476
	/**
477
	 * Returns the label of the named area together with the area level label and the abbreviated label
478
	 * @param namedArea the area
479
	 * @param language the preferred language
480
	 * @return
481
	 */
482
	public static String labelWithLevel(NamedArea namedArea, Language language) {
483
		NamedArea area = (NamedArea) HibernateProxyHelper.deproxy(namedArea);
484
		
485
		StringBuilder title = new StringBuilder();
486
		Representation representation = area.getPreferredRepresentation(language);
487
		if (representation != null){
488
			String areaString = getPreferredAreaLabel(namedArea, representation);
489
			
490
			title.append(areaString);
491
			if (! area.getClass().equals(NamedArea.class)){
492
				title.append(" - ");
493
				title.append(area.getClass().getSimpleName());
494
			}
495
			if(area.getLevel() != null){
496
				title.append(" - ");
497
				Representation levelRepresentation = area.getLevel().getPreferredRepresentation(language);
498
				String levelString = getPreferredAreaLabel(area.getLevel(), levelRepresentation);
499
				title.append(levelString);
500
			}
501
			if(! CdmUtils.isEmpty(representation.getAbbreviatedLabel())){
502
				title.append(" - ");
503
				title.append(representation.getAbbreviatedLabel());
504
			}
505
		}
506
		return title.toString();
507
	}
508

    
509
	/**
510
	 * @param namedArea
511
	 * @param representation
512
	 * @return
513
	 */
514
	private static String getPreferredAreaLabel(DefinedTermBase<?> namedArea, Representation representation) {
515
		String areaString = null;
516
		if (representation != null){
517
			areaString = representation.getLabel();
518
			if (areaString == null){
519
				areaString = representation.getAbbreviatedLabel();
520
			}
521
			if (areaString == null){
522
				areaString = representation.getText();
523
			}
524
		}
525
		if (areaString == null){
526
			areaString = namedArea.getTitleCache();
527
		}
528
		if (areaString == null){
529
			areaString = "no title";
530
		}
531
		return areaString;
532
	}
533
	
534
	//*********************************** CLONE *****************************************/
535

    
536
	/** 
537
	 * Clones <i>this</i> NamedArea. This is a shortcut that enables to create
538
	 * a new instance that differs only slightly from <i>this</i> NamedArea by
539
	 * modifying only some of the attributes.
540
	 * 
541
	 * @see eu.etaxonomy.cdm.model.common.OrderedTermBase#clone()
542
	 * @see java.lang.Object#clone()
543
	 */
544
	@Override
545
	public Object clone() {
546
		NamedArea result;
547
		
548
			result = (NamedArea)super.clone();
549
			//no changes to level, pointApproximation, shape, type, validPeriod and waterbodiesOrCountries
550
			return result;
551
		
552
	}
553
		
554
	
555
}
(2-2/10)