source: josm/trunk/src/org/openstreetmap/josm/tools/Utils.java @ 5241

Revision 5221, 16.2 KB checked in by Don-vip, 2 weeks ago (diff)

should fix #7663 - Pasting in Windows gives "java.lang.IllegalStateException: cannot open system clipboard"

  • Property svn:eol-style set to native
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.tools;
3
4import java.awt.Color;
5import java.awt.Toolkit;
6import java.awt.datatransfer.Clipboard;
7import java.awt.datatransfer.ClipboardOwner;
8import java.awt.datatransfer.DataFlavor;
9import java.awt.datatransfer.StringSelection;
10import java.awt.datatransfer.Transferable;
11import java.awt.datatransfer.UnsupportedFlavorException;
12import java.io.File;
13import java.io.IOException;
14import java.io.InputStream;
15import java.io.OutputStream;
16import java.io.Reader;
17import java.io.UnsupportedEncodingException;
18import java.security.MessageDigest;
19import java.security.NoSuchAlgorithmException;
20import java.text.MessageFormat;
21import java.util.ArrayList;
22import java.util.Collection;
23import java.util.Iterator;
24import java.util.List;
25
26/**
27 * Basic utils, that can be useful in different parts of the program.
28 */
29public class Utils {
30
31    public static <T> boolean exists(Iterable<? extends T> collection, Predicate<? super T> predicate) {
32        for (T item : collection) {
33            if (predicate.evaluate(item))
34                return true;
35        }
36        return false;
37    }
38
39    public static <T> boolean exists(Iterable<T> collection, Class<? extends T> klass) {
40        for (Object item : collection) {
41            if (klass.isInstance(item))
42                return true;
43        }
44        return false;
45    }
46
47    public static <T> T find(Iterable<? extends T> collection, Predicate<? super T> predicate) {
48        for (T item : collection) {
49            if (predicate.evaluate(item))
50                return item;
51        }
52        return null;
53    }
54
55    @SuppressWarnings("unchecked")
56    public static <T> T find(Iterable<? super T> collection, Class<? extends T> klass) {
57        for (Object item : collection) {
58            if (klass.isInstance(item))
59                return (T) item;
60        }
61        return null;
62    }
63
64    public static <T> Collection<T> filter(Collection<? extends T> collection, Predicate<? super T> predicate) {
65        return new FilteredCollection<T>(collection, predicate);
66    }
67
68    public static <T> T firstNonNull(T... items) {
69        for (T i : items) {
70            if (i != null) {
71                return i;
72            }
73        }
74        return null;
75    }
76
77    /**
78     * Filter a collection by (sub)class.
79     * This is an efficient read-only implementation.
80     */
81    public static <S, T extends S> SubclassFilteredCollection<S, T> filteredCollection(Collection<S> collection, final Class<T> klass) {
82        return new SubclassFilteredCollection<S, T>(collection, new Predicate<S>() {
83            @Override
84            public boolean evaluate(S o) {
85                return klass.isInstance(o);
86            }
87        });
88    }
89
90    public static <T> int indexOf(Iterable<? extends T> collection, Predicate<? super T> predicate) {
91        int i = 0;
92        for (T item : collection) {
93            if (predicate.evaluate(item))
94                return i;
95            i++;
96        }
97        return -1;
98    }
99
100    /**
101     * Get minimum of 3 values
102     */
103    public static int min(int a, int b, int c) {
104        if (b < c) {
105            if (a < b)
106                return a;
107            return b;
108        } else {
109            if (a < c)
110                return a;
111            return c;
112        }
113    }
114
115    public static int max(int a, int b, int c, int d) {
116        return Math.max(Math.max(a, b), Math.max(c, d));
117    }
118
119    /**
120     * for convenience: test whether 2 objects are either both null or a.equals(b)
121     */
122    public static <T> boolean equal(T a, T b) {
123        if (a == b)
124            return true;
125        return (a != null && a.equals(b));
126    }
127
128    public static void ensure(boolean condition, String message, Object...data) {
129        if (!condition)
130            throw new AssertionError(
131                    MessageFormat.format(message,data)
132            );
133    }
134
135    /**
136     * return the modulus in the range [0, n)
137     */
138    public static int mod(int a, int n) {
139        if (n <= 0)
140            throw new IllegalArgumentException();
141        int res = a % n;
142        if (res < 0) {
143            res += n;
144        }
145        return res;
146    }
147
148    /**
149     * Joins a list of strings (or objects that can be converted to string via
150     * Object.toString()) into a single string with fields separated by sep.
151     * @param sep the separator
152     * @param values collection of objects, null is converted to the
153     *  empty string
154     * @return null if values is null. The joined string otherwise.
155     */
156    public static String join(String sep, Collection<?> values) {
157        if (sep == null)
158            throw new IllegalArgumentException();
159        if (values == null)
160            return null;
161        if (values.isEmpty())
162            return "";
163        StringBuilder s = null;
164        for (Object a : values) {
165            if (a == null) {
166                a = "";
167            }
168            if (s != null) {
169                s.append(sep).append(a.toString());
170            } else {
171                s = new StringBuilder(a.toString());
172            }
173        }
174        return s.toString();
175    }
176
177    public static String joinAsHtmlUnorderedList(Collection<?> values) {
178        StringBuilder sb = new StringBuilder(1024);
179        sb.append("<ul>");
180        for (Object i : values) {
181            sb.append("<li>").append(i).append("</li>");
182        }
183        sb.append("</ul>");
184        return sb.toString();
185    }
186
187    /**
188     * convert Color to String
189     * (Color.toString() omits alpha value)
190     */
191    public static String toString(Color c) {
192        if (c == null)
193            return "null";
194        if (c.getAlpha() == 255)
195            return String.format("#%06x", c.getRGB() & 0x00ffffff);
196        else
197            return String.format("#%06x(alpha=%d)", c.getRGB() & 0x00ffffff, c.getAlpha());
198    }
199
200    /**
201     * convert float range 0 <= x <= 1 to integer range 0..255
202     * when dealing with colors and color alpha value
203     * @return null if val is null, the corresponding int if val is in the
204     *         range 0...1. If val is outside that range, return 255
205     */
206    public static Integer color_float2int(Float val) {
207        if (val == null)
208            return null;
209        if (val < 0 || val > 1)
210            return 255;
211        return (int) (255f * val + 0.5f);
212    }
213
214    /**
215     * convert back
216     */
217    public static Float color_int2float(Integer val) {
218        if (val == null)
219            return null;
220        if (val < 0 || val > 255)
221            return 1f;
222        return ((float) val) / 255f;
223    }
224
225    public static Color complement(Color clr) {
226        return new Color(255 - clr.getRed(), 255 - clr.getGreen(), 255 - clr.getBlue(), clr.getAlpha());
227    }
228
229    public static int copyStream(InputStream source, OutputStream destination) throws IOException {
230        int count = 0;
231        byte[] b = new byte[512];
232        int read;
233        while ((read = source.read(b)) != -1) {
234            count += read;
235            destination.write(b, 0, read);
236        }
237        return count;
238    }
239
240    public static boolean deleteDirectory(File path) {
241        if( path.exists() ) {
242            File[] files = path.listFiles();
243            for(int i=0; i<files.length; i++) {
244                if(files[i].isDirectory()) {
245                    deleteDirectory(files[i]);
246                }
247                else {
248                    files[i].delete();
249                }
250            }
251        }
252        return( path.delete() );
253    }
254
255    /**
256     * <p>Utility method for closing an input stream.</p>
257     *
258     * @param is the input stream. May be null.
259     */
260    public static void close(InputStream is){
261        if (is == null) return;
262        try {
263            is.close();
264        } catch(IOException e){
265            // ignore
266        }
267    }
268
269    /**
270     * <p>Utility method for closing an output stream.</p>
271     *
272     * @param os the output stream. May be null.
273     */
274    public static void close(OutputStream os){
275        if (os == null) return;
276        try {
277            os.close();
278        } catch(IOException e){
279            // ignore
280        }
281    }
282
283    /**
284     * <p>Utility method for closing a reader.</p>
285     *
286     * @param reader the reader. May be null.
287     */
288    public static void close(Reader reader){
289        if (reader == null) return;
290        try {
291            reader.close();
292        } catch(IOException e){
293            // ignore
294        }
295    }
296
297    private final static double EPSILION = 1e-11;
298
299    public static boolean equalsEpsilon(double a, double b) {
300        return Math.abs(a - b) <= EPSILION;
301    }
302
303    /**
304     * Copies the string {@code s} to system clipboard.
305     * @param s string to be copied to clipboard.
306     * @return true if succeeded, false otherwise.
307     */
308    public static boolean copyToClipboard(String s) {
309        try {
310            Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(s), new ClipboardOwner() {
311
312                @Override
313                public void lostOwnership(Clipboard clpbrd, Transferable t) {
314                }
315            });
316            return true;
317        } catch (IllegalStateException ex) {
318            ex.printStackTrace();
319            return false;
320        }
321    }
322
323    /**
324     * Extracts clipboard content as string.
325     * @return string clipboard contents if available, {@code null} otherwise.
326     */
327    public static String getClipboardContent() {
328        Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
329        Transferable t = null;
330        for (int tries = 0; t == null && tries < 10; tries++) {
331            try {
332                t = clipboard.getContents(null);
333            } catch (IllegalStateException e) { 
334                // Clipboard currently unavailable. On some platforms, the system clipboard is unavailable while it is accessed by another application.
335                try {
336                    Thread.sleep(1);
337                } catch (InterruptedException ex) {
338                }
339            }
340        }
341        try {
342            if (t != null && t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
343                String text = (String) t.getTransferData(DataFlavor.stringFlavor);
344                return text;
345            }
346        } catch (UnsupportedFlavorException ex) {
347            ex.printStackTrace();
348            return null;
349        } catch (IOException ex) {
350            ex.printStackTrace();
351            return null;
352        }
353        return null;
354    }
355
356    /**
357     * Calculate MD5 hash of a string and output in hexadecimal format.
358     * Output has length 32 with characters in range [0-9a-f]
359     */
360    public static String md5Hex(String data) {
361        byte[] byteData = null;
362        try {
363            byteData = data.getBytes("UTF-8");
364        } catch (UnsupportedEncodingException e) {
365            throw new RuntimeException();
366        }
367        MessageDigest md = null;
368        try {
369            md = MessageDigest.getInstance("MD5");
370        } catch (NoSuchAlgorithmException e) {
371            throw new RuntimeException();
372        }
373        byte[] byteDigest = md.digest(byteData);
374        return toHexString(byteDigest);
375    }
376
377    /**
378     * Converts a byte array to a string of hexadecimal characters. Preserves leading zeros, so the
379     * size of the output string is always twice the number of input bytes.
380     */
381    public static String toHexString(byte[] bytes) {
382        char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
383        char[] hexChars = new char[bytes.length * 2];
384        for (int j=0; j<bytes.length; j++) {
385            int v = bytes[j] & 0xFF;
386            hexChars[j*2] = hexArray[v/16];
387            hexChars[j*2 + 1] = hexArray[v%16];
388        }
389        return new String(hexChars);
390    }
391
392    /**
393     * Topological sort.
394     *
395     * @param dependencies contains mappings (key -> value). In the final list of sorted objects, the key will come
396     * after the value. (In other words, the key depends on the value(s).)
397     * There must not be cyclic dependencies.
398     * @return the list of sorted objects
399     */
400    public static <T> List<T> topologicalSort(final MultiMap<T,T> dependencies) {
401        MultiMap<T,T> deps = new MultiMap<T,T>();
402        for (T key : dependencies.keySet()) {
403            deps.putVoid(key);
404            for (T val : dependencies.get(key)) {
405                deps.putVoid(val);
406                deps.put(key, val);
407            }
408        }
409
410        int size = deps.size();
411        List<T> sorted = new ArrayList<T>();
412        for (int i=0; i<size; ++i) {
413            T parentless = null;
414            for (T key : deps.keySet()) {
415                if (deps.get(key).size() == 0) {
416                    parentless = key;
417                    break;
418                }
419            }
420            if (parentless == null) throw new RuntimeException();
421            sorted.add(parentless);
422            deps.remove(parentless);
423            for (T key : deps.keySet()) {
424                deps.remove(key, parentless);
425            }
426        }
427        if (sorted.size() != size) throw new RuntimeException();
428        return sorted;
429    }
430
431    /**
432     * Represents a function that can be applied to objects of {@code A} and
433     * returns objects of {@code B}.
434     * @param <A> class of input objects
435     * @param <B> class of transformed objects
436     */
437    public static interface Function<A, B> {
438
439        /**
440         * Applies the function on {@code x}.
441         * @param x an object of
442         * @return the transformed object
443         */
444        B apply(A x);
445    }
446
447    /**
448     * Transforms the collection {@code c} into an unmodifiable collection and
449     * applies the {@link Function} {@code f} on each element upon access.
450     * @param <A> class of input collection
451     * @param <B> class of transformed collection
452     * @param c a collection
453     * @param f a function that transforms objects of {@code A} to objects of {@code B}
454     * @return the transformed unmodifiable collection
455     */
456    public static <A, B> Collection<B> transform(final Collection<? extends A> c, final Function<A, B> f) {
457        return new Collection<B>() {
458
459            @Override
460            public int size() {
461                return c.size();
462            }
463
464            @Override
465            public boolean isEmpty() {
466                return c.isEmpty();
467            }
468
469            @Override
470            public boolean contains(Object o) {
471                return c.contains(o);
472            }
473
474            @Override
475            public Object[] toArray() {
476                return c.toArray();
477            }
478
479            @Override
480            public <T> T[] toArray(T[] a) {
481                return c.toArray(a);
482            }
483
484            @Override
485            public String toString() {
486                return c.toString();
487            }
488
489            @Override
490            public Iterator<B> iterator() {
491                return new Iterator<B>() {
492
493                    private Iterator<? extends A> it = c.iterator();
494
495                    @Override
496                    public boolean hasNext() {
497                        return it.hasNext();
498                    }
499
500                    @Override
501                    public B next() {
502                        return f.apply(it.next());
503                    }
504
505                    @Override
506                    public void remove() {
507                        throw new UnsupportedOperationException();
508                    }
509                };
510            }
511
512            @Override
513            public boolean add(B e) {
514                throw new UnsupportedOperationException();
515            }
516
517            @Override
518            public boolean remove(Object o) {
519                throw new UnsupportedOperationException();
520            }
521
522            @Override
523            public boolean containsAll(Collection<?> c) {
524                throw new UnsupportedOperationException();
525            }
526
527            @Override
528            public boolean addAll(Collection<? extends B> c) {
529                throw new UnsupportedOperationException();
530            }
531
532            @Override
533            public boolean removeAll(Collection<?> c) {
534                throw new UnsupportedOperationException();
535            }
536
537            @Override
538            public boolean retainAll(Collection<?> c) {
539                throw new UnsupportedOperationException();
540            }
541
542            @Override
543            public void clear() {
544                throw new UnsupportedOperationException();
545            }
546        };
547    }
548}
Note: See TracBrowser for help on using the repository browser.