Project

General

Profile

« Previous | Next » 

Revision d5d79aea

Added by Andreas Müller about 8 years ago

Improve sort order within a homotypic group (new Comparator) #3338

View differences:

cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/TaxonComparator.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.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

  
18
import org.joda.time.DateTime;
19

  
20
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
21
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
22
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
23
import eu.etaxonomy.cdm.model.name.ZoologicalName;
24
import eu.etaxonomy.cdm.model.reference.Reference;
25

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

  
39
    /**
40
     * Returns an integer generated by comparing first the nomenclatural status and then the 
41
     * {@link eu.etaxonomy.cdm.model.name.INomenclaturalReference#getYear() publication years}
42
     * of both {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon names} 
43
     * used in the given {@link TaxonBase taxa}.
44
     * If 1 name has status of type nom.inval. or nom.nudum the name is but to the end in a
45
     * list (returns +1 for a status in taxon1 and -1 for a status in taxon2). If both do have
46
     * no status or the same status, the publication date is taken for comparison.
47
     * Nom. nudum is handled as more "severe" status then nom.inval.
48
     *  
49
     * Returns a negative value if the publication year corresponding to the
50
     * first given taxon precedes the publication year corresponding to the
51
     * second given taxon. Returns a positive value if the contrary is true and
52
     * 0 if both publication years and the date, when they are created, are identical. 
53
     * In case one of the publication
54
     * years is "null" and the other is not, the "empty" publication year will
55
     * be considered to be always preceded by the "not null" publication year.
56
     * If both publication years are "null" the creation date is used for the comparison
57
     *
58
     *
59
     * @see		java.lang.String#compareTo(String)
60
     * @see		java.util.Comparator#compare(java.lang.Object, java.lang.Object)
61
     */
62
    public int compare(TaxonBase taxonBase1, TaxonBase taxonBase2) {
63
        int result;
64

  
65
        if (taxonBase1.equals(taxonBase2)){
66
        	return 0;
67
        }
68
        
69
        //set to end if a taxon has nomenclatural status "nom. inval." or "nom. nud."
70
        int statusCompareWeight = 0;
71
        statusCompareWeight += computeStatusCompareWeight(taxonBase1);
72
        statusCompareWeight -= computeStatusCompareWeight(taxonBase2);
73
        
74
        if (statusCompareWeight != 0){
75
        	return Integer.signum(statusCompareWeight);
76
        }
77
        
78
        //dates
79
        Integer intDate1 = getIntegerDate(taxonBase1);
80
        Integer intDate2 = getIntegerDate(taxonBase2);
81

  
82
        if (intDate1 == null && intDate2 == null){
83
            result = 0;
84
        }else if (intDate1 == null){
85
            return 1;
86
        }else if (intDate2 == null){
87
            return -1;
88
        }else{
89
            result = intDate1.compareTo(intDate2);
90
        }
91

  
92
        if (result == 0){
93
            TaxonNameBase<?,?> taxName1 = taxonBase1.getName();
94
            TaxonNameBase<?,?> taxName2 = taxonBase2.getName();
95

  
96
            result = taxName1.compareTo(taxName2);
97
            if (result != 0){
98
            	return result;
99
            }
100
        }
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 taxonBase1
126
	 * @param statusCompareWeight
127
	 * @return
128
	 */
129
	private int computeStatusCompareWeight(TaxonBase<?> taxonBase) {
130
		int result = 0;
131
		if (taxonBase == null || taxonBase.getName() == null || taxonBase.getName().getStatus() == null){
132
			return 0;
133
		}
134
		Set<NomenclaturalStatus> status1 = taxonBase.getName().getStatus();
135
        for (NomenclaturalStatus nomStatus1 : status1){
136
            if (nomStatus1.getType() != null){
137
            	if (nomStatus1.getType().equals(NomenclaturalStatusType.INVALID())){
138
            		result += 1;
139
            	}else if(nomStatus1.getType().equals(NomenclaturalStatusType.NUDUM())){
140
            		result += 2;
141
                }
142
            }
143
        }
144
		return result;
145
	}
146

  
147

  
148
    private Integer getIntegerDate(TaxonBase<?> taxonBase){
149
        Integer result;
150

  
151
        if (taxonBase == null){
152
            result = null;
153
        }else{
154
            TaxonNameBase<?,?> name = taxonBase.getName();
155
           if (name == null){
156
                result = null;
157
            }else{
158
                if (name instanceof ZoologicalName){
159
                    result = (((ZoologicalName)name).getPublicationYear());
160
                }else{
161
                    Reference<?> ref = (Reference<?>) name.getNomenclaturalReference();
162
                    if (ref == null){
163
                        result = null;
164
                    }else{
165
                        if (ref.getDatePublished() == null){
166
                        	Reference<?> inRef = ref.getInReference();
167
                        	if (inRef == null){
168
                                result = null;
169
                            }else{
170
                                if (inRef.getDatePublished() == null){
171
                                	result = null;
172
                                }else{
173
                                	result = ref.getInReference().getDatePublished().getStartYear();
174
                                }
175
                            }
176
                        }else{
177
                            result = ref.getDatePublished().getStartYear();
178
                        }
179
                    }
180
                }
181
            }
182
        }
183

  
184
        return result;
185
    }
186

  
187

  
188
}
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.TaxonNameBase;
22
import eu.etaxonomy.cdm.model.name.ZoologicalName;
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.TaxonNameBase 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
    /**
39
     * Returns an integer generated by comparing first the nomenclatural status and then the
40
     * {@link eu.etaxonomy.cdm.model.name.INomenclaturalReference#getYear() publication years}
41
     * of both {@link eu.etaxonomy.cdm.model.name.TaxonNameBase taxon names}
42
     * used in the given {@link TaxonBase taxa}.
43
     * If 1 name has status of type nom. inval. or nom. nudum the name is put to the end of a
44
     * list (returns +1 for a status in taxon1 and -1 for a status in taxon2). If both do have
45
     * no status or the same status, the publication date is taken for comparison.
46
     * Nom. nudum is handled as more "severe" status then nom.inval.
47
     *
48
     * Returns a negative value if the publication year corresponding to the
49
     * first given taxon precedes the publication year corresponding to the
50
     * second given taxon. Returns a positive value if the contrary is true and
51
     * 0 if both publication years and the date, when they are created, are identical.
52
     * In case one of the publication
53
     * years is "null" and the other is not, the "empty" publication year will
54
     * be considered to be always preceded by the "not null" publication year.
55
     * If both publication years are "null" the creation date is used for the comparison
56
     *
57
     *
58
     * @see		java.lang.String#compareTo(String)
59
     * @see		java.util.Comparator#compare(java.lang.Object, java.lang.Object)
60
     */
61
    @Override
62
    public int compare(
63
            @SuppressWarnings("rawtypes") TaxonBase taxonBase1,
64
            @SuppressWarnings("rawtypes") TaxonBase taxonBase2) {
65
        int result;
66

  
67
        if (taxonBase1.equals(taxonBase2)){
68
        	return 0;
69
        }
70

  
71
        TaxonNameBase<?,?> name1 = taxonBase1.getName();
72
        TaxonNameBase<?,?> name2 = taxonBase2.getName();
73

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

  
77
        if (statusCompareWeight != 0){
78
        	return Integer.signum(statusCompareWeight);
79
        }
80

  
81
        result = compare(name1, name2);
82

  
83
        if (result == 0){
84
            DateTime date11 = taxonBase1.getCreated();
85
            DateTime date12 = taxonBase2.getCreated();
86
            if (date11 == null && date12 == null) {
87
                result = 0;
88
            }else if (date11 == null) {
89
                return 1;
90
            }else if (date12 == null) {
91
                return -1;
92
            }else{
93
            	result = date11.compareTo(date12);
94
            }
95
        }
96
        if (result == 0){
97
        	//the Comparator contract
98
        	return taxonBase1.getUuid().compareTo(taxonBase1.getUuid());
99
        }else{
100
        	return result;
101
        }
102
    }
103

  
104

  
105
    /**
106
     * @param taxonNameBase
107
     * @param taxonNameBase2
108
     * @param statusCompareWeight
109
     * @return
110
     */
111
    protected int compareStatus(TaxonNameBase<?,?> taxonNameBase, TaxonNameBase<?,?> taxonNameBase2) {
112
        int statusCompareWeight = 0;
113
        statusCompareWeight += computeStatusCompareWeight(taxonNameBase);
114
        statusCompareWeight -= computeStatusCompareWeight(taxonNameBase2);
115
        return statusCompareWeight;
116
    }
117

  
118

  
119
	/**
120
	 * @param taxonBase1
121
	 * @param statusCompareWeight
122
	 * @return
123
	 */
124
	private int computeStatusCompareWeight(TaxonNameBase<?,?> taxonNameBase) {
125
		int result = 0;
126
		if (taxonNameBase == null || taxonNameBase.getStatus() == null){
127
			return 0;
128
		}
129
		Set<NomenclaturalStatus> status1 = taxonNameBase.getStatus();
130
        for (NomenclaturalStatus nomStatus1 : status1){
131
            if (nomStatus1.getType() != null){
132
            	if (nomStatus1.getType().equals(NomenclaturalStatusType.INVALID())){
133
            		result += 1;
134
            	}else if(nomStatus1.getType().equals(NomenclaturalStatusType.NUDUM())){
135
            		result += 2;
136
                }
137
            }
138
        }
139
		return result;
140
	}
141

  
142

  
143
    private Integer getIntegerDate(TaxonNameBase<?,?> name){
144
        Integer result;
145

  
146
       if (name == null){
147
            result = null;
148
        }else{
149
            if (name instanceof ZoologicalName){
150
                result = (((ZoologicalName)name).getPublicationYear());
151
            }else{
152
                Reference<?> ref = (Reference<?>) name.getNomenclaturalReference();
153
                if (ref == null){
154
                    result = null;
155
                }else{
156
                    if (ref.getDatePublished() == null){
157
                    	Reference<?> inRef = ref.getInReference();
158
                    	if (inRef == null){
159
                            result = null;
160
                        }else{
161
                            if (inRef.getDatePublished() == null){
162
                            	result = null;
163
                            }else{
164
                            	result = ref.getInReference().getDatePublished().getStartYear();
165
                            }
166
                        }
167
                    }else{
168
                        result = ref.getDatePublished().getStartYear();
169
                    }
170
                }
171
            }
172
        }
173

  
174
        return result;
175
    }
176

  
177

  
178
    /**
179
     *
180
     * @param name1
181
     * @param name2
182
     * @return
183
     */
184
    protected int compare(TaxonNameBase<?,?> name1, TaxonNameBase<?,?> name2) {
185
        int result;
186

  
187
        //dates
188
        Integer intDate1 = getIntegerDate(name1);
189
        Integer intDate2 = getIntegerDate(name2);
190

  
191
        if (intDate1 == null && intDate2 == null){
192
            result = 0;
193
        }else if (intDate1 == null){
194
            return 1;
195
        }else if (intDate2 == null){
196
            return -1;
197
        }else{
198
            result = intDate1.compareTo(intDate2);
199
        }
200

  
201
        if (result == 0){
202
            result = name1.compareTo(name2);
203
            if (result != 0){
204
                return result;
205
            }
206
        }
207
        return result;
208
    }
209

  
210

  
211
}

Also available in: Unified diff