All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.rapidoid.u.U Maven / Gradle / Ivy

The newest version!
package org.rapidoid.u;

/*
 * #%L
 * rapidoid-u
 * %%
 * Copyright (C) 2014 - 2016 Nikolche Mihajlovski and contributors
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */

import org.rapidoid.lambda.Dynamic;
import org.rapidoid.lambda.Mapper;

import java.io.File;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author Nikolche Mihajlovski
 * @since 2.0.0
 */
public class U {

	public static String str(Object obj) {
		if (obj == null) {
			return "null";
		} else if (obj instanceof byte[]) {
			return Arrays.toString((byte[]) obj);
		} else if (obj instanceof short[]) {
			return Arrays.toString((short[]) obj);
		} else if (obj instanceof int[]) {
			return Arrays.toString((int[]) obj);
		} else if (obj instanceof long[]) {
			return Arrays.toString((long[]) obj);
		} else if (obj instanceof float[]) {
			return Arrays.toString((float[]) obj);
		} else if (obj instanceof double[]) {
			return Arrays.toString((double[]) obj);
		} else if (obj instanceof boolean[]) {
			return Arrays.toString((boolean[]) obj);
		} else if (obj instanceof char[]) {
			return Arrays.toString((char[]) obj);
		} else if (obj instanceof Object[]) {
			return str((Object[]) obj);
		} else {
			return String.valueOf(obj);
		}
	}

	public static String str(Object[] objs) {
		StringBuilder sb = new StringBuilder();
		sb.append("[");

		for (int i = 0; i < objs.length; i++) {
			if (i > 0) {
				sb.append(", ");
			}
			sb.append(str(objs[i]));
		}

		sb.append("]");

		return sb.toString();
	}

	public static String str(Iterable coll) {
		StringBuilder sb = new StringBuilder();
		sb.append("[");

		boolean first = true;

		for (Object obj : coll) {
			if (!first) {
				sb.append(", ");
			}

			sb.append(str(obj));
			first = false;
		}

		sb.append("]");
		return sb.toString();
	}

	public static String str(Iterator it) {
		StringBuilder sb = new StringBuilder();
		sb.append("[");

		boolean first = true;

		while (it.hasNext()) {
			if (first) {
				sb.append(", ");
				first = false;
			}

			sb.append(str(it.next()));
		}

		sb.append("]");

		return sb.toString();
	}

	public static String frmt(String format, Object... args) {
		for (int i = 0; i < args.length; i++) {
			if (!(args[i] instanceof Number)) {
				args[i] = str(args[i]);
			}
		}

		return String.format(format, args);
	}

	public static String replace(String s, String[][] repls) {
		for (String[] repl : repls) {
			U.must(repl.length == 2, "Expected pairs of [search, replacement] strings!");
			s = s.replaceAll(Pattern.quote(repl[0]), repl[1]);
		}

		return s;
	}

	public static String replace(String s, String regex, Mapper replacer) {
		StringBuffer output = new StringBuffer();
		Pattern p = Pattern.compile(regex);
		Matcher matcher = p.matcher(s);

		while (matcher.find()) {
			int len = matcher.groupCount() + 1;
			String[] groups = new String[len];

			for (int i = 0; i < groups.length; i++) {
				groups[i] = matcher.group(i);
			}

			Object value;
			try {
				value = replacer.map(groups);
			} catch (Exception e) {
				throw rte(e);
			}

			matcher.appendReplacement(output, str(value));
		}

		matcher.appendTail(output);
		return output.toString();
	}

	public static void print(Object... values) {
		String text;

		if (values != null) {
			text = values.length == 1 ? str(values[0]) : str(values);
		} else {
			text = "null";
		}

		System.out.println(text);
	}

	@SuppressWarnings({"varargs"})
	public static  String join(String sep, T... items) {
		return render(items, "%s", sep);
	}

	public static String join(String sep, Iterable items) {
		return render(items, "%s", sep);
	}

	public static String join(String sep, char[][] items) {
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < items.length; i++) {
			if (i > 0) {
				sb.append(sep);
			}
			sb.append(items[i]);
		}

		return sb.toString();
	}

	public static String render(Object[] items, String itemFormat, String sep) {
		StringBuilder sb = new StringBuilder();

		for (int i = 0; i < items.length; i++) {
			if (i > 0) {
				sb.append(sep);
			}
			sb.append(frmt(itemFormat, items[i]));
		}

		return sb.toString();
	}

	public static String render(Iterable items, String itemFormat, String sep) {
		StringBuilder sb = new StringBuilder();

		int i = 0;
		Iterator it = items.iterator();
		while (it.hasNext()) {
			Object item = it.next();
			if (i > 0) {
				sb.append(sep);
			}

			sb.append(frmt(itemFormat, item));
			i++;
		}

		return sb.toString();
	}

	public static  Iterator iterator(T[] arr) {
		return Arrays.asList(arr).iterator();
	}

	@SuppressWarnings({"varargs"})
	public static  T[] array(T... items) {
		return items;
	}

	public static Object[] array(Iterable items) {
		return (items instanceof Collection) ? ((Collection) items).toArray() : list(items).toArray();
	}

	@SuppressWarnings("unchecked")
	public static  Set synchronizedSet() {
		return (Set) Collections.synchronizedSet(set());
	}

	public static  Set set() {
		return new LinkedHashSet();
	}

	public static  Set set(Iterable values) {
		Set set = set();

		for (T val : values) {
			set.add(val);
		}

		return set;
	}

	@SuppressWarnings({"varargs"})
	public static  Set set(T... values) {
		Set set = set();

		for (T val : values) {
			set.add(val);
		}

		return set;
	}

	@SuppressWarnings("unchecked")
	public static  List synchronizedList() {
		return (List) Collections.synchronizedList(list());
	}

	public static  List list() {
		return new ArrayList();
	}

	public static  List list(Iterable values) {
		List list = list();

		for (T item : values) {
			list.add(item);
		}

		return list;
	}

	@SuppressWarnings({"varargs"})
	public static  List list(T... values) {
		List list = list();

		for (T item : values) {
			list.add(item);
		}

		return list;
	}

	public static  Map map() {
		return new LinkedHashMap();
	}

	public static  Map map(Map src) {
		Map map = map();
		map.putAll(src);
		return map;
	}

	public static  Map map(K key, V value) {
		Map map = map();
		map.put(key, value);
		return map;
	}

	public static  Map map(K key1, V value1, K key2, V value2) {
		Map map = map(key1, value1);
		map.put(key2, value2);
		return map;
	}

	public static  Map map(K key1, V value1, K key2, V value2, K key3, V value3) {
		Map map = map(key1, value1, key2, value2);
		map.put(key3, value3);
		return map;
	}

	public static  Map map(K key1, V value1, K key2, V value2, K key3, V value3, K key4, V value4) {
		Map map = map(key1, value1, key2, value2, key3, value3);
		map.put(key4, value4);
		return map;
	}

	public static  Map map(K key1, V value1, K key2, V value2, K key3, V value3, K key4, V value4, K key5,
	                                   V value5) {
		Map map = map(key1, value1, key2, value2, key3, value3, key4, value4);
		map.put(key5, value5);
		return map;
	}

	@SuppressWarnings("unchecked")
	public static  Map map(Object... keysAndValues) {
		must(keysAndValues.length % 2 == 0, "Incorrect number of arguments (expected key-value pairs)!");

		Map map = map();

		for (int i = 0; i < keysAndValues.length / 2; i++) {
			map.put((K) keysAndValues[i * 2], (V) keysAndValues[i * 2 + 1]);
		}

		return map;
	}

	public static  ConcurrentMap concurrentMap() {
		return new ConcurrentHashMap();
	}

	public static  ConcurrentMap concurrentMap(Map src, boolean ignoreNullValues) {
		ConcurrentMap map = concurrentMap();

		for (Entry e : src.entrySet()) {
			if (!ignoreNullValues || e.getValue() != null) {
				map.put(e.getKey(), e.getValue());
			}
		}

		return map;
	}

	public static  ConcurrentMap concurrentMap(K key, V value) {
		ConcurrentMap map = concurrentMap();
		map.put(key, value);
		return map;
	}

	public static  ConcurrentMap concurrentMap(K key1, V value1, K key2, V value2) {
		ConcurrentMap map = concurrentMap(key1, value1);
		map.put(key2, value2);
		return map;
	}

	public static  ConcurrentMap concurrentMap(K key1, V value1, K key2, V value2, K key3, V value3) {
		ConcurrentMap map = concurrentMap(key1, value1, key2, value2);
		map.put(key3, value3);
		return map;
	}

	public static  ConcurrentMap concurrentMap(K key1, V value1, K key2, V value2, K key3, V value3,
	                                                       K key4, V value4) {
		ConcurrentMap map = concurrentMap(key1, value1, key2, value2, key3, value3);
		map.put(key4, value4);
		return map;
	}

	public static  ConcurrentMap concurrentMap(K key1, V value1, K key2, V value2, K key3, V value3,
	                                                       K key4, V value4, K key5, V value5) {
		ConcurrentMap map = concurrentMap(key1, value1, key2, value2, key3, value3, key4, value4);
		map.put(key5, value5);
		return map;
	}

	@SuppressWarnings("unchecked")
	public static  ConcurrentMap concurrentMap(Object... keysAndValues) {
		must(keysAndValues.length % 2 == 0, "Incorrect number of arguments (expected key-value pairs)!");

		ConcurrentMap map = concurrentMap();

		for (int i = 0; i < keysAndValues.length / 2; i++) {
			map.put((K) keysAndValues[i * 2], (V) keysAndValues[i * 2 + 1]);
		}

		return map;
	}

	public static  Map orderedMap() {
		return new LinkedHashMap();
	}

	public static  Map orderedMap(Map src, boolean ignoreNullValues) {
		Map map = orderedMap();

		for (Entry e : src.entrySet()) {
			if (!ignoreNullValues || e.getValue() != null) {
				map.put(e.getKey(), e.getValue());
			}
		}

		return map;
	}

	public static  Map orderedMap(K key, V value) {
		Map map = orderedMap();
		map.put(key, value);
		return map;
	}

	public static  Map orderedMap(K key1, V value1, K key2, V value2) {
		Map map = orderedMap(key1, value1);
		map.put(key2, value2);
		return map;
	}

	public static  Map orderedMap(K key1, V value1, K key2, V value2, K key3, V value3) {
		Map map = orderedMap(key1, value1, key2, value2);
		map.put(key3, value3);
		return map;
	}

	public static  Map orderedMap(K key1, V value1, K key2, V value2, K key3, V value3, K key4, V value4) {
		Map map = orderedMap(key1, value1, key2, value2, key3, value3);
		map.put(key4, value4);
		return map;
	}

	public static  Map orderedMap(K key1, V value1, K key2, V value2, K key3, V value3, K key4, V value4,
	                                          K key5, V value5) {
		Map map = orderedMap(key1, value1, key2, value2, key3, value3, key4, value4);
		map.put(key5, value5);
		return map;
	}

	@SuppressWarnings("unchecked")
	public static  Map orderedMap(Object... keysAndValues) {
		must(keysAndValues.length % 2 == 0, "Incorrect number of arguments (expected key-value pairs)!");

		Map map = orderedMap();

		for (int i = 0; i < keysAndValues.length / 2; i++) {
			map.put((K) keysAndValues[i * 2], (V) keysAndValues[i * 2 + 1]);
		}

		return map;
	}

	public static  Map synchronizedMap() {
		return Collections.synchronizedMap(U.map());
	}

	public static  Queue queue() {
		return new ConcurrentLinkedQueue();
	}

	public static  BlockingQueue queue(int maxSize) {
		argMust(maxSize > 0, "Maximum queue size must be > 0!");
		return new ArrayBlockingQueue(maxSize);
	}

	public static  T or(T value, T fallback) {
		return value != null ? value : fallback;
	}

	public static String safe(String s) {
		return or(s, "");
	}

	public static boolean safe(Boolean b) {
		return or(b, false);
	}

	public static int safe(Integer num) {
		return or(num, 0);
	}

	public static long safe(Long num) {
		return or(num, 0L);
	}

	public static byte safe(Byte num) {
		return or(num, (byte) 0);
	}

	public static float safe(Float num) {
		return or(num, 0.0f);
	}

	public static double safe(Double num) {
		return or(num, 0.0);
	}

	public static Object[] safe(Object[] arr) {
		return arr != null ? arr : new Object[0];
	}

	public static  List safe(List list) {
		return list != null ? list : U.list();
	}

	public static  Set safe(Set set) {
		return set != null ? set : U.set();
	}

	public static  Map safe(Map map) {
		return map != null ? map : U.map();
	}

	public static long time() {
		return System.currentTimeMillis();
	}

	public static boolean xor(boolean a, boolean b) {
		return a && !b || b && !a;
	}

	public static boolean eq(Object a, Object b) {
		return a == null ? b == null : a.equals(b);
	}

	public static RuntimeException rte(String message) {
		return new RuntimeException(message);
	}

	public static RuntimeException rte(String message, Throwable cause) {
		return new RuntimeException(message, cause);
	}

	public static RuntimeException rte(Throwable cause) {
		return rte("", cause);
	}

	public static RuntimeException rte(String message, Object... args) {
		return rte(frmt(message, args));
	}

	public static RuntimeException notExpected() {
		return rte("This operation is not expected to be called!");
	}

	public static RuntimeException notReady() {
		return rte("Not yet implemented!");
	}

	public static RuntimeException notSupported() {
		return rte("This operation is not supported by this implementation!");
	}

	public static void rteIf(boolean failureCondition, String msg) {
		if (failureCondition) {
			throw rte(msg);
		}
	}

	public static boolean must(boolean expectedCondition, String message) {
		if (!expectedCondition) {
			throw rte(message);
		}
		return true;
	}

	public static RuntimeException rte(String message, Throwable cause, Object... args) {
		return rte(frmt(message, args), cause);
	}

	public static boolean must(boolean expectedCondition) {
		if (!expectedCondition) {
			throw rte("Expectation failed!");
		}
		return true;
	}

	public static boolean must(boolean expectedCondition, String message, long arg) {
		if (!expectedCondition) {
			throw rte(message, arg);
		}
		return true;
	}

	public static boolean must(boolean expectedCondition, String message, Object arg) {
		if (!expectedCondition) {
			throw rte(message, str(arg));
		}
		return true;
	}

	public static boolean must(boolean expectedCondition, String message, Object arg1, Object arg2) {
		if (!expectedCondition) {
			throw rte(message, str(arg1), str(arg2));
		}
		return true;
	}

	public static boolean must(boolean expectedCondition, String message, Object arg1, Object arg2, Object arg3) {
		if (!expectedCondition) {
			throw rte(message, str(arg1), str(arg2), str(arg3));
		}
		return true;
	}

	public static IllegalArgumentException illegalArg(String message, Object... args) {
		return new IllegalArgumentException(frmt(message, args));
	}

	public static void secure(boolean condition, String msg) {
		if (!condition) {
			throw new SecurityException(str(msg));
		}
	}

	public static void secure(boolean condition, String msg, Object arg) {
		if (!condition) {
			throw new SecurityException(frmt(msg, arg));
		}
	}

	public static void secure(boolean condition, String msg, Object arg1, Object arg2) {
		if (!condition) {
			throw new SecurityException(frmt(msg, arg1, arg2));
		}
	}

	public static void bounds(int value, int min, int max) {
		must(value >= min && value <= max, "%s is not in the range [%s, %s]!", value, min, max);
	}

	public static  T notNull(T value, String msgOrDesc, Object... descArgs) {
		if (value == null) {
			throw rte("%s must NOT be null!", frmt(msgOrDesc, descArgs));
		}

		return value;
	}

	public static boolean isEmpty(String value) {
		return value == null || value.isEmpty();
	}

	public static boolean isEmpty(Object[] arr) {
		return arr == null || arr.length == 0;
	}

	public static boolean isEmpty(Collection coll) {
		return coll == null || coll.isEmpty();
	}

	public static boolean isEmpty(Iterable iter) {
		return iter.iterator().hasNext();
	}

	public static boolean isEmpty(Map map) {
		return map == null || map.isEmpty();
	}

	public static boolean isEmpty(Object value) {
		if (value == null) {
			return true;
		} else if (value instanceof String) {
			return isEmpty((String) value);
		} else if (value instanceof byte[]) {
			return ((byte[]) value).length == 0;
		} else if (value instanceof short[]) {
			return ((short[]) value).length == 0;
		} else if (value instanceof int[]) {
			return ((int[]) value).length == 0;
		} else if (value instanceof long[]) {
			return ((long[]) value).length == 0;
		} else if (value instanceof float[]) {
			return ((float[]) value).length == 0;
		} else if (value instanceof double[]) {
			return ((double[]) value).length == 0;
		} else if (value instanceof boolean[]) {
			return ((boolean[]) value).length == 0;
		} else if (value instanceof char[]) {
			return ((char[]) value).length == 0;
		} else if (value instanceof Object[]) {
			return ((Object[]) value).length == 0;
		} else if (value instanceof Collection) {
			return isEmpty((Collection) value);
		} else if (value instanceof Map) {
			return isEmpty((Map) value);
		} else if (value instanceof Iterable) {
			return isEmpty((Iterable) value);
		}
		return false;
	}

	public static boolean notEmpty(String value) {
		return !isEmpty(value);
	}

	public static boolean notEmpty(Object[] arr) {
		return !isEmpty(arr);
	}

	public static boolean notEmpty(Collection coll) {
		return !isEmpty(coll);
	}

	public static boolean notEmpty(Iterable iter) {
		return !isEmpty(iter);
	}

	public static boolean notEmpty(Map map) {
		return !isEmpty(map);
	}

	public static boolean notEmpty(Object value) {
		return !isEmpty(value);
	}

	public static String capitalized(String s) {
		return s.isEmpty() ? s : s.substring(0, 1).toUpperCase() + s.substring(1);
	}

	public static String uncapitalized(String s) {
		return s.isEmpty() ? s : s.substring(0, 1).toLowerCase() + s.substring(1);
	}

	public static String mul(String s, int n) {
		StringBuffer sb = new StringBuffer();

		for (int i = 0; i < n; i++) {
			sb.append(s);
		}

		return sb.toString();
	}

	public static String mid(String s, int beginIndex, int endIndex) {
		if (endIndex < 0) {
			endIndex = s.length() + endIndex;
		}
		return s.substring(beginIndex, endIndex);
	}

	public static String insert(String target, int atIndex, String insertion) {
		return target.substring(0, atIndex) + insertion + target.substring(atIndex);
	}

	public static int num(String s) {
		return Integer.parseInt(s);
	}

	public static int bounded(int min, int value, int max) {
		return Math.min(Math.max(min, value), max);
	}

	public static  T single(Iterable coll) {
		Iterator it = coll.iterator();
		must(it.hasNext(), "Expected exactly 1 item, but didn't find any!");
		T item = it.next();
		must(!it.hasNext(), "Expected exactly 1 item, but found more than 1!");
		return item;
	}

	public static  T singleOrNone(Iterable coll) {
		Iterator it = coll.iterator();
		T item = it.hasNext() ? it.next() : null;
		must(!it.hasNext(), "Expected 0 or 1 items, but found more than 1!");
		return item;
	}

	public static  T first(T[] values) {
		return values != null && values.length > 0 ? values[0] : null;
	}

	public static  T first(List values) {
		return values != null && values.size() > 0 ? values.get(0) : null;
	}

	public static  T last(T[] values) {
		return values != null && values.length > 0 ? values[values.length - 1] : null;
	}

	public static  T last(List values) {
		return values != null && values.size() > 0 ? values.get(values.size() - 1) : null;
	}

	@SuppressWarnings("unchecked")
	public static  int compare(T val1, T val2) {
		if (val1 == null && val2 == null) {
			return 0;
		} else if (val1 == null) {
			return -1;
		} else if (val2 == null) {
			return 1;
		} else {
			return ((Comparable) val1).compareTo(val2);
		}
	}

	public static  List range(Iterable items, int fromIndex, int toIndex) {
		// TODO more efficient implementation
		List list = list(items);

		fromIndex = bounded(0, fromIndex, list.size());
		toIndex = bounded(fromIndex, toIndex, list.size());

		return list(list.subList(fromIndex, toIndex));
	}

	public static  List page(Iterable items, int page, int pageSize) {
		return range(items, (page - 1) * pageSize, page * pageSize);
	}

	public static String trimr(String s, char suffix) {
		return (!s.isEmpty() && s.charAt(s.length() - 1) == suffix) ? mid(s, 0, -1) : s;
	}

	public static String trimr(String s, String suffix) {
		return s.endsWith(suffix) ? mid(s, 0, -suffix.length()) : s;
	}

	public static String triml(String s, char prefix) {
		return (!s.isEmpty() && s.charAt(0) == prefix) ? s.substring(1) : s;
	}

	public static String triml(String s, String prefix) {
		return s.startsWith(prefix) ? s.substring(prefix.length()) : s;
	}

	public static void argMust(boolean expectedCondition, String message, Object... args) {
		if (!expectedCondition) {
			throw illegalArg(message, args);
		}
	}

	/**
	 * Sleeps (calling Thread.sleep) for the specified period.
	 * 

* If the thread is interrupted while sleeping, throws {@link CancellationException} to propagate the interruption. * * @param millis the length of time to sleep in milliseconds. */ public static void sleep(long millis) { try { Thread.sleep(millis); } catch (InterruptedException e) { throw new CancellationException(); } } public static Map autoExpandingMap(final Class clazz) { return autoExpandingMap(new Mapper() { @SuppressWarnings("unchecked") @Override public V map(K src) throws Exception { try { return (V) clazz.newInstance(); } catch (Exception e) { throw rte(e); } } }); } @SuppressWarnings("serial") public static Map autoExpandingMap(final Mapper valueFactory) { return Collections.synchronizedMap(new HashMap() { @SuppressWarnings("unchecked") @Override public synchronized V get(Object key) { V val = super.get(key); if (val == null) { try { val = valueFactory.map((K) key); } catch (Exception e) { throw rte(e); } put((K) key, val); } return val; } }); } public static Map> mapOfMaps() { return autoExpandingMap(new Mapper>() { @Override public Map map(K1 src) throws Exception { return synchronizedMap(); } }); } public static Map> mapOfLists() { return autoExpandingMap(new Mapper>() { @Override public List map(K src) throws Exception { return Collections.synchronizedList(U.list()); } }); } public static Map> mapOfSets() { return autoExpandingMap(new Mapper>() { @Override public Set map(K src) throws Exception { return Collections.synchronizedSet(U.set()); } }); } /** * Simpler casts, less warnings. */ @SuppressWarnings("unchecked") public static T cast(Object value) { return (T) value; } public static void wait(CountDownLatch latch) { try { latch.await(); } catch (InterruptedException e) { throw new CancellationException(); } } public static void wait(CountDownLatch latch, long timeout, TimeUnit unit) { try { latch.await(timeout, unit); } catch (InterruptedException e) { throw new CancellationException(); } } @SuppressWarnings("unchecked") public static T dynamic(final Class targetInterface, final Dynamic dynamic) { final Object obj = new Object(); InvocationHandler handler = new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.getDeclaringClass().equals(Object.class)) { if (method.getName().equals("toString")) { return targetInterface.getSimpleName() + "@" + Integer.toHexString(obj.hashCode()); } return method.invoke(obj, args); } return dynamic.call(method, safe(args)); } }; return ((T) Proxy.newProxyInstance(targetInterface.getClassLoader(), new Class[]{targetInterface}, handler)); } @SuppressWarnings({"varargs"}) public static boolean isIn(T value, T... candidates) { for (T candidate : candidates) { if (eq(value, candidate)) { return true; } } return false; } public static Is is(T value) { return new Is(value); } public static boolean exists(Callable accessChain) { try { return accessChain != null && accessChain.call() != null; } catch (NullPointerException e) { return false; } catch (Exception e) { throw U.rte(e); } } public static String uri(String... parts) { return "/" + constructPath("/", false, parts); } public static String path(String... parts) { return constructPath(File.separator, true, parts); } private static String constructPath(String separator, boolean preserveFirstSegment, String... parts) { String s = ""; for (int i = 0; i < parts.length; i++) { String part = U.safe(parts[i]); // trim '/'s and '\'s if (!preserveFirstSegment || i > 0) { part = triml(part, "/"); } if (!preserveFirstSegment || part.length() > 1 || i > 0) { part = trimr(part, "/"); part = trimr(part, "\\"); } if (!U.isEmpty(part)) { if (!s.isEmpty() && !s.endsWith(separator)) { s += separator; } s += part; } } return s; } public static boolean isMap(Object obj) { return obj instanceof Map; } public static boolean isList(Object obj) { return obj instanceof List; } public static boolean isSet(Object obj) { return obj instanceof Set; } public static boolean isCollection(Object obj) { return obj instanceof Collection; } public static void assign(Collection destination, Collection source) { if (destination != null && source != null) { destination.clear(); destination.addAll(source); } } public static void assign(Map destination, Map source) { if (destination != null && source != null) { destination.clear(); destination.putAll(source); } } public static V get(Map map, K key) { V value = map.get(key); notNull(value, "map[%s]", key); return value; } public static V get(Map map, K key, V defaultValue) { V value = map.get(key); return value != null ? value : defaultValue; } }