OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Rev 21 | Rev 28 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
17 ilm 1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
7
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
8
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
9
 * language governing permissions and limitations under the License.
10
 *
11
 * When distributing the software, include this License Header Notice in each file.
12
 */
13
 
14
 /*
15
 * Créé le 3 mars 2005
16
 */
17
package org.openconcerto.utils;
18
 
19 ilm 19
import java.nio.charset.Charset;
17 ilm 20
import java.util.ArrayList;
21
import java.util.Collections;
22
import java.util.HashMap;
23
import java.util.HashSet;
24
import java.util.LinkedHashMap;
25
import java.util.List;
26
import java.util.Map;
27
import java.util.Set;
28
 
29
/**
30
 * @author Sylvain CUAZ
31
 */
32
public class StringUtils {
33
 
19 ilm 34
    private static final Charset UTF8 = Charset.forName("UTF8");
35
 
17 ilm 36
    /**
37
     * Retourne la chaine avec la première lettre en majuscule et le reste en minuscule.
38
     *
39
     * @param s la chaîne à transformer.
40
     * @return la chaine avec la première lettre en majuscule et le reste en minuscule.
41
     */
42
    public static String firstUpThenLow(String s) {
43
        if (s.length() == 0) {
44
            return s;
45
        }
46
        if (s.length() == 1) {
47
            return s.toUpperCase();
48
        }
49
        return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
50
    }
51
 
52
    public static String firstUp(String s) {
53
        if (s.length() == 0) {
54
            return s;
55
        }
56
        if (s.length() == 1) {
57
            return s.toUpperCase();
58
        }
59
        return s.substring(0, 1).toUpperCase() + s.substring(1);
60
    }
61
 
19 ilm 62
    static public abstract class Shortener {
63
 
64
        private final int hashSize;
65
        private final int hashPartSize;
66
        private final String prefix;
67
        private final String suffix;
68
        private final int minStringLength;
69
 
70
        protected Shortener(int hashSize, String prefix, String suffix, int minCharsBeforeAndAfter) {
71
            super();
72
            this.hashSize = hashSize;
73
            this.prefix = prefix;
74
            this.suffix = suffix;
75
            this.hashPartSize = this.hashSize + this.prefix.length() + this.suffix.length();
76
            if (minCharsBeforeAndAfter < 1)
77
                throw new IllegalArgumentException("minCharsBeforeAndAfter must be at least 1: " + minCharsBeforeAndAfter);
78
            this.minStringLength = this.hashPartSize + minCharsBeforeAndAfter * 2;
79
        }
80
 
81
        public final int getMinStringLength() {
82
            return this.minStringLength;
83
        }
84
 
85
        public final String getBoundedLengthString(final String s, final int maxLength) {
86
            // don't test first for s.length, it's more predictable
87
            // (otherwise boundedString("a", 2) would succeed)
88
            if (maxLength < this.getMinStringLength())
89
                throw new IllegalArgumentException("Maximum too low : " + maxLength + "<" + getMinStringLength());
90
            if (s.length() <= maxLength)
91
                return s;
92
            else
93
                return this.shorten(s, maxLength);
94
        }
95
 
96
        final String shorten(final String s, final int maxLength) {
97
            assert s.length() >= this.getMinStringLength();
98
            final int toRemoveLength = s.length() - maxLength + this.hashPartSize;
99
            // remove the middle part of encoded
100
            final int toRemoveStartIndex = s.length() / 2 - toRemoveLength / 2;
101
            final String toHash = s.substring(toRemoveStartIndex, toRemoveStartIndex + toRemoveLength);
102
 
103
            final String hash = shorten(toHash);
104
            assert this.hashSize == hash.length();
105
 
106
            final String res = s.substring(0, toRemoveStartIndex) + this.prefix + hash + this.suffix + s.substring(toRemoveStartIndex + toRemoveLength);
107
            assert res.length() == maxLength;
108
            return res;
109
        }
110
 
111
        protected abstract String shorten(String s);
112
 
113
        static public final Shortener Ellipsis = new Shortener(1, "", "", 1) {
114
            @Override
115
            protected String shorten(String s) {
116
                return "…";
117
            }
118
        };
119
 
120
        // String.hashCode() is an int written in hex
121
        static public final Shortener JavaHashCode = new Shortener(Integer.SIZE / 8 * 2, "#", "#", 3) {
122
            @Override
123
            protected String shorten(String s) {
124
                return MessageDigestUtils.asHex(MessageDigestUtils.int2bytes(s.hashCode()));
125
            }
126
        };
127
 
128
        // 128 bits written in hex
129
        static public final Shortener MD5 = new Shortener(128 / 8 * 2, "#", "#", 11) {
130
            @Override
131
            protected String shorten(String s) {
132
                return MessageDigestUtils.getHashString(MessageDigestUtils.getMD5(), s.getBytes(UTF8));
133
            }
134
        };
135
 
136
        // order descendant by getMinStringLength()
137
        static final Shortener[] ORDERED = new Shortener[] { MD5, JavaHashCode, Ellipsis };
138
    }
139
 
140
    /**
141
     * The minimum value for {@link #getBoundedLengthString(String, int)}.
142
     *
143
     * @return the minimum value for <code>maxLength</code>.
144
     */
145
    public static final int getLeastMaximum() {
146
        return Shortener.ORDERED[Shortener.ORDERED.length - 1].getMinStringLength();
147
    }
148
 
149
    private static final Shortener getShortener(final int l) {
150
        for (final Shortener sh : Shortener.ORDERED) {
151
            if (l >= sh.getMinStringLength())
152
                return sh;
153
        }
154
        return null;
155
    }
156
 
157
    /**
158
     * Return a string built from <code>s</code> that is at most <code>maxLength</code> long.
159
     *
160
     * @param s the string to bound.
161
     * @param maxLength the maximum length the result must have.
162
     * @return a string built from <code>s</code>.
163
     * @throws IllegalArgumentException if <code>maxLength</code> is too small.
164
     * @see #getLeastMaximum()
165
     * @see Shortener#getBoundedLengthString(String, int)
166
     */
167
    public static final String getBoundedLengthString(final String s, final int maxLength) throws IllegalArgumentException {
168
        // don't test first for s.length, it's more predictable
169
        // (otherwise boundedString("a", 2) would succeed)
170
        if (maxLength < getLeastMaximum())
171
            throw new IllegalArgumentException("Maximum too low : " + maxLength + "<" + getLeastMaximum());
172
 
173
        final String res;
174
        if (s.length() <= maxLength) {
175
            res = s;
176
        } else {
177
            // use maxLength to choose the shortener since it's generally a constant
178
            // and thus the strings returned by this method have the same pattern
179
            res = getShortener(maxLength).shorten(s, maxLength);
180
        }
181
        return res;
182
    }
183
 
17 ilm 184
    public static final List<String> fastSplit(final String string, final char sep) {
185
        final List<String> l = new ArrayList<String>();
186
        final int length = string.length();
187
        final char[] cars = string.toCharArray();
188
        int rfirst = 0;
189
 
190
        for (int i = 0; i < length; i++) {
191
            if (cars[i] == sep) {
192
                l.add(new String(cars, rfirst, i - rfirst));
193
                rfirst = i + 1;
194
            }
195
        }
196
 
197
        if (rfirst < length) {
198
            l.add(new String(cars, rfirst, length - rfirst));
199
        }
200
        return l;
201
    }
202
 
19 ilm 203
    /**
204
     * Split une string s tous les nbCharMaxLine
205
     *
206
     * @param s
207
     * @param nbCharMaxLine
208
     * @return
209
     */
210
    public static String splitString(String s, int nbCharMaxLine) {
211
 
212
        if (s == null) {
213
            return s;
214
        }
215
 
216
        if (s.trim().length() < nbCharMaxLine) {
217
            return s;
218
        }
219
        StringBuffer lastString = new StringBuffer();
220
        StringBuffer result = new StringBuffer();
221
        for (int i = 0; i < s.length(); i++) {
222
 
223
            if (lastString.length() == nbCharMaxLine) {
224
                int esp = lastString.lastIndexOf(" ");
25 ilm 225
                if (result.length() > 0 && result.charAt(result.length() - 1) != '\n') {
19 ilm 226
                    result.append("\n");
227
                }
228
                if (esp > 0) {
229
                    result.append(lastString.substring(0, esp).toString().trim());
230
                    lastString = new StringBuffer(lastString.substring(esp, lastString.length()));
231
                } else {
232
                    result.append(lastString.toString().trim());
233
                    lastString = new StringBuffer();
234
                }
25 ilm 235
                result.append("\n");
19 ilm 236
            }
237
 
238
            char charAt = s.charAt(i);
239
            if (charAt == '\n') {
240
                lastString.append(charAt);
21 ilm 241
                result.append(lastString);
19 ilm 242
                lastString = new StringBuffer();
243
            } else {
244
                lastString.append(charAt);
245
            }
246
        }
247
 
25 ilm 248
        if (result.length() > 0 && result.charAt(result.length() - 1) != '\n') {
19 ilm 249
            result.append("\n");
250
        }
251
 
252
        result.append(lastString.toString().trim());
253
 
254
        return result.toString();
255
    }
256
 
17 ilm 257
    public static final class Escaper {
258
 
259
        // eg '
260
        private final char esc;
261
 
262
        // eg { '=> S, " => D}
263
        private final Map<Character, Character> substitution;
264
        private final Map<Character, Character> inv;
265
 
266
        /**
267
         * A new escaper that will have <code>esc</code> as escape character.
268
         *
269
         * @param esc the escape character, eg '
270
         * @param name the character that will be appended to <code>esc</code>, eg with S all
271
         *        occurrences of ' will be replaced by 'S
272
         */
273
        public Escaper(char esc, char name) {
274
            super();
275
            this.esc = esc;
276
            this.substitution = new LinkedHashMap<Character, Character>();
277
            this.inv = new HashMap<Character, Character>();
278
            this.add(esc, name);
279
        }
280
 
281
        public Escaper add(char toRemove, char escapedName) {
282
            if (this.inv.containsKey(escapedName))
283
                throw new IllegalArgumentException(escapedName + " already replaces " + this.inv.get(escapedName));
284
            this.substitution.put(toRemove, escapedName);
285
            this.inv.put(escapedName, toRemove);
286
            return this;
287
        }
288
 
289
        public final Set<Character> getEscapedChars() {
290
            final Set<Character> res = new HashSet<Character>(this.substitution.keySet());
291
            res.remove(this.esc);
292
            return res;
293
        }
294
 
295
        /**
296
         * Escape <code>s</code>, so that the resulting string has none of
297
         * {@link #getEscapedChars()}.
298
         *
299
         * @param s a string to escape.
300
         * @return the escaped form.
301
         */
302
        public final String escape(String s) {
303
            String res = s;
304
            // this.esc en premier
305
            for (final Character toEsc : this.substitution.keySet()) {
306
                // use Pattern.LITERAL to avoid interpretion
307
                res = res.replace(toEsc + "", getEscaped(toEsc));
308
            }
309
            return res;
310
        }
311
 
312
        private String getEscaped(final Character toEsc) {
313
            return this.esc + "" + this.substitution.get(toEsc);
314
        }
315
 
316
        public final String unescape(String escaped) {
317
            String res = escaped;
318
            final List<Character> toEscs = new ArrayList<Character>(this.substitution.keySet());
319
            Collections.reverse(toEscs);
320
            for (final Character toEsc : toEscs) {
321
                res = res.replaceAll(getEscaped(toEsc), toEsc + "");
322
            }
323
            return res;
324
        }
325
 
326
        @Override
327
        public boolean equals(Object obj) {
328
            if (obj instanceof Escaper) {
329
                final Escaper o = (Escaper) obj;
330
                return this.esc == o.esc && this.substitution.equals(o.substitution);
331
            } else
332
                return false;
333
        }
334
 
335
        @Override
336
        public int hashCode() {
337
            return this.esc + this.substitution.hashCode();
338
        }
339
    }
340
 
25 ilm 341
    public static String rightAlign(String s, int width) {
342
        String r = s;
343
        int n = width - s.length();
344
        for (int i = 0; i < n; i++) {
345
            r = ' ' + r;
346
        }
347
        return r;
348
    }
349
 
350
    public static String leftAlign(String s, int width) {
351
        String r = s;
352
        int n = width - s.length();
353
        for (int i = 0; i < n; i++) {
354
            r += ' ';
355
        }
356
        return r;
357
    }
17 ilm 358
}