Project

General

Profile

Download (22 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.name;
11

    
12
import java.util.ArrayList;
13
import java.util.Collections;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Set;
17

    
18
import javax.persistence.Entity;
19
import javax.persistence.FetchType;
20
import javax.persistence.OneToMany;
21
import javax.persistence.Transient;
22
import javax.xml.bind.annotation.XmlAccessType;
23
import javax.xml.bind.annotation.XmlAccessorType;
24
import javax.xml.bind.annotation.XmlElement;
25
import javax.xml.bind.annotation.XmlElementWrapper;
26
import javax.xml.bind.annotation.XmlIDREF;
27
import javax.xml.bind.annotation.XmlSchemaType;
28
import javax.xml.bind.annotation.XmlType;
29

    
30
import org.apache.log4j.Logger;
31
import org.hibernate.envers.Audited;
32

    
33
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
34
import eu.etaxonomy.cdm.model.reference.Reference;
35
import eu.etaxonomy.cdm.model.taxon.Synonym;
36
import eu.etaxonomy.cdm.model.taxon.TaxonComparator;
37

    
38

    
39
/**
40
 * The homotypical group class represents a set of {@link TaxonNameBase taxon names} associated
41
 * on the base of their typifications. Since it can be asserted that two taxon
42
 * names are typified by the same type without mentioning the type itself, even
43
 * taxon names without explicit {@link TypeDesignationBase type designation} can belong
44
 * to an homotypical group.<BR>
45
 * Taxon names belonging to an homotypical group and the taxon names or
46
 * {@link eu.etaxonomy.cdm.model.occurrence.DerivedUnitBase specimens} used as types for their
47
 * {@link TypeDesignationBase type designations} have the following properties: <ul>
48
 * <li>	A taxon name belongs exactly to one homotypical group
49
 * <li>	A type specimen or a type name can be used as a type only for taxon
50
 * 		names belonging to the same homotypical group<BR>
51
 * 		- therefore an homotypical group circumscribes a set of types<BR>
52
 * 		- each taxon name shares a subset of these types<BR>
53
 * 		- each type is used by a subset of these taxon names
54
 * 			within the homotypical group
55
 * <li>	Names that share at least one common type must belong to the same
56
 * 		homotypical group
57
 * <li>	Names that share the same basionym or replaced synonym must belong to
58
 * 		the same homotypical group
59
 * </ul>
60
 * 
61
 * @see		TypeDesignationBase
62
 * @see		NameTypeDesignation
63
 * @see		SpecimenTypeDesignation
64
 * @author  m.doering
65
 * @version 1.0
66
 * @created 08-Nov-2007
67
 */
68
@XmlAccessorType(XmlAccessType.FIELD)
69
@XmlType(name = "HomotypicalGroup", propOrder = {
70
    "typifiedNames"
71
})
72
@Entity
73
@Audited
74
public class HomotypicalGroup extends AnnotatableEntity {
75
	private static final Logger logger = Logger.getLogger(HomotypicalGroup.class);
76

    
77
	@XmlElementWrapper(name = "TypifiedNames")
78
	@XmlElement(name = "TypifiedName")
79
	@XmlIDREF
80
	@XmlSchemaType(name = "IDREF")
81
	@OneToMany(mappedBy="homotypicalGroup", fetch=FetchType.LAZY)
82
	protected Set<TaxonNameBase> typifiedNames = new HashSet<TaxonNameBase>();
83

    
84
// ******************** static methods **************************************/
85
	/** 
86
	 * Creates a new homotypical group instance with an empty set of typified
87
	 * {@link TaxonNameBase taxon names}.
88
	 * 
89
	 * @see #HomotypicalGroup()
90
	 */
91
	public static HomotypicalGroup NewInstance(){
92
		return new HomotypicalGroup();
93
	}
94
	
95
	
96
//********************** CONSTRUCTOR ********************************************/
97
	
98
	/** 
99
	 * Class constructor: creates a new homotypical group instance with an
100
	 * empty set of typified {@link TaxonNameBase taxon names}.
101
	 */
102
	public HomotypicalGroup() {
103
		super();
104
	}
105

    
106
// ********************** GETTER/SETTER/ADDER/REMOVER ********************************/
107
		
108
	/** 
109
	 * Returns the set of {@link TaxonNameBase taxon names} that belong to <i>this</i> homotypical group.
110
	 *
111
	 * @see	#getSpecimenTypeDesignations()
112
	 */
113
	public Set<TaxonNameBase> getTypifiedNames() {
114
		return typifiedNames;
115
	}
116
	
117
	/** 
118
	 * Adds a new {@link TaxonNameBase taxon name} to the set of taxon names that belong
119
	 * to <i>this</i> homotypical group.
120
	 *
121
	 * @param  typifiedName  the taxon name to be added to <i>this</i> group
122
	 * @see 			  	 #getTypifiedNames()
123
	 * @see 			  	 #removeTypifiedName(TaxonNameBase)
124
	 */
125
	public void addTypifiedName(TaxonNameBase typifiedName) {
126
		if (typifiedName != null){
127
			typifiedNames.add(typifiedName);
128
			typifiedName.setHomotypicalGroup(this);
129
		}
130
	}
131
	/** 
132
	 * Removes one element from the set of {@link TaxonNameBase taxon names}
133
	 * that belong to <i>this</i> homotypical group.
134
	 *
135
	 * @param  taxonBase	the taxon name which should be removed from the corresponding set
136
	 * @see    				#addTypifiedName(TaxonNameBase)
137
	 */
138
	public void removeTypifiedName(TaxonNameBase typifiedName) {
139
		HomotypicalGroup newHomotypicalGroup = HomotypicalGroup.NewInstance();
140
		typifiedName.setHomotypicalGroup(newHomotypicalGroup);
141
		typifiedNames.remove(typifiedName);	
142
	}
143

    
144
	/**
145
	 * Merges the typified {@link TaxonNameBase taxon names} from one homotypical group into
146
	 * the set of typified taxon names of <i>this</i> homotypical group.
147
	 *  
148
	 * @param	homotypicalGroupToMerge the homotypical group the typified names of which
149
	 * 									are to be transferred to <i>this</i> homotypical group
150
	 */
151
	public void merge(HomotypicalGroup homotypicalGroupToMerge){
152
		if (homotypicalGroupToMerge != null){
153
			Set<TaxonNameBase> typifiedNames = new HashSet<TaxonNameBase>();
154
			typifiedNames.addAll(homotypicalGroupToMerge.getTypifiedNames());
155
			for (TaxonNameBase typifiedName: typifiedNames){
156
				this.addTypifiedName(typifiedName);
157
			}
158
		}
159
	}
160
	
161
	
162
	/** 
163
	 * Returns the set of {@link SpecimenTypeDesignation specimen type designations} that
164
	 * typify the {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group
165
	 * including the status of these designations.
166
	 *
167
	 * @see	#getTypifiedNames()
168
	 * @see	#getNameTypeDesignations()
169
	 * @see	#getTypeDesignations()
170
	 * @see	TaxonNameBase#getSpecimenTypeDesignations()
171
	 */
172
	@Transient
173
	public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations(){
174
		Set<SpecimenTypeDesignation> result = new HashSet<SpecimenTypeDesignation>();
175
		for (TaxonNameBase taxonName : typifiedNames){
176
			result.addAll(taxonName.getSpecimenTypeDesignations());
177
		}
178
		return result;
179
	}
180
	
181
	/** 
182
	 * Returns the set of {@link NameTypeDesignation name type designations} that
183
	 * typify the {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group
184
	 * including the status of these designations.
185
	 *
186
	 * @see	#getTypifiedNames()
187
	 * @see	#getSpecimenTypeDesignations()
188
	 * @see	#getTypeDesignations()
189
	 * @see	TaxonNameBase#getNameTypeDesignations()
190
	 */
191
	@Transient
192
	public Set<NameTypeDesignation> getNameTypeDesignations(){
193
		Set<NameTypeDesignation> result = new HashSet<NameTypeDesignation>();
194
		for (TaxonNameBase taxonName : typifiedNames){
195
			result.addAll(taxonName.getNameTypeDesignations());
196
		}
197
		return result;
198
	}
199
	
200
	
201
	/** 
202
	 * Returns the set of all {@link TypeDesignationBase type designations} that
203
	 * typify the {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group
204
	 * (this includes either {@link NameTypeDesignation name type designations} or
205
	 * {@link SpecimenTypeDesignation specimen type designations}).
206
	 *
207
	 * @see	#getTypifiedNames()
208
	 * @see	#getNameTypeDesignations()
209
	 * @see	#getSpecimenTypeDesignations()
210
	 * @see	TaxonNameBase#getTypeDesignations()
211
	 */
212
	@Transient
213
	public Set<TypeDesignationBase> getTypeDesignations(){
214
		Set<TypeDesignationBase> result = new HashSet<TypeDesignationBase>();
215
		for (TaxonNameBase taxonName : typifiedNames){
216
			result.addAll(taxonName.getTypeDesignations());
217
		}
218
		return result;
219
	}
220
	
221
//	/** 
222
//	 * Returns the set of {@link SpecimenTypeDesignation specimen type designations} that
223
//	 * typify <i>this</i> homotypical group including the status of these designations.
224
//	 *
225
//	 * @see	#getTypifiedNames()
226
//	 */
227
//	@OneToMany
228
//	@Cascade({CascadeType.SAVE_UPDATE})
229
//	public Set<SpecimenTypeDesignation> getSpecimenTypeDesignations() {
230
//		return specimenTypeDesignations;
231
//	}
232
//	/** 
233
//	 * @see #getSpecimenTypeDesignations()
234
//	 */
235
//	protected void setSpecimenTypeDesignations(Set<SpecimenTypeDesignation> specimenTypeDesignations) {
236
//		this.specimenTypeDesignations = specimenTypeDesignations;
237
//	}	
238
//	/** 
239
//	 * Adds a new {@link SpecimenTypeDesignation specimen type designation} to the set
240
//	 * of specimen type designations assigned to <i>this</i> homotypical group and eventually
241
//	 * (with a boolean parameter) also to the corresponding set of each of the
242
//	 * {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group.
243
//	 *
244
//	 * @param  specimenTypeDesignation	the specimen type designation to be added
245
//	 * @param  addToAllNames	the boolean flag indicating whether the addition will also
246
//	 * 							carried out for each taxon name
247
//	 * 
248
//	 * @see 			  		TaxonNameBase#getSpecimenTypeDesignations()
249
//	 * @see 			  		SpecimenTypeDesignation
250
//	 */
251
//	public void addSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation, boolean addToAllNames) {
252
//		if (specimenTypeDesignation != null){
253
//			specimenTypeDesignation.setHomotypicalGroup(this);
254
//			specimenTypeDesignations.add(specimenTypeDesignation);
255
//		}
256
//		if (addToAllNames){
257
//			for (TaxonNameBase taxonNameBase : this.typifiedNames){
258
//				taxonNameBase.addSpecimenTypeDesignation(specimenTypeDesignation);
259
//			}
260
//		}
261
//	}	
262
//	/** 
263
//	 * Removes one element from the set of {@link SpecimenTypeDesignation specimen type designations} assigned to the
264
//	 * {@link HomotypicalGroup homotypical group} to which this {@link TaxonNameBase taxon name} belongs.
265
//	 * The same element will be removed from the corresponding set of each of
266
//	 * the taxon names belonging to <i>this</i> homotypical group. Furthermore the
267
//	 * homotypical group attribute of the specimen type designation will be
268
//	 * nullified.
269
//	 *
270
//	 * @param  specimenTypeDesignation  the specimen type designation which should be deleted
271
//	 * @see     		  		#getSpecimenTypeDesignations()
272
//	 * @see    					#addSpecimenTypeDesignation(SpecimenTypeDesignation, boolean)
273
//	 * @see     		  		TaxonNameBase#removeSpecimenTypeDesignation(SpecimenTypeDesignation)
274
//	 * @see     		  		SpecimenTypeDesignation#getHomotypicalGroup()
275
//	 */
276
//	public void removeSpecimenTypeDesignation(SpecimenTypeDesignation specimenTypeDesignation) {
277
//		if (specimenTypeDesignation != null){
278
//			specimenTypeDesignation.setHomotypicalGroup(null);
279
//			specimenTypeDesignations.remove(specimenTypeDesignation);
280
//		}
281
//		for (TaxonNameBase taxonNameBase : this.typifiedNames){
282
//			taxonNameBase.removeSpecimenTypeDesignation(specimenTypeDesignation);
283
//		}
284
//	}	
285

    
286
	
287
//	/** 
288
//	 * Returns the set of {@link NameTypeDesignation name type designations} that
289
//	 * typify <i>this</i> homotypical group including the status of these designations.
290
//	 *
291
//	 * @see	#getTypifiedNames()
292
//	 */
293
//	@OneToMany
294
//	@Cascade({CascadeType.SAVE_UPDATE})
295
//	public Set<NameTypeDesignation> getNameTypeDesignations() {
296
//		return nameTypeDesignations;
297
//	}
298
//	/** 
299
//	 * @see #getNameTypeDesignations()
300
//	 */
301
//	protected void setNameTypeDesignations(Set<NameTypeDesignation> nameTypeDesignations) {
302
//		this.nameTypeDesignations = nameTypeDesignations;
303
//	}	
304
//	/** 
305
//	 * Adds a new {@link NameTypeDesignation name type designation} to the set
306
//	 * of name type designations assigned to <i>this</i> homotypical group and eventually
307
//	 * (with a boolean parameter) also to the corresponding set of each of the
308
//	 * {@link TaxonNameBase taxon names} belonging to <i>this</i> homotypical group.
309
//	 *
310
//	 * @param  nameTypeDesignation	the name type designation to be added
311
//	 * @param  addToAllNames	the boolean flag indicating whether the addition will also
312
//	 * 							carried out for each taxon name
313
//	 * 
314
//	 * @see 			  		TaxonNameBase#getNameTypeDesignations()
315
//	 * @see 			  		NameTypeDesignation
316
//	 */
317
//	public void addNameTypeDesignation(NameTypeDesignation nameTypeDesignation, boolean addToAllNames) {
318
//		if (nameTypeDesignation != null){
319
//			nameTypeDesignation.setHomotypicalGroup(this);
320
//			nameTypeDesignations.add(nameTypeDesignation);
321
//		}
322
//		if (addToAllNames){
323
//			for (TaxonNameBase taxonNameBase : this.typifiedNames){
324
//				taxonNameBase.addNameTypeDesignation(nameTypeDesignation);
325
//			}
326
//		}
327
//	}	
328
//	/** 
329
//	 * Removes one element from the set of {@link NameTypeDesignation name type designations} assigned to the
330
//	 * {@link HomotypicalGroup homotypical group} to which this {@link TaxonNameBase taxon name} belongs.
331
//	 * The same element will be removed from the corresponding set of each of
332
//	 * the taxon names belonging to <i>this</i> homotypical group. Furthermore the
333
//	 * homotypical group attribute of the name type designation will be
334
//	 * nullified.
335
//	 *
336
//	 * @param  nameTypeDesignation  the name type designation which should be deleted
337
//	 * @see     		  		#getNameTypeDesignations()
338
//	 * @see    					#addNameTypeDesignation(NameTypeDesignation, boolean)
339
//	 * @see     		  		TaxonNameBase#removeNameTypeDesignation(NameTypeDesignation)
340
//	 * @see     		  		NameTypeDesignation#getHomotypicalGroup()
341
//	 */
342
//	public void removeNameTypeDesignation(NameTypeDesignation nameTypeDesignation) {
343
//		if (nameTypeDesignation != null){
344
//			nameTypeDesignation.setHomotypicalGroup(null);
345
//			nameTypeDesignations.remove(nameTypeDesignation);
346
//		}
347
//		for (TaxonNameBase taxonNameBase : this.typifiedNames){
348
//			taxonNameBase.removeNameTypeDesignation(nameTypeDesignation);
349
//		}
350
//	}	
351
	
352
	
353
	/**
354
	 * Retrieves the ordered list (depending on the date of publication) of
355
	 * {@link taxon.Synonym synonyms} (according to a given reference)
356
	 * the {@link TaxonNameBase taxon names} of which belong to <i>this</i> homotypical group.
357
	 * If other names are part of <i>this</i> group that are not considered synonyms
358
	 * according to the respective reference, then they will not be included in
359
	 * the result set.
360
	 * 
361
	 * @deprecated synonyms should not depend on the sec. Therefore this method will be removed in 
362
	 * version 3.1 or higher. Use {@link Taxon#getSynonymsInGroup(HomotypicalGroup)} instead. But be
363
	 * aware that the semantics is slightly different.
364
	 * @param  sec	the reference whose treatment is to be considered
365
	 * @return		the ordered list of synonyms
366
	 * @see			TaxonNameBase#getSynonyms()
367
	 * @see			TaxonNameBase#getTaxa()
368
	 * @see			taxon.Synonym
369
	 */
370
	@Deprecated
371
	public List<Synonym> getSynonymsInGroup(Reference sec){
372
		List<Synonym> result = new ArrayList<Synonym>();
373
		for (TaxonNameBase<?, ?>name : this.getTypifiedNames()){
374
			for (Synonym synonym : name.getSynonyms()){
375
				if ( (synonym.getSec() == null && sec == null) ||
376
						synonym.getSec() != null && synonym.getSec().equals(sec)){
377
					result.add(synonym);
378
				}
379
			}
380
		}
381
		Collections.sort(result, new TaxonComparator());
382
		return result;
383
	}
384
	
385
    /**
386
     * Creates a basionym relationship to all other names in this names homotypical
387
     * group. 
388
     * 
389
     * @see HomotypicalGroup.setGroupBasionym(TaxonNameBase basionymName)
390
     *
391
     * @param basionymName
392
     * @throws IllegalArgumentException if basionymName is not member in this homotypical group
393
     */
394
	public void setGroupBasionym(TaxonNameBase basionymName) throws IllegalArgumentException{
395
    	setGroupBasionym(basionymName, null, null, null);
396
    }	
397
    
398
	public void setGroupBasionym(TaxonNameBase basionymName, Reference citation, String microCitation, String ruleConsidered) 
399
    			throws IllegalArgumentException {
400
    	if (! typifiedNames.contains(basionymName)){
401
        	throw new IllegalArgumentException("Name to be set as basionym/original combination must be part of the homotypical group but is not");
402
        }
403
        if (typifiedNames.size() < 2){return;}
404
//        
405
    	//Add new relations
406
        for (TaxonNameBase name : typifiedNames) {
407
    		if (!name.equals(basionymName)) {
408
		    	name.addRelationshipFromName(basionymName, NameRelationshipType.BASIONYM(), citation, microCitation, ruleConsidered);
409
			}
410
    	}
411
    }
412
    
413
    /**
414
     * Removes all basionym relationships between basionymName and any other name 
415
     * in its homotypic group
416
     *
417
     * @param basionymName
418
     */
419
     public static void removeGroupBasionym(TaxonNameBase basionymName) {
420
    	 HomotypicalGroup homotypicalGroup = basionymName.getHomotypicalGroup();
421
         Set<NameRelationship> relations = basionymName.getRelationsFromThisName();
422
         Set<NameRelationship> removeRelations = new HashSet<NameRelationship>();
423
        
424
         for (NameRelationship relation : relations) {
425
                
426
                 // If this is a basionym relation, and toName is in the homotypical group,
427
                 //      remove the relationship.
428
                 if (relation.getType().isBasionymRelation() &&
429
                                 relation.getToName().getHomotypicalGroup().equals(homotypicalGroup)) {
430
                         removeRelations.add(relation);
431
                 }
432
         }
433
         
434
          // Removing relations from a set through which we are iterating causes a
435
          //      ConcurrentModificationException. Therefore, we delete the targeted
436
          //      relations in a second step.
437
          for (NameRelationship relation : removeRelations) {
438
                  basionymName.removeNameRelationship(relation);
439
          }
440
     }
441
	
442
	
443
	/**
444
	 * Returns all taxon names in the homotypical group that do not have an 'is_basionym_for' (zool.: 'is_original_combination_for') 
445
	 * or a replaced synonym relationship.
446
	 * @return
447
	 */
448
	@Transient
449
	public Set<TaxonNameBase> getUnrelatedNames(){
450
		Set<NameRelationship> set = getBasionymOrReplacedSynonymRelations(true, true);
451
		Set<TaxonNameBase> result = new HashSet<TaxonNameBase>();
452
		result.addAll(this.getTypifiedNames());
453
		for (NameRelationship nameRelationship : set){
454
			result.remove(nameRelationship.getFromName());
455
			result.remove(nameRelationship.getToName());
456
		}
457
		return result;
458
	}	
459
	
460
	/**
461
	 * Returns all taxon names in the homotypical group that are new combinations (have a basionym/original combination 
462
	 * or a replaced synonym).
463
	 * @return
464
	 */
465
	@Transient
466
	public Set<TaxonNameBase> getNewCombinations(){
467
		Set<NameRelationship> set = getBasionymOrReplacedSynonymRelations(true, true);
468
		Set<TaxonNameBase> result = new HashSet<TaxonNameBase>();
469
		for (NameRelationship nameRelationship : set){
470
			result.add(nameRelationship.getToName());
471
		}
472
		return result;
473
	}	
474

    
475
	
476
	
477
	/**
478
	 * Returns all taxon names in the homotypical group that have an 'is_basionym_for' (zool.: 'is_original_combination_for') 
479
	 * or a replaced synonym relationship.
480
	 * @return
481
	 */
482
	@Transient
483
	public Set<TaxonNameBase> getBasionymsOrReplacedSynonyms(){
484
		Set<NameRelationship> set = getBasionymOrReplacedSynonymRelations(true, true);
485
		Set<TaxonNameBase> result = new HashSet<TaxonNameBase>();
486
		for (NameRelationship nameRelationship : set){
487
			result.add(nameRelationship.getFromName());
488
		}
489
		return result;
490
	}	
491
	
492
	/**
493
	 * Returns all taxon names in the homotypical group that have a 'is_basionym_for' (zool.: 'is_original_combination_for') relationship.
494
	 * @return
495
	 */
496
	@Transient
497
	public Set<TaxonNameBase> getBasionyms(){
498
		Set<NameRelationship> set = getBasionymOrReplacedSynonymRelations(true, false);
499
		Set<TaxonNameBase> result = new HashSet<TaxonNameBase>();
500
		for (NameRelationship nameRelationship : set){
501
			result.add(nameRelationship.getFromName());
502
		}
503
		return result;
504
	}
505

    
506
	/**
507
	 * Returns all taxon names in the homotypical group that have a 'is_replaced_synonym_for' relationship.
508
	 * @return
509
	 */
510
	@Transient
511
	public Set<TaxonNameBase> getReplacedSynonym(){
512
		Set<NameRelationship> set = getBasionymOrReplacedSynonymRelations(false, true);
513
		Set<TaxonNameBase> result = new HashSet<TaxonNameBase>();
514
		for (NameRelationship nameRelationship : set){
515
			result.add(nameRelationship.getFromName());
516
		}
517
		return result;
518
	}
519
	
520
	/**
521
	 * Returns the name relationships that represent either a basionym (original combination) relationship or
522
	 * a replaced synonym relationship.  
523
	 * @return
524
	 */
525
	@Transient
526
	public Set<NameRelationship> getBasionymAndReplacedSynonymRelations(){
527
		return getBasionymOrReplacedSynonymRelations(true, true);
528
	}
529
	
530
	/**
531
	 * Computes all basionym and replaced synonym relationships between names in this group.
532
	 * If <code>doBasionym</code> is <code>false</code> basionym relationships are excluded.
533
	 * If <code>doReplacedSynonym</code> is <code>false</code> replaced synonym relationships are excluded.
534
	 * @param doBasionym
535
	 * @param doReplacedSynonym
536
	 * @return
537
	 */
538
	@Transient
539
	private Set<NameRelationship> getBasionymOrReplacedSynonymRelations(boolean doBasionym, boolean doReplacedSynonym){
540
		Set<NameRelationship> result = new HashSet<NameRelationship>(); 
541
		Set<TaxonNameBase> names = this.getTypifiedNames();
542
		if (names.size() > 1){
543
			for (TaxonNameBase name : names){
544
				Set nameRels = name.getNameRelations();
545
				//TODO make getNameRelations generic
546
				for (Object obj : nameRels){
547
					NameRelationship nameRel = (NameRelationship)obj;
548
					NameRelationshipType type = nameRel.getType();
549
					if ( type.isBasionymRelation() && doBasionym){
550
						if (testRelatedNameInThisGroup(nameRel)){
551
							result.add(nameRel);
552
						}else{
553
							logger.warn("Name has basionym relation to a name that is not in the same homotypical group");
554
						}
555
					}else if (type.isReplacedSynonymRelation() && doReplacedSynonym)  {
556
						if (testRelatedNameInThisGroup(nameRel)){
557
							result.add(nameRel);
558
						}else{
559
							logger.warn("Name has replaced synonym relation to a name that is not in the same homotypical group");
560
						}
561
					}
562
				}
563
			}
564
		}
565
		return result;
566
	}
567
	
568
	private boolean testRelatedNameInThisGroup(NameRelationship nameRel){
569
		TaxonNameBase toName = nameRel.getToName();
570
		return (this.getTypifiedNames().contains(toName));
571
	}
572
	
573
	private boolean isBasionymOrRepSynRel(NameRelationshipType relType){
574
		if (relType == null){
575
			throw new IllegalArgumentException("NameRelationshipType should never be null");
576
		}else if (relType.equals(NameRelationshipType.BASIONYM())) {
577
			return true;
578
		}else if (relType.equals(NameRelationshipType.REPLACED_SYNONYM())){
579
			return true;
580
		}else{
581
			return false;
582
		}
583
	}
584
	
585
	
586
}
(4-4/26)