Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.daisy.pipeline.braille.common.util Maven / Gradle / Ivy
package org.daisy.pipeline.braille.common;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;
import java.util.HashMap;
import java.util.Iterator;
import java.util.IllformedLocaleException;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.google.common.base.Function;
import static com.google.common.base.Functions.forPredicate;
import static com.google.common.base.Functions.toStringFunction;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import com.google.common.primitives.Bytes;
import org.daisy.common.file.URLs;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class util {
public static interface Function0 {
public T apply();
}
public static interface Function2 {
public T3 apply(T1 object1, T2 object2);
}
public static class Tuple2 {
public final T1 _1;
public final T2 _2;
public Tuple2(T1 _1, T2 _2) {
this._1 = _1;
this._2 = _2;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((_1 == null) ? 0 : _1.hashCode());
result = prime * result + ((_2 == null) ? 0 : _2.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Tuple2,?> other = (Tuple2,?>) obj;
if (_1 == null) {
if (other._1 != null)
return false;
} else if (!_1.equals(other._1))
return false;
if (_2 == null) {
if (other._2 != null)
return false;
} else if (!_2.equals(other._2))
return false;
return true;
}
}
public static class Tuple3 {
public final T1 _1;
public final T2 _2;
public final T3 _3;
public Tuple3(T1 _1, T2 _2, T3 _3) {
this._1 = _1;
this._2 = _2;
this._3 = _3;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((_1 == null) ? 0 : _1.hashCode());
result = prime * result + ((_2 == null) ? 0 : _2.hashCode());
result = prime * result + ((_3 == null) ? 0 : _3.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Tuple3,?,?> other = (Tuple3,?,?>) obj;
if (_1 == null) {
if (other._1 != null)
return false;
} else if (!_1.equals(other._1))
return false;
if (_2 == null) {
if (other._2 != null)
return false;
} else if (!_2.equals(other._2))
return false;
if (_3 == null) {
if (other._3 != null)
return false;
} else if (!_3.equals(other._3))
return false;
return true;
}
}
@FunctionalInterface
public static interface ThrowingSupplier extends Supplier {
@Override
default T get() {
try {
return getThrows();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
T getThrows() throws Throwable;
}
public static abstract class Functions {
public static Function0 noOp = new Function0 () {
public Void apply() { return null; }
};
public static Function sideEffect(final Function super F,?> function) {
return new Function() {
public Void apply(F input) {
function.apply(input);
return null;
}
};
}
public static Function doAll(final Iterable> functions) {
return new Function() {
public Void apply(F input) {
for (Function super F,Void> f : functions)
f.apply(input);
return null;
}
};
}
public static Supplier propagateException(ThrowingSupplier f, Function newEx) {
return new Supplier() {
public T get() throws E {
try {
return f.getThrows();
} catch (RuntimeException e) {
throw e;
} catch (Throwable e) {
throw newEx.apply(e);
}
}
};
}
}
public static abstract class Predicates {
private static Predicate matchesRegexPattern(final Pattern pattern) {
return new Predicate() {
public boolean apply(String s) {
return pattern.matcher(s).matches(); }};
}
public static Predicate matchesRegexPattern(final String pattern) {
return matchesRegexPattern(Pattern.compile(pattern));
}
public static Predicate matchesGlobPattern(final String pattern) {
return matchesRegexPattern(GlobPattern.compile(pattern));
}
}
public static abstract class Iterators {
public static T1 fold(Iterator iterator, Function2 super T1,? super T2,? extends T1> function, T1 seed) {
T1 result = seed;
while(iterator.hasNext()) result = function.apply(result, iterator.next());
return result;
}
public static T reduce(Iterator iterator, Function2 super T,? super T,? extends T> function) {
T seed = iterator.next();
return Iterators.fold(iterator, function, seed);
}
public static Tuple2,Collection> partition(Iterator iterator, Predicate super T> predicate) {
Multimap map = Multimaps.index(iterator, forPredicate(predicate));
return new Tuple2,Collection>(map.get(true), map.get(false));
}
}
public static abstract class Iterables {
public static Iterable memoize(final Iterable iterable) {
return new Memoize() {
protected Iterator _iterator() {
return iterable.iterator();
}
@Override
public String toString() {
return "memoize( " + iterable + " )";
}
};
}
protected static abstract class Memoize implements Iterable {
private final ArrayList cache = new ArrayList();
protected abstract Iterator _iterator();
private Iterator _iterator;
public final Iterator iterator() {
return new Iterator() {
private int index = 0;
public boolean hasNext() {
synchronized(cache) {
if (index < cache.size())
return true;
if (_iterator == null)
_iterator = _iterator();
return _iterator.hasNext();
}
}
public T next() throws NoSuchElementException {
synchronized(cache) {
if (index < cache.size())
return cache.get(index++);
if (_iterator == null)
_iterator = _iterator();
T next = _iterator.next();
cache.add(next);
index++;
return next;
}
}
public void remove() {
throw new UnsupportedOperationException();
}
};
}
}
public static Iterable clone(final Iterable iterable) {
return new Clone() {
protected Iterator _iterator() {
return iterable.iterator();
}
@Override
public String toString() {
return iterable.toString();
}
};
}
protected static abstract class Clone implements Iterable {
protected abstract Iterator _iterator();
public final Iterator iterator() {
return new AbstractIterator() {
Iterator iterator = _iterator();
@SuppressWarnings("unchecked")
protected T computeNext() {
T next;
try {
next = iterator.next(); }
catch (NoSuchElementException e) {
return endOfData(); }
try {
return (T)next.getClass().getMethod("clone").invoke(next); }
catch (IllegalAccessException
| IllegalArgumentException
| InvocationTargetException
| NoSuchMethodException
| SecurityException e) {
throw new RuntimeException("Could not invoke clone() method", e);
}
}
};
}
}
/**
* Returns all combinations of N items, where each item comes from a different map entry and
* N is the size of the map.
*/
public static Iterable> combinations(final Map> fromMap) {
if (fromMap.isEmpty())
return Collections.singleton(Collections.emptyMap());
return new Iterable>() {
public Iterator> iterator() {
return new AbstractIterator>() {
Map> iterators; {
iterators = new HashMap>();
for (K k : fromMap.keySet()) {
Iterator i = fromMap.get(k).iterator();
if (!i.hasNext())
throw new RuntimeException("Can't compute combinations. No iterables may be empty.");
iterators.put(k, i); }
}
Map currentMap = null;
protected Map computeNext() {
Map nextMap = new HashMap();
if (currentMap == null)
for (K k : fromMap.keySet())
nextMap.put(k, iterators.get(k).next());
else {
nextMap.putAll(currentMap);
Iterator keys = fromMap.keySet().iterator();
while (keys.hasNext()) {
K k = keys.next();
Iterator i = iterators.get(k);
if (i.hasNext()) {
nextMap.put(k, i.next());
break; }
else if (!keys.hasNext())
return endOfData();
else {
i = fromMap.get(k).iterator();
nextMap.put(k, i.next());
iterators.put(k, i); }}}
currentMap = nextMap;
return nextMap;
}
};
}
@Override
public String toString() {
return "combinations( " + fromMap + " )";
}
};
}
}
public static abstract class OS {
public static enum Family {
LINUX ("linux"),
MACOSX ("macosx"),
WINDOWS ("windows");
private final String name;
private Family(String name) { this.name = name; }
public String toString() { return name; }
}
public static Family getFamily() {
String name = System.getProperty("os.name").toLowerCase();
if (name.startsWith("windows"))
return Family.WINDOWS;
else if (name.startsWith("mac os x"))
return Family.MACOSX;
else if (name.startsWith("linux"))
return Family.LINUX;
else
throw new RuntimeException("Unsupported OS: " + name);
}
public static boolean isWindows() {
return getFamily() == Family.WINDOWS;
}
public static boolean isMacOSX() {
return getFamily() == Family.MACOSX;
}
public static String getArch() {
return System.getProperty("os.arch").toLowerCase();
}
public static boolean is64Bit() {
return getArch().equals("amd64")
|| getArch().equals("x86_64")
|| getArch().equals("aarch64")
|| getArch().equals("arm64");
}
}
public static abstract class Strings {
@SuppressWarnings(
"unchecked" // safe cast to Iterator
)
public static String join(Iterator extends T> strings, final Object separator, final Function super T,String> toStringFunction) {
if (!strings.hasNext()) return "";
String seed = toStringFunction.apply(strings.next());
return Iterators.fold(
(Iterator)strings,
new Function2() {
public String apply(String s1, T s2) {
return s1 + separator.toString() + toStringFunction.apply(s2); }},
seed);
}
public static String join(Iterator extends Object> strings, final Object separator) {
return join(strings, separator, toStringFunction());
}
public static String join(Iterable extends T> strings, final Object separator, final Function super T,String> toStringFunction) {
return join(strings.iterator(), separator, toStringFunction);
}
public static String join(Iterable> strings, final Object separator) {
return join(strings.iterator(), separator);
}
public static String join(Iterable> strings) {
return join(strings, "");
}
public static String join(T[] strings, Object separator, final Function super T,String> toStringFunction) {
return join(Arrays.asList(strings), separator, toStringFunction);
}
public static String join(Object[] strings, Object separator) {
return join(Arrays.asList(strings), separator);
}
public static String join(Object[] strings) {
return join(strings, "");
}
public static String normalizeSpace(Object object) {
return String.valueOf(object).replaceAll("\\s+", " ").trim();
}
public static Tuple2 extractHyphens(String text, boolean codePointBased, Character... characters) {
return extractHyphens(null, text, codePointBased, characters);
}
/**
* @param codePointBased Whether byte array index refers to code points or chars.
*/
public static Tuple2 extractHyphens(byte[] addTo, String text, boolean codePointBased, Character... characters) {
StringBuilder unhyphenatedText = new StringBuilder();
List hyphens = new ArrayList();
byte hyphen = 0;
int j = -1;
int[] charArray = codePointBased ? text.codePoints().toArray() : text.chars().toArray();
next_char: for (int c : charArray) {
j++;
if (addTo != null && j > 0)
hyphen |= addTo[j - 1];
for (int i = 0; i < characters.length; i++)
if (characters[i] != null && characters[i] == c) {
hyphen |= (1 << i);
continue next_char; }
unhyphenatedText.appendCodePoint(c);
hyphens.add(hyphen);
hyphen = 0; }
if (unhyphenatedText.length() > 0) {
hyphens.remove(0);
return new Tuple2(unhyphenatedText.toString(), Bytes.toArray(hyphens)); }
else
return new Tuple2("", null);
}
/**
* @param codePointBased Whether byte array index refers to code points or chars.
*/
public static String insertHyphens(String text, byte hyphens[], boolean codePointBased, Character... characters) {
if (text.equals("")) return "";
if (hyphens == null) return text;
int textLength = codePointBased ? text.codePoints().toArray().length : text.length();
if (hyphens.length != textLength - 1)
throw new RuntimeException("hyphens.length must be equal to text.length() - 1");
StringBuilder hyphenatedText = new StringBuilder();
int i = 0;
int j = 0;
for (Character c : text.toCharArray()) {
hyphenatedText.append(c);
if (j < hyphens.length && (!codePointBased || text.codePointAt(i) == c)) {
if (hyphens[j] != 0) {
for (int k = 0; k < characters.length; k++) {
byte b = (byte)(1 << k);
Character h = characters[k];
if (h != null && (hyphens[j] & b) == b)
hyphenatedText.append(h); }}
j++; }
i++; }
return hyphenatedText.toString();
}
public static Iterable splitInclDelimiter(final String text, final Pattern delimiterPattern) {
return new Iterable() {
public final Iterator iterator() {
return new AbstractIterator() {
Matcher m = delimiterPattern.matcher(text);
int i = 0;
String nextNext = null;
protected String computeNext() {
if (nextNext != null) {
String next = nextNext;
nextNext = null;
return next; }
if (m.find()) {
String next = text.substring(i, m.start());
nextNext = m.group();
i = m.end();
return next; }
else if (i >= 0) {
String next = text.substring(i);
i = -1;
return next; }
else
return endOfData();
}
};
}
};
}
}
public static abstract class Files {
/* If object is a String, it is assumed to represent a URI */
public static File asFile(Object o) {
if (o == null)
return null;
try {
if (o instanceof String)
return asFile(URLs.asURI((String)o));
if (o instanceof File)
return (File)o;
if (o instanceof URL)
return asFile(URLs.asURI((URL)o));
if (o instanceof URI)
return new File((URI)o); }
catch (Exception e) {}
throw new RuntimeException("Object can not be converted to File: " + o);
}
public static boolean isAbsoluteFile(Object o) {
if (o instanceof String)
return ((String)o).startsWith("file:");
try { asFile(o); }
catch (Exception e) { return false; }
return true;
}
public static String fileName(File file) {
return file.getName();
}
public static String fileName(URL url) {
String file = url.getFile();
return file.substring(file.lastIndexOf('/')+1);
}
public static File normalize(File file) {
try { return file.toPath().toRealPath().normalize().toFile(); }
catch (Exception e) { throw new RuntimeException(e); }
}
public static boolean unpack(URL url, File file) {
if (file.exists()) return false;
try {
file.getParentFile().mkdirs();
file.createNewFile();
FileOutputStream writer = new FileOutputStream(file);
url.openConnection();
InputStream reader = url.openStream();
byte[] buffer = new byte[153600];
int bytesRead = 0;
while ((bytesRead = reader.read(buffer)) > 0) {
writer.write(buffer, 0, bytesRead);
buffer = new byte[153600]; }
writer.close();
reader.close();
logger.debug("Unpacking file {} ...", file.getName());
return true; }
catch (Exception e) {
throw new RuntimeException(
"Exception occured during unpacking of file '" + file.getName() + "'", e); }
}
public static Iterable unpack(Iterator urls, File directory) {
if (!directory.exists()) directory.mkdirs();
Collection files = new ArrayList();
while(urls.hasNext()) {
URL url = urls.next();
File file = new File(directory.getAbsolutePath(), fileName(url));
if (unpack(url, file)) files.add(file); }
return files;
}
public static void chmod775(File file) {
if (OS.isWindows()) return;
try {
Runtime.getRuntime().exec(new String[] { "chmod", "775", file.getAbsolutePath() }).waitFor();
logger.debug("Chmodding file {} ...", file.getName());}
catch (Exception e) {
throw new RuntimeException(
"Exception occured during chmodding of file '" + file.getName() + "'", e); }
}
}
public static abstract class Locales {
public static Locale parseLocale(String locale) {
try {
return (new Locale.Builder()).setLanguageTag(locale.replace('_','-')).build(); }
catch (IllformedLocaleException e) {
throw new IllegalArgumentException("Locale '" + locale + "' could not be parsed", e); }
}
}
/*
* Naive implementation of glob syntax. Assumes the pattern is valid.
* @see http://docs.oracle.com/javase/tutorial/essential/io/fileOps.html#glob
*/
private static abstract class GlobPattern {
private static Pattern compile(String pattern) {
return new RegexBuilder(pattern).build();
}
private static class RegexBuilder {
private final StringCharacterIterator glob;
private boolean inClass;
private boolean inGroup;
private RegexBuilder(String globPattern) {
glob = new StringCharacterIterator(globPattern);
}
private Pattern build() {
StringBuilder regex = new StringBuilder();
regex.append('^');
inClass = false;
inGroup = false;
for (char c = glob.first(); c != CharacterIterator.DONE; c = glob.next()) {
if (!inClass) {
if (c == '[') {
regex.append("[[^/]&&[");
if (lookAhead() == '!')
regex.append(glob.next());
if (lookAhead() == '^')
regex.append("\\" + glob.next());
inClass = true; }
else if (c == '{' && !inGroup) {
regex.append("(?:(?:");
inGroup = true; }
else if (c == '}' && inGroup) {
regex.append("))");
inGroup = false; }
else if (c == ',' && inGroup)
regex.append(")|(?:");
else if (c == '*' && lookAhead() == '*') {
regex.append(".*");
glob.next(); }
else if (c == '*')
regex.append("[^/]*");
else if (c == '?')
regex.append("[^/]");
else if (".^$+]|()".indexOf(c) > -1)
regex.append("\\" + c);
else
regex.append(c); }
else {
if (c == ']') {
regex.append("]]");
inClass = false; }
else if (c == '&' && lookAhead() == '&')
regex.append("\\" + c + glob.next());
else if (c == '\\')
regex.append("\\" + c);
else
regex.append(c); }}
regex.append('$');
return Pattern.compile(regex.toString());
}
private char lookAhead() {
char la = glob.next();
glob.previous();
return la;
}
}
}
private static final Logger logger = LoggerFactory.getLogger(util.class);
}