use of org.rx.annotation.ErrorCode in project rxlib by RockyLOMO.
the class Reflects method changeType.
@SuppressWarnings(NON_RAW_TYPES)
@ErrorCode("enumError")
@ErrorCode(cause = NoSuchMethodException.class)
@ErrorCode(cause = ReflectiveOperationException.class)
public static <T> T changeType(Object value, @NonNull Class<T> toType) {
if (value == null) {
if (!toType.isPrimitive()) {
if (List.class.equals(toType)) {
return (T) Collections.emptyList();
}
if (Map.class.equals(toType)) {
return (T) Collections.emptyMap();
}
return null;
}
if (boolean.class.equals(toType)) {
return (T) Boolean.FALSE;
} else {
value = 0;
}
}
Class<?> fromType = value.getClass();
Object fValue = value;
if (toType.equals(String.class)) {
value = value.toString();
} else if (toType.equals(UUID.class)) {
value = UUID.fromString(value.toString());
} else if (toType.equals(BigDecimal.class)) {
value = new BigDecimal(value.toString());
} else if (toType.isEnum()) {
boolean failBack = true;
if (NEnum.class.isAssignableFrom(toType)) {
if (value instanceof String) {
try {
value = Integer.valueOf((String) value);
} catch (NumberFormatException e) {
// ignore
}
}
if (value instanceof Number) {
int val = ((Number) value).intValue();
value = NEnum.valueOf((Class) toType, val);
failBack = false;
}
}
if (failBack) {
String val = value.toString();
value = NQuery.of(toType.getEnumConstants()).singleOrDefault(p -> ((Enum) p).name().equals(val));
}
if (value == null) {
throw new ApplicationException("enumError", values(fValue, toType.getSimpleName()));
}
} else if ((!toType.isPrimitive() && TypeUtils.isInstance(value, toType))) {
// isInstance int to long/all to object ok, do nothing
} else {
try {
toType = (Class) primitiveToWrapper(toType);
if (toType.equals(Boolean.class) && isAssignable(fromType, Number.class)) {
int val = ((Number) value).intValue();
if (val == 0) {
value = Boolean.FALSE;
} else if (val == 1) {
value = Boolean.TRUE;
} else {
throw new InvalidException("Value should be 0 or 1");
}
} else {
NQuery<Method> methods = getMethodMap(toType).get(CHANGE_TYPE_METHOD);
if (methods == null || fromType.isEnum()) {
Class<T> fType = toType;
ConvertBean convertBean = NQuery.of(CONVERT_BEANS).firstOrDefault(p -> TypeUtils.isInstance(fValue, p.baseFromType) && p.toType.isAssignableFrom(fType));
if (convertBean != null) {
return (T) convertBean.converter.apply(value, convertBean.toType);
}
throw new NoSuchMethodException(CHANGE_TYPE_METHOD);
}
if (isAssignable(toType, Number.class) && primitiveToWrapper(fromType).equals(Boolean.class)) {
boolean val = (boolean) value;
if (!val) {
value = "0";
} else {
value = "1";
}
}
Method m = null;
for (Method p : methods) {
if (!(p.getParameterCount() == 1 && p.getParameterTypes()[0].equals(String.class))) {
continue;
}
m = p;
break;
}
if (m == null) {
m = toType.getDeclaredMethod(CHANGE_TYPE_METHOD, String.class);
}
value = m.invoke(null, value.toString());
}
} catch (NoSuchMethodException e) {
throw new ApplicationException(values(toType), e);
} catch (ReflectiveOperationException e) {
throw new ApplicationException(values(fromType, toType, value), e);
}
}
return (T) value;
}
use of org.rx.annotation.ErrorCode in project rxlib by RockyLOMO.
the class YamlCodeHandler method handle.
@SneakyThrows
public void handle(ApplicationException e) {
Class<?> codeType = e.getErrorCode().getClass();
if (codeType.isEnum()) {
Map<String, Object> messageSource = getMessageSource().readAs(codeType.getName(), Map.class);
if (messageSource == null) {
return;
}
Enum<?> anEnum = (Enum<?>) e.getErrorCode();
Field field = codeType.getDeclaredField(anEnum.name());
ErrorCode errorCode;
if ((errorCode = findCode(field, null, null)) == null) {
errorCode = new ErrorCode() {
@Override
public Class<? extends Annotation> annotationType() {
return ErrorCode.class;
}
@Override
public String value() {
return null;
}
@Override
public Class<? extends Throwable> cause() {
return Exception.class;
}
@Override
public MessageFormatter messageFormatter() {
return MessageFormatter.MessageFormat;
}
};
}
e.setFriendlyMessage(friendlyMessage(errorCode, messageSource, anEnum.name(), e.getCodeValues()));
return;
}
for (StackTraceElement stack : e.getStacks()) {
Map<String, Object> messageSource = getMessageSource().readAs(stack.getClassName(), Map.class);
if (messageSource == null) {
continue;
}
Tuple<Class<?>, Method[]> caller = as(Cache.getOrSet(stack.getClassName(), p -> {
Class<?> type = Reflects.loadClass(p, false);
return Tuple.of(type, type.getDeclaredMethods());
}, Cache.MEMORY_CACHE), Tuple.class);
if (caller == null) {
continue;
}
Method targetSite = null;
ErrorCode errorCode = null;
for (Method method : caller.right) {
if (!method.getName().equals(stack.getMethodName())) {
continue;
}
if ((errorCode = findCode(method, e.getErrorCode().toString(), e.getCause())) == null) {
continue;
}
log.debug("SystemException: Found @ErrorCode at {}", method);
targetSite = method;
break;
}
if (errorCode == null) {
continue;
}
e.setFriendlyMessage(friendlyMessage(errorCode, messageSource, targetSite.getName(), e.getCodeValues()));
break;
}
if (e.getFriendlyMessage() == null) {
log.debug("SystemException: Not found @ErrorCode");
}
}
use of org.rx.annotation.ErrorCode in project rxlib by RockyLOMO.
the class CoreTester method exceptionHandle.
@ErrorCode
@ErrorCode(cause = IllegalArgumentException.class)
@Test
public void exceptionHandle() {
ExceptionHandler handler = ExceptionHandler.INSTANCE;
handler.log(new InvalidException("test error"));
System.out.println(handler.queryTraces(null, null, null));
String err = "ERR";
ApplicationException ex = new ApplicationException(values(err));
assert eq(ex.getFriendlyMessage(), "Test error code, value=" + err);
ex = new ApplicationException(values(err), new IllegalArgumentException());
assert eq(ex.getFriendlyMessage(), "Test IAException, value=" + err);
$<IllegalArgumentException> out = $();
assert ex.tryGet(out, IllegalArgumentException.class);
String errCode = "ERR_CODE";
ex = new ApplicationException(UserManager.BizCode.USER_NOT_FOUND, values(errCode));
assert eq(ex.getFriendlyMessage(), "User " + errCode + " not found");
ex = new ApplicationException(UserManager.BizCode.COMPUTE_FAIL, values(errCode));
assert eq(ex.getFriendlyMessage(), "Compute user level error " + errCode);
try {
Reflects.changeType("x", Date.class);
} catch (InvalidException e) {
e.printStackTrace();
}
}
use of org.rx.annotation.ErrorCode in project rxlib by RockyLOMO.
the class Reflects method invokeMethod.
@SneakyThrows
@ErrorCode
public static <T, TT> T invokeMethod(Class<? extends TT> type, TT instance, String name, Object... args) {
boolean isStatic = type != null;
Class<?> searchType = isStatic ? type : instance.getClass();
Method method = null;
NQuery<Method> methods = getMethodMap(searchType).get(name);
if (methods != null) {
for (Method p : methods) {
if (p.getParameterCount() != args.length) {
continue;
}
boolean find = true;
Class<?>[] parameterTypes = p.getParameterTypes();
for (int i = 0; i < parameterTypes.length; i++) {
Class<?> parameterType = parameterTypes[i];
Object arg = args[i];
if (arg == null) {
if (parameterType.isPrimitive()) {
find = false;
break;
}
continue;
}
if (!primitiveToWrapper(parameterType).isInstance(arg)) {
find = false;
break;
}
}
if (find) {
method = p;
break;
}
}
}
if (method != null) {
return (T) method.invoke(instance, args);
}
try {
if (isStatic) {
// null 不准
Class<?>[] parameterTypes = toClass(args);
method = MethodUtils.getMatchingMethod(searchType, name, parameterTypes);
return invokeMethod(method, args);
} else {
return (T) MethodUtils.invokeMethod(instance, true, name, args);
}
} catch (Exception e) {
throw new ApplicationException(values(searchType.getName(), name), e);
}
}
use of org.rx.annotation.ErrorCode in project rxlib by RockyLOMO.
the class YamlConfiguration method readAs.
@ErrorCode("keyError")
@ErrorCode("partialKeyError")
public synchronized <T> T readAs(String key, Class<T> type, boolean throwOnEmpty) {
Map<String, Object> tmp = yaml;
if (key == null) {
return convert(tmp, type);
}
Object val;
if ((val = tmp.get(key)) != null) {
return convert(val, type);
}
StringBuilder buf = new StringBuilder();
String[] splits = Strings.split(key, Constants.CONFIG_KEY_SPLITS);
int c = splits.length - 1;
for (int i = 0; i <= c; i++) {
if (buf.length() > 0) {
buf.append(Constants.CONFIG_KEY_SPLITS);
}
String k = buf.append(splits[i]).toString();
if ((val = tmp.get(k)) == null) {
continue;
}
if (i == c) {
return convert(val, type);
}
if ((tmp = as(val, Map.class)) == null) {
throw new ApplicationException("partialKeyError", values(k, type));
}
buf.setLength(0);
}
if (throwOnEmpty) {
throw new ApplicationException("keyError", values(key, type));
}
return null;
}
Aggregations