Project

General

Profile

Download (9.28 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.taxon;
11

    
12
import java.io.Serializable;
13
import java.util.Comparator;
14
import java.util.Set;
15

    
16
import org.apache.log4j.Logger;
17
import org.joda.time.DateTime;
18

    
19
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
20
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
21
import eu.etaxonomy.cdm.model.name.Rank;
22
import eu.etaxonomy.cdm.model.name.TaxonName;
23
import eu.etaxonomy.cdm.model.reference.Reference;
24

    
25
/**
26
 * This class makes available a method to compare two {@link TaxonBase taxa} by
27
 * comparing the publication dates of the corresponding
28
 * {@link eu.etaxonomy.cdm.model.name.TaxonName taxon names}.
29
 *
30
 * @author a.mueller
31
 * @created 11.06.2008
32
 */
33
public class TaxonComparator implements Comparator<TaxonBase>, Serializable {
34
	private static final long serialVersionUID = -1433623743189043446L;
35
	@SuppressWarnings("unused")
36
	private static final Logger logger = Logger.getLogger(TaxonComparator.class);
37

    
38
	private boolean includeRanks = false;
39

    
40
    /**
41
     * @param includeRanks
42
     */
43
    public TaxonComparator() {
44
        super();
45
    }
46

    
47
    /**
48
     * @param includeRanks
49
     */
50
    public TaxonComparator(boolean includeRanks) {
51
        super();
52
        this.includeRanks = includeRanks;
53
    }
54

    
55

    
56
    /**
57
     * Returns an integer generated by comparing first the nomenclatural status and then the
58
     * {@link eu.etaxonomy.cdm.model.name.INomenclaturalReference#getYear() publication years}
59
     * of both {@link eu.etaxonomy.cdm.model.name.TaxonName taxon names}
60
     * used in the given {@link TaxonBase taxa}.
61
     * If 1 name has status of type nom. inval. or nom. nudum the name is put to the end of a
62
     * list (returns +1 for a status in taxon1 and -1 for a status in taxon2). If both do have
63
     * no status or the same status, the publication date is taken for comparison.
64
     * Nom. nudum is handled as more "severe" status then nom.inval.
65
     *
66
     * Returns a negative value if the publication year corresponding to the
67
     * first given taxon precedes the publication year corresponding to the
68
     * second given taxon. Returns a positive value if the contrary is true and
69
     * 0 if both publication years and the date, when they are created, are identical.
70
     * In case one of the publication
71
     * years is "null" and the other is not, the "empty" publication year will
72
     * be considered to be always preceded by the "not null" publication year.
73
     * If both publication years are "null" the creation date is used for the comparison
74
     *
75
     *
76
     * @see		java.lang.String#compareTo(String)
77
     * @see		java.util.Comparator#compare(java.lang.Object, java.lang.Object)
78
     */
79
    @Override
80
    public int compare(
81
            @SuppressWarnings("rawtypes") TaxonBase taxonBase1,
82
            @SuppressWarnings("rawtypes") TaxonBase taxonBase2) {
83
        int result;
84

    
85
        if (taxonBase1.equals(taxonBase2)){
86
        	return 0;
87
        }
88

    
89
        TaxonName name1 = taxonBase1.getName();
90
        TaxonName name2 = taxonBase2.getName();
91

    
92
        //set to end if a taxon has nomenclatural status "nom. inval." or "nom. nud."
93
        int statusCompareWeight = compareStatus(name1, name2);
94

    
95
        if (statusCompareWeight != 0){
96
        	return Integer.signum(statusCompareWeight);
97
        }
98

    
99
        //TODO discuss if we should also include nom. illeg. here on taxon level comparison
100
        result = compare(name1, name2, false);
101

    
102
        if (result == 0){
103
            DateTime date11 = taxonBase1.getCreated();
104
            DateTime date12 = taxonBase2.getCreated();
105
            if (date11 == null && date12 == null) {
106
                result = 0;
107
            }else if (date11 == null) {
108
                return 1;
109
            }else if (date12 == null) {
110
                return -1;
111
            }else{
112
            	result = date11.compareTo(date12);
113
            }
114
        }
115
        if (result == 0){
116
        	//the Comparator contract
117
        	return taxonBase1.getUuid().compareTo(taxonBase1.getUuid());
118
        }else{
119
        	return result;
120
        }
121
    }
122

    
123

    
124
    /**
125
     * @param taxonName
126
     * @param taxonName2
127
     * @param statusCompareWeight
128
     * @return
129
     */
130
    protected int compareStatus(TaxonName taxonName, TaxonName taxonName2) {
131
        int statusCompareWeight = 0;
132
        statusCompareWeight += computeStatusCompareWeight(taxonName);
133
        statusCompareWeight -= computeStatusCompareWeight(taxonName2);
134
        return statusCompareWeight;
135
    }
136

    
137

    
138
	/**
139
	 * @param taxonBase1
140
	 * @param statusCompareWeight
141
	 * @return
142
	 */
143
	private int computeStatusCompareWeight(TaxonName taxonName) {
144
		int result = 0;
145
		if (taxonName == null || taxonName.getStatus() == null){
146
			return 0;
147
		}
148
		Set<NomenclaturalStatus> status1 = taxonName.getStatus();
149
        for (NomenclaturalStatus nomStatus1 : status1){
150
            NomenclaturalStatusType type = nomStatus1.getType();
151
            if (type != null && type.isInvalidType()){
152
                if(type.equals(NomenclaturalStatusType.PROVISIONAL())){
153
                    result += 1;
154
                }else if (type.equals(NomenclaturalStatusType.INVALID())){
155
            		result += 2;
156
            	}else if(type.equals(NomenclaturalStatusType.COMBINATION_INVALID())){
157
                    result += 2;
158
            	}else if (type.equals(NomenclaturalStatusType.OPUS_UTIQUE_OPPR())){
159
                    result += 2;
160
                }else if(type.equals(NomenclaturalStatusType.NUDUM())){
161
            		result += 3;
162
                }
163
                result += 1;
164
            }
165
        }
166
		return result;
167
	}
168

    
169
    protected int compareNomIlleg(TaxonName taxonName1, TaxonName taxonName2) {
170
        int isNomIlleg1 = isNomIlleg(taxonName1);
171
        int isNomIlleg2 = isNomIlleg(taxonName2);
172
        return isNomIlleg1 - isNomIlleg2;
173
    }
174

    
175
    private int isNomIlleg(TaxonName taxonName) {
176
        if (taxonName == null || taxonName.getStatus() == null){
177
            return 0;
178
        }
179
        Set<NomenclaturalStatus> status = taxonName.getStatus();
180
        for (NomenclaturalStatus nomStatus : status){
181
            if (nomStatus.getType() != null){
182
                if (nomStatus.getType().equals(NomenclaturalStatusType.ILLEGITIMATE())){
183
                    return 1;
184
                }
185
            }
186
        }
187
        return 0;
188
    }
189

    
190

    
191
    private Integer getIntegerDate(TaxonName name){
192
        Integer result;
193

    
194
       if (name == null){
195
            result = null;
196
        }else{
197
            if (name.isZoological()){
198
                result = name.getPublicationYear();
199
            }else{
200
                Reference ref = (Reference) name.getNomenclaturalReference();
201
                if (ref == null){
202
                    result = null;
203
                }else{
204
                    if (ref.getDatePublished() == null){
205
                    	Reference inRef = ref.getInReference();
206
                    	if (inRef == null){
207
                            result = null;
208
                        }else{
209
                            if (inRef.getDatePublished() == null){
210
                            	result = null;
211
                            }else{
212
                            	result = ref.getInReference().getDatePublished().getStartYear();
213
                            }
214
                        }
215
                    }else{
216
                        result = ref.getDatePublished().getStartYear();
217
                    }
218
                }
219
            }
220
        }
221

    
222
        return result;
223
    }
224

    
225

    
226
    /**
227
     *
228
     * @param name1
229
     * @param name2
230
     * @param includeNomIlleg if true and if both names have no date or same date, the only
231
     * name having nom. illeg. state is handled as if the name was published later than the name
232
     * without status nom. illeg.
233
     * @return
234
     */
235
    protected int compare(TaxonName name1, TaxonName name2, boolean includeNomIlleg) {
236
        int result;
237

    
238
        //dates
239
        Integer intDate1 = getIntegerDate(name1);
240
        Integer intDate2 = getIntegerDate(name2);
241

    
242
        if (intDate1 == null && intDate2 == null){
243
            result = 0;
244
        }else if (intDate1 == null){
245
            return 1;
246
        }else if (intDate2 == null){
247
            return -1;
248
        }else{
249
            result = intDate1.compareTo(intDate2);
250
        }
251

    
252
        //nom. illeg.
253
        if (result == 0 && includeNomIlleg){
254
            result = compareNomIlleg(name1, name2);
255
            if (result != 0){
256
                return result;
257
            }
258
        }
259

    
260
        if (result == 0 && includeRanks){
261
            Rank rank1 = name1 == null? null : name1.getRank();
262
            Rank rank2 = name2 == null? null : name2.getRank();
263

    
264
            if (rank1 == null && rank2 == null){
265
                result = 0;
266
            }else if (rank1 == null){
267
                return 1;
268
            }else if (rank2 == null){
269
                return -1;
270
            }else{
271
                //for some strange reason compareTo for ranks returns 1 if rank2 is lower. So we add minus (-)
272
                result = - rank1.compareTo(rank2);
273
            }
274
        }
275

    
276
        if (result == 0 && name1 != null && name2 != null){
277
            result = name1.compareToName(name2);
278
            if (result != 0){
279
                return result;
280
            }
281
        }
282
        return result;
283
    }
284

    
285

    
286
}
(11-11/20)