2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.model
.location
;
13 import java
.util
.ArrayList
;
14 import java
.util
.HashMap
;
15 import java
.util
.HashSet
;
16 import java
.util
.List
;
19 import java
.util
.UUID
;
21 import javax
.persistence
.Entity
;
22 import javax
.persistence
.FetchType
;
23 import javax
.persistence
.JoinColumn
;
24 import javax
.persistence
.JoinTable
;
25 import javax
.persistence
.ManyToMany
;
26 import javax
.persistence
.ManyToOne
;
27 import javax
.persistence
.Transient
;
28 import javax
.xml
.bind
.annotation
.XmlAccessType
;
29 import javax
.xml
.bind
.annotation
.XmlAccessorType
;
30 import javax
.xml
.bind
.annotation
.XmlElement
;
31 import javax
.xml
.bind
.annotation
.XmlElementWrapper
;
32 import javax
.xml
.bind
.annotation
.XmlIDREF
;
33 import javax
.xml
.bind
.annotation
.XmlRootElement
;
34 import javax
.xml
.bind
.annotation
.XmlSchemaType
;
35 import javax
.xml
.bind
.annotation
.XmlSeeAlso
;
36 import javax
.xml
.bind
.annotation
.XmlType
;
38 import org
.apache
.commons
.lang
.StringUtils
;
39 import org
.apache
.log4j
.Logger
;
40 import org
.hibernate
.annotations
.Cascade
;
41 import org
.hibernate
.annotations
.CascadeType
;
42 import org
.hibernate
.envers
.Audited
;
43 import org
.hibernate
.search
.annotations
.ClassBridge
;
44 import org
.hibernate
.search
.annotations
.Parameter
;
46 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
47 import eu
.etaxonomy
.cdm
.hibernate
.HibernateProxyHelper
;
48 import eu
.etaxonomy
.cdm
.hibernate
.search
.DefinedTermBaseClassBridge
;
49 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
50 import eu
.etaxonomy
.cdm
.model
.common
.DefaultTermInitializer
;
51 import eu
.etaxonomy
.cdm
.model
.common
.DefinedTermBase
;
52 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
53 import eu
.etaxonomy
.cdm
.model
.common
.OrderedTermBase
;
54 import eu
.etaxonomy
.cdm
.model
.common
.Representation
;
55 import eu
.etaxonomy
.cdm
.model
.common
.TermType
;
56 import eu
.etaxonomy
.cdm
.model
.common
.TermVocabulary
;
57 import eu
.etaxonomy
.cdm
.model
.common
.TimePeriod
;
58 import eu
.etaxonomy
.cdm
.model
.media
.Media
;
62 * @created 08-Nov-2007 13:06:36
64 @XmlAccessorType(XmlAccessType
.PROPERTY
)
65 @XmlType(name
= "NamedArea", propOrder
= {
77 @XmlRootElement(name
= "NamedArea")
82 //@Indexed disabled to reduce clutter in indexes, since this type is not used by any search
83 //@Indexed(index = "eu.etaxonomy.cdm.model.common.DefinedTermBase")
85 @ClassBridge(impl
=DefinedTermBaseClassBridge
.class, params
={
86 @Parameter(name
="includeParentTerms", value
="true")
88 public class NamedArea
extends OrderedTermBase
<NamedArea
> implements Cloneable
{
89 private static final long serialVersionUID
= 6248434369557403036L;
90 private static final Logger logger
= Logger
.getLogger(NamedArea
.class);
94 private static final UUID uuidEurope
= UUID
.fromString("3b69f979-408c-4080-b573-0ad78a315610");
95 private static final UUID uuidAfrica
= UUID
.fromString("c204c529-d8d2-458f-b939-96f0ebd2cbe8");
96 private static final UUID uuidAsiaTemperate
= UUID
.fromString("7f4f4f89-3b4c-475d-929f-144109bd8457");
97 private static final UUID uuidAsiaTropical
= UUID
.fromString("f8039275-d2c0-4753-a1ab-0336642a1499");
98 private static final UUID uuidNAmerica
= UUID
.fromString("81d8aca3-ddd7-4537-9f2b-5327c95b6e28");
99 private static final UUID uuidSAmerica
= UUID
.fromString("12b861c9-c922-498c-8b1a-62afc26d19e3");
100 private static final UUID uuidAustralasia
= UUID
.fromString("a2afdb9a-04a0-434c-9e75-d07dbeb86526");
101 private static final UUID uuidPacific
= UUID
.fromString("c57adcff-5213-45f0-a5f0-97a9f5c0f1fe");
102 private static final UUID uuidAntarctica
= UUID
.fromString("71fd9ab7-9b07-4eb6-8e54-c519aff56728");
105 public static final UUID uuidTdwgAreaVocabulary
= UUID
.fromString("1fb40504-d1d7-44b0-9731-374fbe6cac77");
106 public static final UUID uuidContinentVocabulary
= UUID
.fromString("e72cbcb6-58f8-4201-9774-15d0c6abc128");
107 public static final UUID uuidWaterbodyVocabulary
= UUID
.fromString("35a62b25-f541-4f12-a7c7-17d90dec3e03");
110 private static final UUID uuidArcticOcean
= UUID
.fromString("af4271e5-8897-4e6f-9db7-54ea4f28cfc0");
111 private static final UUID uuidAtlanticOcean
= UUID
.fromString("77e79804-1b17-4c99-873b-933fe216e3da");
112 private static final UUID uuidPacificOcean
= UUID
.fromString("3d68a327-104c-49d5-a2d8-c71c6600181b");
113 private static final UUID uuidIndianOcean
= UUID
.fromString("ff744a37-5990-462c-9c20-1e85a9943851");
114 private static final UUID uuidSouthernOcean
= UUID
.fromString("ef04f363-f67f-4a2c-8d98-110de4c5f654");
115 private static final UUID uuidMediterraneanSea
= UUID
.fromString("8811a47e-29d6-4455-8f83-8916b78a692f");
116 private static final UUID uuidBlackSea
= UUID
.fromString("4cb4bbae-9aab-426c-9025-e34f809165af");
117 private static final UUID uuidCaspianSea
= UUID
.fromString("598fec0e-b93a-4947-a1f3-601e380797f7");
118 private static final UUID uuidRedSea
= UUID
.fromString("ee69385e-6c80-405c-be6e-974e9fd1e297");
119 private static final UUID uuidPersianGulf
= UUID
.fromString("8dc16e70-74b8-4143-95cf-a659a319a854");
123 private static Map
<String
, UUID
> tdwgAbbrevMap
= null;
124 private static Map
<String
, UUID
> tdwglabelMap
= null;
126 private static Map
<UUID
, NamedArea
> tdwgTermMap
= null;
127 private static Map
<UUID
, NamedArea
> continentMap
= null;
128 private static Map
<UUID
, NamedArea
> waterbodyMap
= null;
131 private static Map
<UUID
, NamedArea
> termMap
= null;
133 public static final NamedArea
ARCTICOCEAN () { return waterbodyMap
.get(uuidArcticOcean
);}
134 public static final NamedArea
ATLANTICOCEAN () { return waterbodyMap
.get(uuidAtlanticOcean
);}
135 public static final NamedArea
PACIFICOCEAN () { return waterbodyMap
.get(uuidPacificOcean
);}
136 public static final NamedArea
INDIANOCEAN () { return waterbodyMap
.get(uuidIndianOcean
);}
137 public static final NamedArea
SOUTHERNOCEAN () { return waterbodyMap
.get(uuidSouthernOcean
);}
138 public static final NamedArea
MEDITERRANEANSEA () { return waterbodyMap
.get(uuidMediterraneanSea
);}
139 public static final NamedArea
BLACKSEA () { return waterbodyMap
.get(uuidBlackSea
);}
140 public static final NamedArea
CASPIANSEA () { return waterbodyMap
.get(uuidCaspianSea
);}
141 public static final NamedArea
REDSEA () { return waterbodyMap
.get(uuidRedSea
);}
142 public static final NamedArea
PERSIANGULF () { return waterbodyMap
.get(uuidPersianGulf
);}
145 //************************* FACTORY METHODS ****************************************/
151 public static NamedArea
NewInstance(){
152 return new NamedArea();
159 public static NamedArea
NewInstance(String term
, String label
, String labelAbbrev
){
160 return new NamedArea(term
, label
, labelAbbrev
);
163 //**************************** VARIABLES *******************************/
165 //description of time valid context of this area. e.g. year range
166 private TimePeriod validPeriod
= TimePeriod
.NewInstance();
168 //Binary shape definition for user's defined area as polygon
169 @ManyToOne(fetch
= FetchType
.LAZY
)
170 @Cascade({CascadeType
.SAVE_UPDATE
,CascadeType
.MERGE
})
173 private Point pointApproximation
;
175 @ManyToMany(fetch
= FetchType
.LAZY
)
178 name
="DefinedTermBase_Country",
179 joinColumns
= @JoinColumn( name
="DefinedTermBase_id")
181 private final Set
<Country
> countries
= new HashSet
<Country
>();
183 @ManyToOne(fetch
= FetchType
.LAZY
)
184 private NamedAreaType type
;
186 @ManyToOne(fetch
= FetchType
.LAZY
)
187 private NamedAreaLevel level
;
190 //********************************** Constructor *******************************************************************/
192 //for hibernate use only
194 protected NamedArea() {
195 super(TermType
.NamedArea
);
198 protected NamedArea(String term
, String label
, String labelAbbrev
) {
199 super(TermType
.NamedArea
, term
, label
, labelAbbrev
);
202 //********************************* GETTER /SETTER *********************************************/
204 @XmlElement(name
= "NamedAreaType")
206 @XmlSchemaType(name
= "IDREF")
207 public NamedAreaType
getType(){
211 public void setType(NamedAreaType type
){
215 @XmlElement(name
= "NamedAreaLevel")
217 @XmlSchemaType(name
= "IDREF")
218 public NamedAreaLevel
getLevel(){
222 public void setLevel(NamedAreaLevel level
){
226 @XmlElement(name
= "ValidPeriod")
227 public TimePeriod
getValidPeriod(){
228 return this.validPeriod
;
231 public void setValidPeriod(TimePeriod validPeriod
){
232 this.validPeriod
= validPeriod
;
235 @XmlElement(name
= "Shape")
237 @XmlSchemaType(name
= "IDREF")
238 public Media
getShape(){
241 public void setShape(Media shape
){
245 @XmlElementWrapper(name
= "Countries")
246 @XmlElement(name
= "Country")
248 @XmlSchemaType(name
= "IDREF")
249 public Set
<Country
> getCountries() {
253 public void addCountry(Country country
) {
254 this.countries
.add(country
);
257 public void removeCountry(Country country
) {
258 this.countries
.remove(country
);
261 @XmlElement(name
= "PointApproximation")
262 public Point
getPointApproximation() {
263 return pointApproximation
;
265 public void setPointApproximation(Point pointApproximation
) {
266 this.pointApproximation
= pointApproximation
;
270 @XmlElement(name
= "KindOf", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
272 @XmlSchemaType(name
= "IDREF")
273 public NamedArea
getKindOf(){
274 return super.getKindOf();
278 public void setKindOf(NamedArea kindOf
){
279 super.setKindOf(kindOf
);
282 @XmlElement(name
= "PartOf", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
284 @XmlSchemaType(name
= "IDREF")
286 public NamedArea
getPartOf(){
287 return super.getPartOf();
291 * FIXME this method is a workaround for a casting problem in the getPartOf implementation
293 * the partOf instance variable is typically a proxy object of type DefinedTermBase, thus
294 * does not coincide with the return value of NamedArea and a ClassCastException is thrown.
296 * It is not clear why this only occurs in the editor and not in the webservice where the same
297 * method gets called and should lead to the same results.
299 * Seems to be a bigger problem although its origin is buggy behaviour of the javassist implementation.
303 public NamedArea
getPartOfWorkaround(){
304 Object area
= super.getPartOf();
306 if(!(area
instanceof NamedArea
)){
307 area
= HibernateProxyHelper
.deproxy(area
, NamedArea
.class);
310 return (NamedArea
) area
;
314 public void setPartOf(NamedArea partOf
){
315 this.partOf
= partOf
;
319 @XmlElementWrapper(name
= "Generalizations", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
320 @XmlElement(name
= "GeneralizationOf", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
322 @XmlSchemaType(name
= "IDREF")
323 public Set
<NamedArea
> getGeneralizationOf(){
324 return super.getGeneralizationOf();
328 protected void setGeneralizationOf(Set
<NamedArea
> value
){
329 super.setGeneralizationOf(value
);
333 @XmlElementWrapper(name
= "Includes", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
334 @XmlElement(name
= "Include", namespace
= "http://etaxonomy.eu/cdm/model/common/1.0")
336 @XmlSchemaType(name
= "IDREF")
337 public Set
<NamedArea
> getIncludes(){
338 return super.getIncludes();
342 protected void setIncludes(Set
<NamedArea
> includes
) {
343 super.setIncludes(includes
);
347 public NamedArea
readCsvLine(Class
<NamedArea
> termClass
, List
<String
> csvLine
, Map
<UUID
,DefinedTermBase
> terms
, boolean abbrevAsId
) {
348 NamedArea newInstance
= super.readCsvLine(termClass
, csvLine
, terms
, abbrevAsId
);
350 String levelString
= csvLine
.get(6);
352 if(levelString
!= null && levelString
.length() != 0) {
353 UUID levelUuid
= UUID
.fromString(levelString
);
354 NamedAreaLevel level
= (NamedAreaLevel
)terms
.get(levelUuid
);
355 newInstance
.setLevel(level
);
358 // String partOfString = csvLine.get(7);
360 // if(partOfString != null && partOfString.length() != 0) {
361 // UUID partOfUuid = UUID.fromString(partOfString);
362 // NamedArea partOf = (NamedArea)terms.get(partOfUuid);
363 // partOf.addIncludes(newInstance);
369 protected int partOfCsvLineIndex(){
375 public void resetTerms(){
377 tdwgAbbrevMap
= null;
384 @Deprecated //preliminary, will be removed in future
385 protected static NamedArea
getContinentByUuid(UUID uuid
){
386 if (continentMap
== null){
389 return continentMap
.get(uuid
);
393 @Deprecated //preliminary, will be removed in future
394 protected static NamedArea
getWaterbodyByUuid(UUID uuid
){
395 if (waterbodyMap
== null){
398 return waterbodyMap
.get(uuid
);
402 @Deprecated //preliminary, will be removed in future
403 protected static NamedArea
getTdwgTermByUuid(UUID uuid
){
404 if (tdwgTermMap
== null){
405 DefaultTermInitializer vocabularyStore
= new DefaultTermInitializer();
406 vocabularyStore
.initialize();
408 return tdwgTermMap
.get(uuid
);
411 @Deprecated //preliminary, will be removed in future
412 public static NamedArea
getAreaByTdwgAbbreviation(String tdwgAbbreviation
){
413 if (tdwgAbbrevMap
== null){
416 UUID uuid
= tdwgAbbrevMap
.get(tdwgAbbreviation
);
418 logger
.info("Unknown TDWG area: " + CdmUtils
.Nz(tdwgAbbreviation
));
421 return NamedArea
.getTdwgTermByUuid(uuid
);
424 @Deprecated //preliminary, will be removed in future
425 public static NamedArea
getAreaByTdwgLabel(String tdwgLabel
){
426 if (tdwglabelMap
== null){
429 tdwgLabel
= tdwgLabel
.toLowerCase();
430 UUID uuid
= tdwglabelMap
.get(tdwgLabel
);
432 logger
.info("Unknown TDWG area: " + CdmUtils
.Nz(tdwgLabel
));
435 return NamedArea
.getTdwgTermByUuid(uuid
);
438 @Deprecated //preliminary, will be removed in future
439 public static boolean isTdwgAreaLabel(String label
){
440 label
= (label
== null?
null : label
.toLowerCase());
441 if (tdwglabelMap
.containsKey(label
)){
448 @Deprecated //preliminary, will be removed in future
449 public static boolean isTdwgAreaAbbreviation(String abbrev
){
450 if (tdwgAbbrevMap
.containsKey(abbrev
)){
457 public static final NamedArea
EUROPE(){
458 return getContinentByUuid(uuidEurope
);
461 public static final NamedArea
AFRICA(){
462 return getContinentByUuid(uuidAfrica
);
465 public static final NamedArea
ASIA_TEMPERATE(){
466 return getContinentByUuid(uuidAsiaTemperate
);
469 public static final NamedArea
ASIA_TROPICAL(){
470 return getContinentByUuid(uuidAsiaTropical
);
473 public static final NamedArea
NORTH_AMERICA(){
474 return getContinentByUuid(uuidNAmerica
);
477 public static final NamedArea
ANTARCTICA(){
478 return getContinentByUuid(uuidAntarctica
);
481 public static final NamedArea
SOUTH_AMERICA(){
482 return getContinentByUuid(uuidSAmerica
);
485 public static final NamedArea
AUSTRALASIA(){
486 return getContinentByUuid(uuidAustralasia
);
489 public static final NamedArea
PACIFIC(){
490 return getContinentByUuid(uuidPacific
);
494 protected void setDefaultContinentTerms(TermVocabulary
<NamedArea
> termVocabulary
) {
495 continentMap
= new HashMap
<UUID
, NamedArea
>();
496 for (NamedArea term
: termVocabulary
.getTerms()){
497 continentMap
.put(term
.getUuid(), term
); //TODO casting
501 protected void setDefaultWaterbodyTerms(TermVocabulary
<NamedArea
> termVocabulary
) {
502 waterbodyMap
= new HashMap
<UUID
, NamedArea
>();
503 for (NamedArea term
: termVocabulary
.getTerms()){
504 waterbodyMap
.put(term
.getUuid(), term
); //TODO casting
508 protected void setTdwgDefaultTerms(TermVocabulary
<NamedArea
> tdwgTermVocabulary
) {
509 tdwgTermMap
= new HashMap
<UUID
, NamedArea
>();
510 for (NamedArea term
: tdwgTermVocabulary
.getTerms()){
511 tdwgTermMap
.put(term
.getUuid(), term
); //TODO casting
517 protected static void addTdwgArea(NamedArea area
){
519 logger
.warn("tdwg area is null");
522 Language lang
= Language
.DEFAULT();
523 Representation representation
= area
.getRepresentation(lang
);
524 String tdwgAbbrevLabel
= representation
.getAbbreviatedLabel();
525 String tdwgLabel
= representation
.getLabel().toLowerCase();
526 if (tdwgAbbrevLabel
== null){
527 logger
.warn("tdwgLabel = null");
531 if (tdwgAbbrevMap
== null){
532 tdwgAbbrevMap
= new HashMap
<String
, UUID
>();
534 if (tdwglabelMap
== null){
535 tdwglabelMap
= new HashMap
<String
, UUID
>();
538 tdwgAbbrevMap
.put(tdwgAbbrevLabel
, area
.getUuid());
539 tdwglabelMap
.put(tdwgLabel
, area
.getUuid());
541 area
.setType(NamedAreaType
.ADMINISTRATION_AREA());
543 if (tdwgAbbrevLabel
.trim().length()== 1){
544 area
.setLevel(NamedAreaLevel
.TDWG_LEVEL1());
545 }else if (tdwgAbbrevLabel
.trim().length()== 2){
546 area
.setLevel(NamedAreaLevel
.TDWG_LEVEL2());
547 }else if (tdwgAbbrevLabel
.trim().length()== 3){
548 area
.setLevel(NamedAreaLevel
.TDWG_LEVEL3());
549 }else if (tdwgAbbrevLabel
.trim().length()== 6){
550 area
.setLevel(NamedAreaLevel
.TDWG_LEVEL4());
552 logger
.warn("Unknown TDWG Level " + tdwgAbbrevLabel
+ "! Unvalid string length (" + tdwgAbbrevLabel
.length() +")");
556 private static void initTdwgMaps(){
557 tdwglabelMap
= new HashMap
<String
, UUID
>();
558 tdwgAbbrevMap
= new HashMap
<String
, UUID
>();
564 protected void setDefaultTerms(TermVocabulary
<NamedArea
> termVocabulary
) {
565 if (termVocabulary
.getUuid().equals(NamedArea
.uuidTdwgAreaVocabulary
)){
566 this.setTdwgDefaultTerms(termVocabulary
);
567 }else if (termVocabulary
.getUuid().equals(NamedArea
.uuidContinentVocabulary
)){
568 this.setDefaultContinentTerms(termVocabulary
);
569 }else if (termVocabulary
.getUuid().equals(NamedArea
.uuidWaterbodyVocabulary
)){
570 this.setDefaultWaterbodyTerms(termVocabulary
);
572 termMap
= new HashMap
<UUID
, NamedArea
>();
573 for (NamedArea term
: termVocabulary
.getTerms()){
574 termMap
.put(term
.getUuid(), term
);
579 // ************** Hierarchie List ****************************
582 * This method returns a sorted tree structure which sorts areas by it's level and within the same level
583 * alphabetically (TODO to be tested).
584 * The structure returned is a tree with alternating nodes that represent an area and an areaLevel.
585 * This way also areas that have children belonging to different levels can be handled.<BR>
586 * The root node is always an empty area node which holds the list of top level areaLevels.
587 * AreaLevels with no level defined are handled as if they have a separate level (level="null").
589 * There is a somehow similar implementation in {@link eu.etaxonomy.cdm.api.service.DistributionTree}
594 public static NamedAreaNode
getHiearchieList(List
<NamedArea
> areaList
){
595 NamedAreaNode result
= new NamedAreaNode();
596 for (NamedArea area
: areaList
){
597 List
<NamedArea
> areaHierarchie
= area
.getAllLevelList();
598 mergeIntoResult(result
, areaHierarchie
);
604 public static class LevelNode
{
605 NamedAreaLevel level
;
606 List
<NamedAreaNode
> areaList
= new ArrayList
<NamedAreaNode
>();
608 public NamedAreaNode
add(NamedArea area
) {
609 NamedAreaNode node
= new NamedAreaNode();
616 public NamedAreaNode
getNamedAreaNode(NamedArea area
) {
617 for (NamedAreaNode node
: areaList
) {
618 if (node
.area
.equals(area
)) {
625 ///****************** toString ***********************************************/
628 public String
toString() {
629 return toString(false, 0);
631 public String
toString(boolean recursive
, int identation
) {
632 String result
= level
== null?
"" :level
.getTitleCache();
633 if (recursive
== false){
636 int areaSize
= this.areaList
.size();
638 result
= "\n" + StringUtils
.leftPad("", identation
) + result
+ "[";
640 boolean isFirst
= true;
641 for (NamedAreaNode level
: this.areaList
){
647 result
+= level
.toString(recursive
, identation
+1);
659 public static class NamedAreaNode
{
661 List
<LevelNode
> levelList
= new ArrayList
<LevelNode
>();
663 public LevelNode
getLevelNode(NamedAreaLevel level
) {
664 for (LevelNode node
: levelList
) {
665 if (node
.level
!= null && node
.level
.equals(level
)) {
672 public List
<NamedAreaNode
> getList(NamedAreaLevel level
) {
673 LevelNode node
= getLevelNode(level
);
675 return new ArrayList
<NamedAreaNode
>();
677 return node
.areaList
;
681 public boolean contains(NamedAreaLevel level
) {
682 if (getList(level
).size() > 0) {
689 public LevelNode
add(NamedAreaLevel level
) {
690 LevelNode node
= new LevelNode();
697 public String
toString() {
698 return toString(false, 0);
701 public String
toString(boolean recursive
, int identation
) {
704 result
= area
.getTitleCache();
707 int levelSize
= this.levelList
.size();
709 result
= "\n" + StringUtils
.leftPad("", identation
) + result
+ "[";
711 boolean isFirst
= true;
712 for (LevelNode level
: this.levelList
){
718 result
+= level
.toString(recursive
, identation
+1);
726 int levelSize
= this.levelList
.size();
727 return result
+ "[" + levelSize
+ " sublevel(s)]";
732 private static void mergeIntoResult(NamedAreaNode root
, List
<NamedArea
> areaHierarchie
) {
733 if (areaHierarchie
.isEmpty()) {
736 NamedArea highestArea
= areaHierarchie
.get(0);
737 NamedAreaLevel level
= highestArea
.getLevel();
738 NamedAreaNode namedAreaNode
;
739 if (! root
.contains(level
)) {
740 LevelNode node
= root
.add(level
);
741 namedAreaNode
= node
.add(highestArea
);
743 // root.area = highestArea;
745 LevelNode levelNode
= root
.getLevelNode(level
);
746 namedAreaNode
= levelNode
.getNamedAreaNode(highestArea
);
747 if (namedAreaNode
== null) {
748 namedAreaNode
= levelNode
.add(highestArea
);
751 List
<NamedArea
> newList
= areaHierarchie
.subList(1, areaHierarchie
.size());
752 mergeIntoResult(namedAreaNode
, newList
);
757 public List
<NamedArea
> getAllLevelList() {
758 List
<NamedArea
> result
= new ArrayList
<NamedArea
>();
759 NamedArea copyArea
= this;
760 result
.add(copyArea
);
761 while (copyArea
.getPartOf() != null) {
762 copyArea
= copyArea
.getPartOf();
763 result
.add(0, copyArea
);
768 // ******************* toString **********************************/
771 public String
toString(){
772 String result
, label
, IdInVocabulary
, level
= "";
774 if (this.level
!= null){
775 level
= this.level
.getLabel();
779 label
= this.getLabel();
780 IdInVocabulary
= getIdInVocabulary();
781 IdInVocabulary
= IdInVocabulary
!= null ?
'<' + IdInVocabulary
+ '>' : "";
782 result
= "[" + level
+ ", " + IdInVocabulary
+ label
+ "]";
790 * Returns the label of the named area together with the area level label and the abbreviated label.
791 * This is kind of a formatter method which may be moved to a better place in future.
792 * @param namedArea the area
793 * @param language the preferred language
794 * @return null if namedArea == null, the labelWithLevel otherwise
796 public static String
labelWithLevel(NamedArea namedArea
, Language language
) {
797 if (namedArea
== null){
800 NamedArea area
= CdmBase
.deproxy(namedArea
, NamedArea
.class);
802 StringBuilder title
= new StringBuilder();
803 Representation representation
= area
.getPreferredRepresentation(language
);
804 if (representation
!= null){
805 String areaString
= getPreferredAreaLabel(namedArea
, representation
);
807 title
.append(areaString
);
808 }else if (area
.isProtectedTitleCache()){
809 title
.append(area
.getTitleCache());
810 }else if (StringUtils
.isNotBlank(area
.getIdInVocabulary())){
811 title
.append(area
.getIdInVocabulary());
813 if (area
.getLevel() == null){
815 title
.append(area
.getClass().getSimpleName());
818 Representation levelRepresentation
= area
.getLevel().getPreferredRepresentation(language
);
819 String levelString
= getPreferredAreaLabel(area
.getLevel(), levelRepresentation
);
820 title
.append(levelString
);
822 return title
.toString();
827 * @param representation
830 private static String
getPreferredAreaLabel(DefinedTermBase
<?
> definedTerm
, Representation representation
) {
831 String areaString
= null;
832 if (representation
!= null){
833 areaString
= representation
.getLabel();
834 if (StringUtils
.isBlank(areaString
)){
835 areaString
= representation
.getAbbreviatedLabel();
837 if (StringUtils
.isBlank(areaString
)){
838 areaString
= representation
.getText();
841 if (StringUtils
.isBlank(areaString
)){
842 areaString
= definedTerm
== null ?
null : definedTerm
.getTitleCache();
844 if (StringUtils
.isBlank(areaString
)){
845 areaString
= "no title";
850 //*********************************** CLONE *****************************************/
853 * Clones <i>this</i> NamedArea. This is a shortcut that enables to create
854 * a new instance that differs only slightly from <i>this</i> NamedArea by
855 * modifying only some of the attributes.
857 * @see eu.etaxonomy.cdm.model.common.OrderedTermBase#clone()
858 * @see java.lang.Object#clone()
861 public Object
clone() {
864 result
= (NamedArea
)super.clone();
865 //no changes to level, pointApproximation, shape, type, validPeriod and countries