p2izing the editor
[taxeditor.git] / eclipseprojects / eu.etaxonomy.taxeditor / src / eu / etaxonomy / taxeditor / model / CdmUtil.java
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.taxeditor.model;
11
12 import java.util.ArrayList;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Set;
16
17 import org.apache.log4j.Logger;
18 import org.eclipse.jface.dialogs.MessageDialog;
19
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;
43
44 /**
45 * @author p.ciardelli
46 * @created 17.09.2008
47 * @version 1.0
48 */
49 public class CdmUtil {
50 private static final Logger logger = Logger.getLogger(CdmUtil.class);
51
52 /**
53 * Checks whether synonym's name is the basionym for ALL names
54 * in its group.
55 *
56 * @param synonym
57 *
58 * @return
59 */
60 public static boolean isSynonymGroupBasionym(Synonym synonym) {
61
62 TaxonNameBase synonymName = synonym.getName();
63 return isNameGroupBasionym(synonymName);
64 }
65
66 /**
67 * Checks whether name is the basionym for ALL names
68 * in its group.
69 * @param name
70 *
71 * @return
72 */
73 public static boolean isNameGroupBasionym(TaxonNameBase name) {
74 if (name == null) {
75 return false;
76 }
77
78 HomotypicalGroup homotypicalGroup = name.getHomotypicalGroup();
79 if (homotypicalGroup == null) {
80 return false;
81 }
82
83 Set<TaxonNameBase> typifiedNames = homotypicalGroup.getTypifiedNames();
84
85 // Check whether there are any other names in the group
86 if (typifiedNames.size() == 1) {
87 return false;
88 }
89
90 boolean isBasionymToAll = true;
91
92 for (TaxonNameBase taxonName : typifiedNames) {
93 if (!taxonName.equals(name)) {
94 if (!isNameBasionymOf(name, taxonName)) {
95 return false;
96 }
97 }
98 }
99 return true;
100 }
101
102 /**
103 * Checks whether a basionym relationship exists between fromName and toName.
104 *
105 * @param fromName
106 * @param toName
107 * @return
108 */
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)) {
114 return true;
115 }
116 }
117 return false;
118 }
119
120 /**
121 * Creates a basionym relationship between basionymName and
122 * each name in its homotypic group.
123 *
124 * @param basionymName
125 */
126 public static void setGroupBasionym(TaxonNameBase basionymName) {
127 HomotypicalGroup homotypicalGroup = basionymName.getHomotypicalGroup();
128 if (homotypicalGroup == null) {
129 return;
130 }
131 for (TaxonNameBase name : homotypicalGroup.getTypifiedNames()) {
132 if (!name.equals(basionymName)) {
133
134 // First check whether the relationship already exists
135 if (!isNameBasionymOf(basionymName, name)) {
136
137 // Then create it
138 name.addRelationshipFromName(basionymName,
139 NameRelationshipType.BASIONYM(), null);
140 }
141 }
142 }
143 }
144
145 /**
146 * Removes all basionym relationships between basionymName and
147 * the names in its homotypic group.
148 *
149 * @param basionymName
150 */
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>();
155
156 for (NameRelationship relation : relations) {
157
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);
163 }
164 }
165
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);
171 }
172 }
173
174 /**
175 * Checks whether name belongs to the same homotypic group as taxon's name.
176 *
177 * @param name
178 * @param taxon
179 * @return
180 */
181 public static boolean isNameHomotypic(TaxonNameBase name, Taxon taxon) {
182 TaxonNameBase taxonName = taxon.getName();
183 if (taxonName == null || name == null) {
184 return false;
185 }
186 HomotypicalGroup homotypicGroup = taxonName.getHomotypicalGroup();
187 if (homotypicGroup == null) {
188 return false;
189 }
190 if (homotypicGroup.equals(name.getHomotypicalGroup())) {
191 return true;
192 }
193 return false;
194 }
195
196 /**
197 * Returns whatever is currently considered the display name for Taxon
198 * objects. Currently titleCache.
199 *
200 * @param taxon
201 * @return
202 */
203 public static String getDisplayName(TaxonBase taxonBase) {
204 TaxonNameBase name = taxonBase.getName();
205 return getDisplayName(name);
206 }
207
208 /**
209 * @param name
210 * @return
211 */
212 public static String getDisplayName(TaxonNameBase name) {
213 if (name != null) {
214 return name.getTitleCache().replace("&", "&&");
215 }
216 return "";
217 }
218
219 public static String getDisplayNameWithRef(TaxonBase taxonBase) {
220 TaxonNameBase name = taxonBase.getName();
221 if (name != null) {
222 if (name.getFullTitleCache() == null || name.getFullTitleCache().length() == 0) {
223 return CdmUtils.Nz(name.getTitleCache());
224 } else {
225 return name.getFullTitleCache();
226 }
227 }
228 return "";
229 }
230
231 /**
232 * @param oldTaxon
233 * @param newAcceptedTaxon
234 * @param synonymType
235 * @param citation
236 * @param citationMicroReference
237 */
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);
244 }
245
246 /**
247 * @param searchText
248 * @return
249 */
250 public static List<TaxonNameBase> searchNameString(String searchText) {
251 List<TaxonNameBase> resultsSet = new ArrayList<TaxonNameBase>();
252 resultsSet.addAll(getNameService()
253 .getNamesByName(searchText.replace("*", "%")));
254 return resultsSet;
255 }
256
257 public static SearchResult searchTaxaByName(String name) {
258 SearchResult searchResult = new SearchResult();
259
260 ITaxonServiceConfigurator configurator = new TaxonServiceConfiguratorImpl();
261
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);
270
271 List<IdentifiableEntity> result = getTaxonService().findTaxaAndNames(configurator).getRecords();
272
273 searchResult.addAll(result);
274 return searchResult;
275 }
276
277 private static CdmApplicationController getApplicationController() {
278 return TaxEditorPlugin.getDefault().getApplicationController();
279 }
280
281 public static INameService getNameService() {
282 return getApplicationController().getNameService();
283 }
284
285 public static ITaxonService getTaxonService() {
286 return getApplicationController().getTaxonService();
287 }
288
289 public static IReferenceService getReferenceService() {
290 return getApplicationController().getReferenceService();
291 }
292
293 /**
294 * @param searchText
295 * @param taxon
296 * @return
297 */
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));
302 return resultsSet;
303 }
304
305 /**
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.
308 *
309 * @see #getValidYear(String yearStr)
310 * @param refYear
311 * @return
312 * @throws NumberFormatException
313 */
314 public static TimePeriod convertTimePeriod(String refYear) throws NumberFormatException {
315
316 if (refYear == null || ("").equals(refYear)){
317 return null;
318 }
319
320 TimePeriod datePublished = TimePeriod.NewInstance();
321
322 // In case format is "xxxx-xxxx"
323 String[] years = refYear.split("-");
324
325 // Unlikely case of "xxxx-xxxx-xxxx..."
326 if (years.length > 2) {
327 throw new NumberFormatException();
328 }
329
330 // Set startYear
331 datePublished.setStartYear(getValidYear(years[0]));
332
333 // Format is "xxxx-xxxx"
334 if (years.length == 2) {
335 datePublished.setEndYear(getValidYear(years[1]));
336 }
337
338 return datePublished;
339 }
340
341
342 /**
343 * Checks whether a <code>String</code> is a valid year between
344 * 1750 and 2030. Throws a <code>NumberFormatException</code> if not.
345 *
346 * @param yearStr
347 * @return
348 * @throws NumberFormatException
349 */
350 public static Integer getValidYear(String yearStr) throws NumberFormatException {
351
352 Integer yearInt = null;
353
354 // Try casting string - don't catch number format exception
355 try {
356 yearInt = new Integer(yearStr);
357 } catch (ClassCastException e) {
358 throw new NumberFormatException();
359 }
360
361 // Is year in valid range?
362 if (yearInt < 1750 || yearInt > 2030) {
363 throw new NumberFormatException();
364 }
365
366 return yearInt;
367 }
368
369 /**
370 * Searches for references by string. "%" is used as a wildcard.
371 *
372 * @param text
373 * @return
374 */
375 public static List getReferencesByTitle(String reference) {
376
377 reference = reference.replace("*", "%");
378 List resultsList = null;
379 try {
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.");
385 e.printStackTrace();
386 }
387 return resultsList;
388 }
389
390 /**
391 * Returns true if <code>taxon</code> belongs to the children, grandchildren,
392 * etc. of <code>checkTaxon</code>.
393 *
394 * @param taxon
395 * @param checkTaxon
396 * @return
397 */
398 public static boolean isTaxonChildOfTaxon(Taxon taxon, Taxon checkTaxon) {
399
400 // Traverse all checkTaxon's children
401 for (Taxon childTaxon : checkTaxon.getTaxonomicChildren()) {
402
403 if (childTaxon.equals(taxon)) {
404 return true;
405 } else {
406
407 // Compare taxon with childTaxon's children
408 if (isTaxonChildOfTaxon(taxon, childTaxon)) {
409 return true;
410 }
411 }
412 }
413 return false;
414 }
415
416 /**
417 * @param name
418 * @return
419 */
420 public static boolean isNameSupraSpecific(TaxonNameBase name) {
421
422 if (name == null || name.getRank() == null) {
423 return false;
424 }
425
426 if (name.getRank().isHigher(Rank.SPECIES())) {
427 // if (name.isInfraGeneric() || name.isSupraGeneric() || name.isGenus()) {
428 return true;
429 } else {
430 return false;
431 }
432 }
433 }