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
.taxeditor
.model
;
12 import java
.util
.ArrayList
;
13 import java
.util
.HashSet
;
14 import java
.util
.List
;
17 import org
.apache
.log4j
.Logger
;
18 import org
.eclipse
.jface
.dialogs
.MessageDialog
;
20 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationController
;
21 import eu
.etaxonomy
.cdm
.api
.service
.INameService
;
22 import eu
.etaxonomy
.cdm
.api
.service
.IReferenceService
;
23 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonService
;
24 import eu
.etaxonomy
.cdm
.api
.service
.config
.ITaxonServiceConfigurator
;
25 import eu
.etaxonomy
.cdm
.api
.service
.config
.impl
.TaxonServiceConfiguratorImpl
;
26 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
27 import eu
.etaxonomy
.cdm
.model
.common
.IdentifiableEntity
;
28 import eu
.etaxonomy
.cdm
.model
.common
.TimePeriod
;
29 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
30 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationship
;
31 import eu
.etaxonomy
.cdm
.model
.name
.NameRelationshipType
;
32 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
33 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
34 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
35 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
36 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
37 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
38 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
39 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
40 import eu
.etaxonomy
.taxeditor
.TaxEditorPlugin
;
41 import eu
.etaxonomy
.taxeditor
.controller
.GlobalController
;
42 import eu
.etaxonomy
.taxeditor
.navigation
.SearchResult
;
49 public class CdmUtil
{
50 private static final Logger logger
= Logger
.getLogger(CdmUtil
.class);
53 * Checks whether synonym's name is the basionym for ALL names
60 public static boolean isSynonymGroupBasionym(Synonym synonym
) {
62 TaxonNameBase synonymName
= synonym
.getName();
63 return isNameGroupBasionym(synonymName
);
67 * Checks whether name is the basionym for ALL names
73 public static boolean isNameGroupBasionym(TaxonNameBase name
) {
78 HomotypicalGroup homotypicalGroup
= name
.getHomotypicalGroup();
79 if (homotypicalGroup
== null) {
83 Set
<TaxonNameBase
> typifiedNames
= homotypicalGroup
.getTypifiedNames();
85 // Check whether there are any other names in the group
86 if (typifiedNames
.size() == 1) {
90 boolean isBasionymToAll
= true;
92 for (TaxonNameBase taxonName
: typifiedNames
) {
93 if (!taxonName
.equals(name
)) {
94 if (!isNameBasionymOf(name
, taxonName
)) {
103 * Checks whether a basionym relationship exists between fromName and toName.
109 public static boolean isNameBasionymOf(TaxonNameBase fromName
, TaxonNameBase toName
) {
110 Set
<NameRelationship
> relations
= toName
.getRelationsToThisName();
111 for (NameRelationship relation
: relations
) {
112 if (relation
.getType().equals(NameRelationshipType
.BASIONYM()) &&
113 relation
.getFromName().equals(fromName
)) {
121 * Creates a basionym relationship between basionymName and
122 * each name in its homotypic group.
124 * @param basionymName
126 public static void setGroupBasionym(TaxonNameBase basionymName
) {
127 HomotypicalGroup homotypicalGroup
= basionymName
.getHomotypicalGroup();
128 if (homotypicalGroup
== null) {
131 for (TaxonNameBase name
: homotypicalGroup
.getTypifiedNames()) {
132 if (!name
.equals(basionymName
)) {
134 // First check whether the relationship already exists
135 if (!isNameBasionymOf(basionymName
, name
)) {
138 name
.addRelationshipFromName(basionymName
,
139 NameRelationshipType
.BASIONYM(), null);
146 * Removes all basionym relationships between basionymName and
147 * the names in its homotypic group.
149 * @param basionymName
151 public static void removeGroupBasionym(TaxonNameBase basionymName
) {
152 HomotypicalGroup homotypicalGroup
= basionymName
.getHomotypicalGroup();
153 Set
<NameRelationship
> relations
= basionymName
.getRelationsFromThisName();
154 Set
<NameRelationship
> removeRelations
= new HashSet
<NameRelationship
>();
156 for (NameRelationship relation
: relations
) {
158 // If this is a basionym relation, and toName is in the homotypical group,
159 // remove the relationship.
160 if (relation
.getType().equals(NameRelationshipType
.BASIONYM()) &&
161 relation
.getToName().getHomotypicalGroup().equals(homotypicalGroup
)) {
162 removeRelations
.add(relation
);
166 // Removing relations from a set through which we are iterating causes a
167 // ConcurrentModificationException. Therefore, we delete the targeted
168 // relations in a second step.
169 for (NameRelationship relation
: removeRelations
) {
170 basionymName
.removeNameRelationship(relation
);
175 * Checks whether name belongs to the same homotypic group as taxon's name.
181 public static boolean isNameHomotypic(TaxonNameBase name
, Taxon taxon
) {
182 TaxonNameBase taxonName
= taxon
.getName();
183 if (taxonName
== null || name
== null) {
186 HomotypicalGroup homotypicGroup
= taxonName
.getHomotypicalGroup();
187 if (homotypicGroup
== null) {
190 if (homotypicGroup
.equals(name
.getHomotypicalGroup())) {
197 * Returns whatever is currently considered the display name for Taxon
198 * objects. Currently titleCache.
203 public static String
getDisplayName(TaxonBase taxonBase
) {
204 TaxonNameBase name
= taxonBase
.getName();
205 return getDisplayName(name
);
212 public static String
getDisplayName(TaxonNameBase name
) {
214 return name
.getTitleCache().replace("&", "&&");
219 public static String
getDisplayNameWithRef(TaxonBase taxonBase
) {
220 TaxonNameBase name
= taxonBase
.getName();
222 if (name
.getFullTitleCache() == null || name
.getFullTitleCache().length() == 0) {
223 return CdmUtils
.Nz(name
.getTitleCache());
225 return name
.getFullTitleCache();
233 * @param newAcceptedTaxon
236 * @param citationMicroReference
238 public static void makeTaxonSynonym(Taxon oldTaxon
, Taxon newAcceptedTaxon
,
239 SynonymRelationshipType synonymType
, ReferenceBase citation
,
240 String citationMicroReference
) {
241 ITaxonService taxonService
= getTaxonService();
242 taxonService
.makeTaxonSynonym(oldTaxon
, newAcceptedTaxon
, synonymType
,
243 citation
, citationMicroReference
);
250 public static List
<TaxonNameBase
> searchNameString(String searchText
) {
251 List
<TaxonNameBase
> resultsSet
= new ArrayList
<TaxonNameBase
>();
252 resultsSet
.addAll(getNameService()
253 .getNamesByName(searchText
.replace("*", "%")));
257 public static SearchResult
searchTaxaByName(String name
) {
258 SearchResult searchResult
= new SearchResult();
260 ITaxonServiceConfigurator configurator
= new TaxonServiceConfiguratorImpl();
262 configurator
.setMatchMode(MatchMode
.ANYWHERE
);
263 configurator
.setSearchString(name
.replace("*", "%"));
264 configurator
.setDoTaxa(true);
265 configurator
.setDoNamesWithoutTaxa(true);
266 configurator
.setDoSynonyms(true);
267 configurator
.setPageNumber(1);
268 // TODO currently limit results to 1000 for now
269 configurator
.setPageSize(1000);
271 List
<IdentifiableEntity
> result
= getTaxonService().findTaxaAndNames(configurator
).getRecords();
273 searchResult
.addAll(result
);
277 private static CdmApplicationController
getApplicationController() {
278 return TaxEditorPlugin
.getDefault().getApplicationController();
281 public static INameService
getNameService() {
282 return getApplicationController().getNameService();
285 public static ITaxonService
getTaxonService() {
286 return getApplicationController().getTaxonService();
289 public static IReferenceService
getReferenceService() {
290 return getApplicationController().getReferenceService();
298 public static Set
<TaxonNameBase
> getNameByNameForTaxonContext(String searchText
, Taxon taxon
) {
299 Set
<TaxonNameBase
> resultsSet
= new HashSet
<TaxonNameBase
>();
300 resultsSet
.addAll(getNameService().getNamesByName
301 (searchText
.replace("*", "%"), taxon
));
306 * Converts a <code>String</code> whose format is either a valid year
307 * or two valid years with the format "XXXX-XXXX" into a TimePeriod.
309 * @see #getValidYear(String yearStr)
312 * @throws NumberFormatException
314 public static TimePeriod
convertTimePeriod(String refYear
) throws NumberFormatException
{
316 if (refYear
== null || ("").equals(refYear
)){
320 TimePeriod datePublished
= TimePeriod
.NewInstance();
322 // In case format is "xxxx-xxxx"
323 String
[] years
= refYear
.split("-");
325 // Unlikely case of "xxxx-xxxx-xxxx..."
326 if (years
.length
> 2) {
327 throw new NumberFormatException();
331 datePublished
.setStartYear(getValidYear(years
[0]));
333 // Format is "xxxx-xxxx"
334 if (years
.length
== 2) {
335 datePublished
.setEndYear(getValidYear(years
[1]));
338 return datePublished
;
343 * Checks whether a <code>String</code> is a valid year between
344 * 1750 and 2030. Throws a <code>NumberFormatException</code> if not.
348 * @throws NumberFormatException
350 public static Integer
getValidYear(String yearStr
) throws NumberFormatException
{
352 Integer yearInt
= null;
354 // Try casting string - don't catch number format exception
356 yearInt
= new Integer(yearStr
);
357 } catch (ClassCastException e
) {
358 throw new NumberFormatException();
361 // Is year in valid range?
362 if (yearInt
< 1750 || yearInt
> 2030) {
363 throw new NumberFormatException();
370 * Searches for references by string. "%" is used as a wildcard.
375 public static List
getReferencesByTitle(String reference
) {
377 reference
= reference
.replace("*", "%");
378 List resultsList
= null;
380 resultsList
= getReferenceService().getReferencesByTitle(reference
);
381 } catch (RuntimeException e
) {
382 MessageDialog
.openError(GlobalController
.getShell(), "Search reference error",
383 "Reference search returned an error. This could be a Hibernate concurrency problem. " +
384 "Please try saving your work, then searching again.");
391 * Returns true if <code>taxon</code> belongs to the children, grandchildren,
392 * etc. of <code>checkTaxon</code>.
398 public static boolean isTaxonChildOfTaxon(Taxon taxon
, Taxon checkTaxon
) {
400 // Traverse all checkTaxon's children
401 for (Taxon childTaxon
: checkTaxon
.getTaxonomicChildren()) {
403 if (childTaxon
.equals(taxon
)) {
407 // Compare taxon with childTaxon's children
408 if (isTaxonChildOfTaxon(taxon
, childTaxon
)) {
420 public static boolean isNameSupraSpecific(TaxonNameBase name
) {
422 if (name
== null || name
.getRank() == null) {
426 if (name
.getRank().isHigher(Rank
.SPECIES())) {
427 // if (name.isInfraGeneric() || name.isSupraGeneric() || name.isGenus()) {