org.fryske_akademy.Util Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2018 Fryske Akademy.
*
* 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.
*/
package org.fryske_akademy;
/*-
* #%L
* jpaservices
* %%
* Copyright (C) 2018 - 2021 Fryske Akademy
* %%
* 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 jakarta.ejb.EJBException;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.enterprise.inject.spi.CDI;
import jakarta.validation.ConstraintViolationException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author eduard
*/
public class Util {
private static final Logger LOGGER = LoggerFactory.getLogger(Util.class.getName());
/**
* parse a string containing enums the form "enum simple class"."enum name"
* separated by space, look for the right setter in the Object class and
* call the setter. Case is ignored.
*
* @param inputString space separated inputStrng, containing "enum simple
* class"."enum name"
* @param objectWithEnums
* @throws IllegalArgumentException when no setter has been called for an
* enum string
*/
public static T setEnumsFromString(String inputString, T objectWithEnums) {
new Scanner(inputString).forEachRemaining((t) -> {
boolean set = false;
if (inputString.indexOf('.') > 0) {
String enumName = t.substring(0, t.indexOf('.'));
String enumValue = t.substring(t.indexOf('.') + 1);
for (Method m : objectWithEnums.getClass().getMethods()) {
if (m.getName().equalsIgnoreCase("set" + enumName)) {
Class clazz = m.getParameterTypes()[0];
for (Enum e : (Enum[]) clazz.getEnumConstants()) {
if (e.name().equalsIgnoreCase(enumValue)) {
try {
m.invoke(objectWithEnums, e);
set = true;
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw new EJBException(ex);
}
}
}
}
}
}
if (!set) {
throw new IllegalArgumentException(t + " not found in " + objectWithEnums);
}
});
return objectWithEnums;
}
/**
* look for a setter ignoring case for a string in the form "enum simple
* class"."enum name", return true if it is found.
*
* @param t
* @param objectWithEnums
* @return
*/
public static boolean hasSetterForEnumString(String t, Object objectWithEnums) {
if (t.indexOf('.') > 0) {
String enumName = t.substring(0, t.indexOf('.'));
String enumValue = t.substring(t.indexOf('.') + 1);
for (Method m : objectWithEnums.getClass().getMethods()) {
if (m.getName().equalsIgnoreCase("set" + enumName)) {
Class clazz = m.getParameterTypes()[0];
for (Enum e : (Enum[]) clazz.getEnumConstants()) {
if (e.name().equalsIgnoreCase(enumValue)) {
return true;
}
}
}
}
}
return false;
}
/**
* Look for a setter for the enum in the object, call it and return the
* object.
*
* @param
* @param e
* @param objectWithEnums
* @return
* @throws IllegalArgumentException when no setter has been called for the
* enum
*/
public static T setEnum(Enum e, T objectWithEnums) {
for (Method m : objectWithEnums.getClass().getMethods()) {
if (m.getName().equals("set" + e.getClass().getSimpleName())) {
try {
m.invoke(objectWithEnums, e);
return objectWithEnums;
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw new EJBException(ex);
}
}
}
throw new IllegalArgumentException(e + " not found in " + objectWithEnums);
}
/**
* look for a method returning an enum, call it, if the value isn't null
* return it.
*
* @param objectWithEnums
* @return
*/
public static Enum getEnumWithValue(Object objectWithEnums) {
for (Method m : objectWithEnums.getClass().getMethods()) {
if (m.getReturnType().isEnum() && m.getParameterCount() == 0) {
try {
Object o = m.invoke(objectWithEnums);
if (o != null) {
return (Enum) o;
}
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
throw new EJBException(ex);
}
}
}
return null;
}
/**
* look for all methods whose return type is an enum and add all constants
* to the result.
*
* @param clazz
* @return
*/
public static List listEnums(Class clazz) {
return Arrays.stream(clazz.getMethods()).map(Method::getReturnType).filter(Class::isEnum).map(c -> (Enum[]) c.getEnumConstants()).flatMap(Arrays::stream).collect(Collectors.toCollection(() -> new ArrayList<>(100)));
}
/**
* Look for methods with return type enum, whose simple class is the first
* part of the argument string, look for the enum constant whose name is the
* last part of the argument string. Case is ignored.
*
* @param clazz
* @param e string in the form "enum simple class"."enum name"
* @return
*/
public static Enum findInClass(Class clazz, String e) {
return e.indexOf('.') > 0 ?
Arrays.stream(clazz.getMethods()).filter(m -> m.getReturnType().isEnum() && m.getParameterCount() == 0).map(Method::getReturnType).filter(c -> c.getSimpleName().equalsIgnoreCase(e.substring(0, e.indexOf('.')))).flatMap(c -> Arrays.stream((Enum[]) c.getEnumConstants())).filter(en -> en.name().equalsIgnoreCase(e.substring(e.indexOf('.') + 1))).findFirst().orElse(null) : null;
}
/**
* return "enum simple class"."enum name"
*
* @param e
* @return
*/
public static String toString(Enum e) {
return e.getClass().getSimpleName() + '.' + e.name();
}
/**
* return "[" + {@link #toString(java.lang.Enum) } for each enum + "]"
*
* @param l
* @return
*/
public static String toString(List l) {
return "["+l.stream().map(Util::toString).collect(Collectors.joining(", ")) + "]";
}
/**
* Calls {@link #split(java.lang.String, int, boolean) } with false.
*
* @param toSplit
* @param index
* @return
*/
public static String split(String toSplit, int index) {
return split(toSplit, index, false);
}
/**
* Call {@link #split(java.lang.String, java.lang.String, int, boolean) }
* with ": ?" as regex.
*
* @param toSplit
* @param index
* @param ignorePatternAfterIndex
* @return
*/
public static String split(String toSplit, int index, boolean ignorePatternAfterIndex) {
return split(toSplit, ": ?", index, ignorePatternAfterIndex);
}
/**
* split a string on regex and return the requested index, or null. Can be
* used to find an entity using a readable user representation of an entity
* such as "netherlands: franeker", or "netherlands: franeker: center".
*
* @param toSplit
* @param index
* @param ignorePatternAfterIndex when true, occurring patterns after
* index will be ignored, so the return value will be the rest of the input
* string.
* @return
*/
public static String split(String toSplit, String regex, int index, boolean ignorePatternAfterIndex) {
if (toSplit == null) {
return toSplit;
}
String[] split = toSplit.split(regex, ignorePatternAfterIndex ? index + 1 : -1);
return (index < split.length) ? split[index] : null;
}
/**
* you can set log level to fine to see the original stacktrace in the log.
*
* @param t
* @return
*/
public static Throwable deepestCause(Throwable t) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("only retaining deepest cause of stacktrace!", t);
}
if (t.getCause() != null) {
return deepestCause(t.getCause());
}
return t;
}
/**
* Fast method to check if a char is at a certain position in a string.
* @param input
* @param c
* @param pos
* @return
*/
public static boolean isIndex(String input, char c, int pos) {
return !nullOrEmpty(input) && (input.length() > pos && input.charAt(pos) == c);
}
private static Set> checkBeans(Set> beans) {
if (beans.isEmpty()) {
throw new IllegalArgumentException("No beans found");
} else if (beans.size()>1) {
throw new IllegalArgumentException("Multiple beans found");
}
return beans;
}
/**
* find a bean programmatically in CDI provider by name, can be used if you need one in an unmanaged
* situation. Prefer {@link CDI#select(Class, Annotation...)}.
*
* @param
* @param clazz
* @param name the name of the bean to lookup
* @return
*/
public static T getBean(Class clazz, String name) {
BeanManager beanManager = CDI.current().getBeanManager();
Bean contextual = (Bean) checkBeans(beanManager.getBeans(name)).iterator().next();
CreationalContext ctx = beanManager.createCreationalContext(contextual);
T bean = (T) beanManager.getReference(contextual, clazz, ctx);
return bean;
}
public static List formatConstraintException(ConstraintViolationException cve) {
return cve.getConstraintViolations().stream().map((cv) -> cv.getRootBeanClass().getSimpleName() + "." + cv.getPropertyPath() + " " + cv.getMessage()).collect(Collectors.toList());
}
public static boolean nullOrEmpty(String s) {
return s == null || s.isEmpty();
}
public static boolean bothNullOrEmpty(String s, String t) {
return nullOrEmpty(s) && nullOrEmpty(t);
}
}