~ubuntu-branches/ubuntu/trusty/ivy/trusty

« back to all changes in this revision

Viewing changes to src/java/org/apache/ivy/plugins/latest/LatestRevisionStrategy.java

  • Committer: Bazaar Package Importer
  • Author(s): Varun Hiremath
  • Date: 2009-03-06 22:04:56 UTC
  • Revision ID: james.westby@ubuntu.com-20090306220456-5v37luqiuqda8ewp
Tags: upstream-2.0.0
ImportĀ upstreamĀ versionĀ 2.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 
3
 *  contributor license agreements.  See the NOTICE file distributed with
 
4
 *  this work for additional information regarding copyright ownership.
 
5
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 
6
 *  (the "License"); you may not use this file except in compliance with
 
7
 *  the License.  You may obtain a copy of the License at
 
8
 *
 
9
 *      http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 *  Unless required by applicable law or agreed to in writing, software
 
12
 *  distributed under the License is distributed on an "AS IS" BASIS,
 
13
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
 *  See the License for the specific language governing permissions and
 
15
 *  limitations under the License.
 
16
 *
 
17
 */
 
18
package org.apache.ivy.plugins.latest;
 
19
 
 
20
import java.util.Comparator;
 
21
import java.util.HashMap;
 
22
import java.util.Locale;
 
23
import java.util.Map;
 
24
 
 
25
import org.apache.ivy.core.IvyContext;
 
26
import org.apache.ivy.core.module.id.ModuleRevisionId;
 
27
import org.apache.ivy.plugins.version.VersionMatcher;
 
28
 
 
29
public class LatestRevisionStrategy extends ComparatorLatestStrategy {
 
30
    /**
 
31
     * Compares two ModuleRevisionId by their revision. Revisions are compared using an algorithm
 
32
     * inspired by PHP version_compare one.
 
33
     */
 
34
    final class MridComparator implements Comparator {
 
35
        public int compare(Object o1, Object o2) {
 
36
            String rev1 = ((ModuleRevisionId) o1).getRevision();
 
37
            String rev2 = ((ModuleRevisionId) o2).getRevision();
 
38
        
 
39
            rev1 = rev1.replaceAll("([a-zA-Z])(\\d)", "$1.$2");
 
40
            rev1 = rev1.replaceAll("(\\d)([a-zA-Z])", "$1.$2");
 
41
            rev2 = rev2.replaceAll("([a-zA-Z])(\\d)", "$1.$2");
 
42
            rev2 = rev2.replaceAll("(\\d)([a-zA-Z])", "$1.$2");
 
43
        
 
44
            String[] parts1 = rev1.split("[\\._\\-\\+]");
 
45
            String[] parts2 = rev2.split("[\\._\\-\\+]");
 
46
        
 
47
            int i = 0;
 
48
            for (; i < parts1.length && i < parts2.length; i++) {
 
49
                if (parts1[i].equals(parts2[i])) {
 
50
                    continue;
 
51
                }
 
52
                boolean is1Number = isNumber(parts1[i]);
 
53
                boolean is2Number = isNumber(parts2[i]);
 
54
                if (is1Number && !is2Number) {
 
55
                    return 1;
 
56
                }
 
57
                if (is2Number && !is1Number) {
 
58
                    return -1;
 
59
                }
 
60
                if (is1Number && is2Number) {
 
61
                    return Long.valueOf(parts1[i]).compareTo(Long.valueOf(parts2[i]));
 
62
                }
 
63
                // both are strings, we compare them taking into account special meaning
 
64
                Map specialMeanings = getSpecialMeanings();
 
65
                Integer sm1 = (Integer) specialMeanings.get(parts1[i].toLowerCase(Locale.US));
 
66
                Integer sm2 = (Integer) specialMeanings.get(parts2[i].toLowerCase(Locale.US));
 
67
                if (sm1 != null) {
 
68
                    sm2 = sm2 == null ? new Integer(0) : sm2;
 
69
                    return sm1.compareTo(sm2);
 
70
                }
 
71
                if (sm2 != null) {
 
72
                    return new Integer(0).compareTo(sm2);
 
73
                }
 
74
                return parts1[i].compareTo(parts2[i]);
 
75
            }
 
76
            if (i < parts1.length) {
 
77
                return isNumber(parts1[i]) ? 1 : -1;
 
78
            }
 
79
            if (i < parts2.length) {
 
80
                return isNumber(parts2[i]) ? -1 : 1;
 
81
            }
 
82
            return 0;
 
83
        }
 
84
 
 
85
        private boolean isNumber(String str) {
 
86
            return str.matches("\\d+");
 
87
        }
 
88
    }
 
89
 
 
90
    /**
 
91
     * Compares two ArtifactInfo by their revision. Revisions are compared using an algorithm
 
92
     * inspired by PHP version_compare one, unless a dynamic revision is given, in which case the
 
93
     * version matcher is used to perform the comparison.
 
94
     */
 
95
    final class ArtifactInfoComparator implements Comparator {
 
96
        public int compare(Object o1, Object o2) {
 
97
            String rev1 = ((ArtifactInfo) o1).getRevision();
 
98
            String rev2 = ((ArtifactInfo) o2).getRevision();
 
99
        
 
100
            /*
 
101
             * The revisions can still be not resolved, so we use the current version matcher to
 
102
             * know if one revision is dynamic, and in this case if it should be considered greater
 
103
             * or lower than the other one. Note that if the version matcher compare method returns
 
104
             * 0, it's because it's not possible to know which revision is greater. In this case we
 
105
             * consider the dynamic one to be greater, because most of the time it will then be
 
106
             * actually resolved and a real comparison will occur.
 
107
             */
 
108
            VersionMatcher vmatcher = IvyContext.getContext().getSettings().getVersionMatcher();
 
109
            ModuleRevisionId mrid1 = ModuleRevisionId.newInstance("", "", rev1);
 
110
            ModuleRevisionId mrid2 = ModuleRevisionId.newInstance("", "", rev2);
 
111
            if (vmatcher.isDynamic(mrid1)) {
 
112
                int c = vmatcher.compare(mrid1, mrid2, mridComparator);
 
113
                return c >= 0 ? 1 : -1;
 
114
            } else if (vmatcher.isDynamic(mrid2)) {
 
115
                int c = vmatcher.compare(mrid2, mrid1, mridComparator);
 
116
                return c >= 0 ? -1 : 1;
 
117
            }
 
118
        
 
119
            return mridComparator.compare(mrid1, mrid2);
 
120
        }
 
121
    }
 
122
 
 
123
    public static class SpecialMeaning {
 
124
        private String name;
 
125
 
 
126
        private Integer value;
 
127
 
 
128
        public String getName() {
 
129
            return name;
 
130
        }
 
131
 
 
132
        public void setName(String name) {
 
133
            this.name = name;
 
134
        }
 
135
 
 
136
        public Integer getValue() {
 
137
            return value;
 
138
        }
 
139
 
 
140
        public void setValue(Integer value) {
 
141
            this.value = value;
 
142
        }
 
143
 
 
144
        public void validate() {
 
145
            if (name == null) {
 
146
                throw new IllegalStateException("a special meaning should have a name");
 
147
            }
 
148
            if (value == null) {
 
149
                throw new IllegalStateException("a special meaning should have a value");
 
150
            }
 
151
        }
 
152
    }
 
153
 
 
154
    private static final Map DEFAULT_SPECIAL_MEANINGS;
 
155
    static {
 
156
        DEFAULT_SPECIAL_MEANINGS = new HashMap();
 
157
        DEFAULT_SPECIAL_MEANINGS.put("dev", new Integer(-1));
 
158
        DEFAULT_SPECIAL_MEANINGS.put("rc", new Integer(1));
 
159
        DEFAULT_SPECIAL_MEANINGS.put("final", new Integer(2));
 
160
    }
 
161
 
 
162
    private final Comparator mridComparator = new MridComparator();
 
163
 
 
164
    private final Comparator artifactInfoComparator = new ArtifactInfoComparator();
 
165
 
 
166
    private Map specialMeanings = null;
 
167
 
 
168
    private boolean usedefaultspecialmeanings = true;
 
169
 
 
170
    public LatestRevisionStrategy() {
 
171
        setComparator(artifactInfoComparator);
 
172
        setName("latest-revision");
 
173
    }
 
174
 
 
175
    public void addConfiguredSpecialMeaning(SpecialMeaning meaning) {
 
176
        meaning.validate();
 
177
        getSpecialMeanings().put(meaning.getName().toLowerCase(Locale.US), meaning.getValue());
 
178
    }
 
179
 
 
180
    public synchronized Map getSpecialMeanings() {
 
181
        if (specialMeanings == null) {
 
182
            specialMeanings = new HashMap();
 
183
            if (isUsedefaultspecialmeanings()) {
 
184
                specialMeanings.putAll(DEFAULT_SPECIAL_MEANINGS);
 
185
            }
 
186
        }
 
187
        return specialMeanings;
 
188
    }
 
189
 
 
190
    public boolean isUsedefaultspecialmeanings() {
 
191
        return usedefaultspecialmeanings;
 
192
    }
 
193
 
 
194
    public void setUsedefaultspecialmeanings(boolean usedefaultspecialmeanings) {
 
195
        this.usedefaultspecialmeanings = usedefaultspecialmeanings;
 
196
    }
 
197
}