io.github.jdcmp.codegen.Utils Maven / Gradle / Ivy
package io.github.jdcmp.codegen;
import io.github.jdcmp.api.documentation.ThreadSafe;
import org.jetbrains.annotations.Nullable;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles.Lookup;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
@ThreadSafe
final class Utils {
private static final @Nullable MethodHandle LOOKUP_ACCESS_CLASS = Internals.Lookup.Method.ACCESS_CLASS.tryFind().orElse(null);
public static void verifyLookupCanAccess(Lookup lookup, Class> classToBeAccessed) throws IllegalAccessException {
MethodHandle accessClass = LOOKUP_ACCESS_CLASS;
if (accessClass != null) {
ThrowableRunnable.run(() -> {
Class> ignored = (Class>) accessClass.invokeExact(lookup, classToBeAccessed);
});
return;
}
if (lookup.in(classToBeAccessed).lookupModes() == 0) {
throw new IllegalAccessException();
}
}
public static ClassLoader verifyHasClassLoader(Class> clazz) {
ClassLoader classLoader = clazz.getClassLoader();
if (classLoader == null) {
throw new IllegalArgumentException("Class has no ClassLoader: " + clazz);
}
return classLoader;
}
public static T verify(T value, Predicate super T> predicate, Supplier message) {
if (!predicate.test(value)) {
throw new IllegalArgumentException(message.get());
}
return value;
}
public static T chainThrowables(@Nullable T chain, T e) {
if (chain == null) {
return Objects.requireNonNull(e);
}
chain.addSuppressed(e);
return chain;
}
public static @Nullable T or(@Nullable T first, @Nullable T alternative) {
return first == null ? alternative : first;
}
public static boolean isEmpty(@Nullable T[] array) {
return array == null || array.length == 0;
}
public static boolean isEmpty(@Nullable Iterable> iterable) {
return iterable == null || !iterable.iterator().hasNext();
}
public static boolean isNotEmpty(@Nullable Iterable> iterable) {
return !isEmpty(iterable);
}
public static > Set immutableEnumSet(Class enumClass) {
return Collections.unmodifiableSet(EnumSet.allOf(enumClass));
}
@SafeVarargs
public static > @Nullable Set immutableEnumSetOrNull(@Nullable E... values) {
if (isEmpty(values)) {
return null;
}
return Collections.unmodifiableSet(EnumSet.copyOf(Arrays.asList(values)));
}
public static ArrayList arrayList(Iterable extends T> iterable) throws NullPointerException {
Objects.requireNonNull(iterable);
if (iterable instanceof Collection) {
Collection extends T> collection = (Collection extends T>) iterable;
ArrayList list = new ArrayList<>(collection.size());
for (T value : collection) {
list.add(Objects.requireNonNull(value));
}
return list;
}
ArrayList list = new ArrayList<>();
for (T value : iterable) {
list.add(Objects.requireNonNull(value));
}
return list;
}
public static List immutableArrayList(Iterable extends T> iterable) throws NullPointerException {
return Collections.unmodifiableList(arrayList(iterable));
}
public static List immutableArrayListNonEmpty(Iterable extends T> iterable) throws NullPointerException {
List list = immutableArrayList(iterable);
if (list.isEmpty()) {
throw new IllegalArgumentException("List must not be empty");
}
return list;
}
public static void initializeClass(Class> clazz) {
ThrowableRunnable.run(() -> initializeClassChecked(clazz));
}
private static void initializeClassChecked(Class> clazz) throws Throwable {
Class.forName(clazz.getName(), true, clazz.getClassLoader());
}
public interface ThrowableRunnable extends Runnable {
static void run(ThrowableRunnable runnable) {
runnable.run();
}
void runChecked() throws Throwable;
@Override
default void run() {
try {
runChecked();
} catch (@SuppressWarnings("removal") RuntimeException | ThreadDeath e) {
throw e;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
public interface ThrowableConsumer extends Consumer {
void acceptChecked(T t) throws Throwable;
@Override
default void accept(T t) {
try {
acceptChecked(t);
} catch (@SuppressWarnings("removal") RuntimeException | ThreadDeath e) {
throw e;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
public interface ThrowableFunction extends Function {
R applyChecked(T t) throws Throwable;
@Override
default R apply(T t) {
try {
return applyChecked(t);
} catch (@SuppressWarnings("removal") RuntimeException | ThreadDeath e) {
throw e;
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
private Utils() {
throw new AssertionError("No instances");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy