package edu.uw.easysrl.util; import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; import com.google.common.collect.Multisets; import com.google.common.collect.Table; import com.google.common.primitives.Doubles; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.io.Serializable; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.function.BiFunction; import java.util.stream.Stream; import java.util.stream.StreamSupport; import java.util.zip.GZIPInputStream; public class Util { public static int indexOfAny(final String haystack, final String needles) { for (int i = 0; i < haystack.length(); i++) { for (int j = 0; j < needles.length(); j++) { if (haystack.charAt(i) == needles.charAt(j)) { return i; } } } return -1; } public static File getFile(final String path) { return new File(path.replace("~", System.getProperty("user.home"))); } public static File getHomeFolder() { return new File(System.getProperty("user.home")); } public static void serialize(final Object object, final File file) { try { final FileOutputStream fileOut = new FileOutputStream(file); final ObjectOutputStream out = new ObjectOutputStream(fileOut); out.writeObject(object); out.close(); fileOut.close(); } catch (final IOException e) { throw new RuntimeException(e); } } private final static DecimalFormat twoDP = new DecimalFormat("#.00");; @SuppressWarnings("unused") private final static DecimalFormat exponentialFormat = new DecimalFormat("0.#E0"); public static String twoDP(final double number) { return twoDP.format(number); } @SuppressWarnings("unchecked") public static <O> O deserialize(final File file) { O o = null; try { final FileInputStream fileIn = new FileInputStream(file); final ObjectInputStream in = new ObjectInputStream(fileIn); o = (O) in.readObject(); in.close(); fileIn.close(); return o; } catch (IOException | ClassNotFoundException e) { throw new RuntimeException(e); } } public static Iterable<String> readFile(final File filePath) throws java.io.IOException { return new Iterable<String>() { @Override public Iterator<String> iterator() { try { return readFileLineByLine(filePath); } catch (final IOException e) { throw new RuntimeException(e); } } }; } public static String executeCommand(final String command) throws IOException { final Process process = Runtime.getRuntime().exec(new String[] { "/bin/sh", "-c", command }); final BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); final StringBuilder output = new StringBuilder(); String line; while ((line = input.readLine()) != null) { output.append(line); output.append("\n"); } input.close(); return output.toString(); } public static <T extends Comparable<T>> int compareSortedArrays(final T[] t1, final T[] t2) { if (t1.length != t2.length) { return t1.length - t2.length; } for (int i = 0; i < t1.length; i++) { final int result = t1[i].compareTo(t2[i]); if (result != 0) { return result; } } return 0; } public static void writeStringToFile(final String text, final File filePath) throws java.io.IOException { final BufferedWriter out = new BufferedWriter(new FileWriter(filePath)); out.write(text); out.close(); } public static Iterator<String> readFileLineByLine(final File filePath) throws java.io.IOException { return new Iterator<String>() { // Open the file that is the first // command line parameter InputStream fstream = new FileInputStream(filePath); { if (filePath.getName().endsWith(".gz")) { // Automatically unzip zipped files. fstream = new GZIPInputStream(fstream); } } // Get the object of DataInputStream DataInputStream in = new DataInputStream(fstream); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String next = br.readLine(); @Override public boolean hasNext() { final boolean result = (next != null); if (!result) { try { br.close(); } catch (final IOException e) { throw new RuntimeException(e); } } return result; } @Override public String next() { final String result = next; try { next = br.readLine(); } catch (final IOException e) { throw new RuntimeException(e); } return result; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } public static String dropBrackets(final String cat) { if (cat.startsWith("(") && cat.endsWith(")") && findClosingBracket(cat) == cat.length() - 1) { return cat.substring(1, cat.length() - 1); } else { return cat; } } public static int findClosingBracket(final String source) { return findClosingBracket(source, 0); } public static int findClosingBracket(final String source, final int startIndex) { int openBrackets = 0; for (int i = startIndex; i < source.length(); i++) { if (source.charAt(i) == '(') { openBrackets++; } else if (source.charAt(i) == ')') { openBrackets--; } if (openBrackets == 0) { return i; } } throw new Error("Mismatched brackets in string: " + source); } /** * Finds the first index of a needle character in the haystack, that is not nested in brackets. */ public static int findNonNestedChar(final String haystack, final String needles) { int openBrackets = 0; for (int i = 0; i < haystack.length(); i++) { if (haystack.charAt(i) == '(' || haystack.charAt(i) == '[' || haystack.charAt(i) == '{') { openBrackets++; } else if (haystack.charAt(i) == ')' || haystack.charAt(i) == ']' || haystack.charAt(i) == '}') { openBrackets--; } else if (openBrackets == 0) { for (int j = 0; j < needles.length(); j++) { if (haystack.charAt(i) == needles.charAt(j)) { return i; } } } } return -1; } public static List<File> findAllFiles(final File folder, final String regex) { return Util.findAllFiles(folder, new FilenameFilter() { @Override public boolean accept(final File dir, final String name) { return name.matches(regex); } }); } private static List<File> findAllFiles(final File folder, final FilenameFilter filter) { final List<File> result = new ArrayList<>(); findAllFiles(folder, filter, result); return result; } private static void findAllFiles(final File folder, final FilenameFilter filter, final List<File> result) { final File[] files = folder.listFiles(); if (files != null) { for (final File file : files) { if (file.isDirectory()) { findAllFiles(file, filter, result); } else if (filter.accept(file, file.getName())) { result.add(file.getAbsoluteFile()); } } } } public static class LruCache<A> extends LinkedHashMap<A, A> { /** * */ private static final long serialVersionUID = 1L; private final int maxEntries; public LruCache(final int maxEntries) { super(maxEntries + 1, 1.0f, true); this.maxEntries = maxEntries; } /** * Returns <tt>true</tt> if this <code>LruCache</code> has more entries than the maximum specified when it was * created. * * <p> * This method <em>does not</em> modify the underlying <code>Map</code>; it relies on the implementation of * <code>LinkedHashMap</code> to do that, but that behavior is documented in the JavaDoc for * <code>LinkedHashMap</code>. * </p> * * @param eldest * the <code>Entry</code> in question; this implementation doesn't care what it is, since the * implementation is only dependent on the size of the cache * @return <tt>true</tt> if the oldest * @see java.util.LinkedHashMap#removeEldestEntry(Map.Entry) */ @Override protected boolean removeEldestEntry(final Map.Entry<A, A> eldest) { return super.size() > maxEntries; } public A getCached(final A key) { A result = get(key); if (result == null) { result = key; put(result, result); } return result; } } public static double[] subtract(final double[] vector1, final double[] vector2) { assert (vector1.length == vector2.length); final double[] result = new double[vector1.length]; for (int i = 0; i < vector1.length; i++) { result[i] = vector1[i] - vector2[i]; } return result; } public static void add(final double[] vector1, final double[] vector2) { assert (vector1.length == vector2.length); for (int i = 0; i < vector1.length; i++) { vector1[i] = vector1[i] + vector2[i]; } } public static class Logger implements Serializable { /** * */ private static final long serialVersionUID = 1L; private final File file; private final SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss"); public Logger(final File file) { this.file = file; } public void log(final String message) { try (PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file, true)))) { final String toWrite = format.format(Calendar.getInstance().getTime()) + "\t" + message; System.err.println(toWrite); out.println(toWrite); } catch (final IOException e) { System.err.println("ERROR WRITING TO LOG FILE: " + file.getAbsolutePath()); } } } public static <R, C, V> void add(final Table<R, C, Multiset<V>> table, final R row, final C column, final V value) { Multiset<V> multiset = table.get(row, column); if (multiset == null) { multiset = HashMultiset.create(); table.put(row, column, multiset); } multiset.add(value); } public static <K, V> void add(final Map<K, Multiset<V>> map, final K key, final V value) { Multiset<V> multiset = map.get(key); if (multiset == null) { multiset = HashMultiset.create(); map.put(key, multiset); } multiset.add(value); } public static boolean isCapitalized(final String word) { final char c = word.charAt(0); return 'A' <= c && c <= 'Z'; } public static class Scored<T> implements Comparable<Scored<T>> { private final T object; private final double score; @Override public int compareTo(final Scored<T> o) { return Doubles.compare(o.score, score); } public Scored(final T object, final double score) { super(); this.object = object; this.score = score; } public T getObject() { return object; } public double getScore() { return score; } } public static void runJobsInParallel(final Collection<Runnable> tasks, final int numThreads) { final ExecutorService executor = Executors.newFixedThreadPool(numThreads); try { final List<Future<?>> futures = new ArrayList<>(tasks.size()); for (final Runnable task : tasks) { futures.add(executor.submit(task)); } for (final Future<?> future : futures) { future.get(); } executor.shutdown(); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); throw new RuntimeException(e); } } public static void runInBackground(final Runnable task) { final ExecutorService executor = Executors.newSingleThreadExecutor(); executor.submit(task); } public static String percentage(final int count, final int size) { return Util.twoDP((100.0 * count / size)) + "%"; } public static <T> void print(final Multiset<T> multiset, final int number) { int i = 0; for (final T type : Multisets.copyHighestCountFirst(multiset).elementSet()) { System.out.println(type + ": " + multiset.count(type)); i++; if (i == number) { break; } } System.out.println(); } public static void debugHook() { } public static Properties loadProperties(final File file) { try { final Properties defaultProps = new Properties(); final FileInputStream in = new FileInputStream(file); defaultProps.load(in); in.close(); return defaultProps; } catch (final IOException e) { throw new RuntimeException(e); } } public static String maybeBracket(final String input, final boolean bracket) { return bracket ? "(" + input + ")" : input; } // zip(Stream.of("a", "b", "c"), Stream.of("1", "2", "3"), (x,y) -> x + y) // returns // Stream.of("a1", "b2", "c3") public static <A, B, C> Stream<C> zip(Stream<? extends A> a, Stream<? extends B> b, BiFunction<? super A, ? super B, ? extends C> zipper) { final Iterator<? extends A> iteratorA = a.iterator(); final Iterator<? extends B> iteratorB = b.iterator(); final Iterable<C> iterable = () -> new Iterator<C>() { @Override public boolean hasNext() { return iteratorA.hasNext() && iteratorB.hasNext(); } @Override public C next() { return zipper.apply(iteratorA.next(), iteratorB.next()); } }; return StreamSupport.stream(iterable.spliterator(), a.isParallel() || b.isParallel()); } }