You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2017/10/27 13:25:27 UTC
[isis] branch dev/2.0.0/ISIS-1762-j8-utils updated: ISIS-1762 added
Reflect and NullSafe, reviewing o.a.i.c.commons
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch dev/2.0.0/ISIS-1762-j8-utils
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/dev/2.0.0/ISIS-1762-j8-utils by this push:
new 07e362e ISIS-1762 added Reflect and NullSafe, reviewing o.a.i.c.commons
07e362e is described below
commit 07e362e2b507d80e0eae9abf303cc7a2bbef18e7
Author: Andi Huber <ah...@apache.org>
AuthorDate: Fri Oct 27 15:25:23 2017 +0200
ISIS-1762 added Reflect and NullSafe, reviewing o.a.i.c.commons
---
.../core/commons/exceptions/ExceptionUtils.java | 14 +-
.../isis/core/commons/lang/ArrayExtensions.java | 11 +-
.../isis/core/commons/lang/ClassPredicates.java | 1 -
.../isis/core/commons/lang/MethodExtensions.java | 2 -
.../apache/isis/core/commons/lang/NullSafe.java | 129 ++++++++++++++++
.../apache/isis/core/commons/lang/Nullable.java | 7 +
.../isis/core/commons/lang/StringPredicates.java | 1 -
.../isis/core/commons/reflection/Reflect.java | 167 +++++++++++++++++++++
8 files changed, 317 insertions(+), 15 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/exceptions/ExceptionUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/exceptions/ExceptionUtils.java
index 376caf5..1b313c6 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/exceptions/ExceptionUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/exceptions/ExceptionUtils.java
@@ -26,6 +26,8 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
+import org.apache.isis.core.commons.reflection.Reflect;
+
/**
* <p>Provides utilities for manipulating and examining
* <code>Throwable</code> objects.</p>
@@ -67,7 +69,7 @@ public class ExceptionUtils {
static {
Method causeMethod;
try {
- causeMethod = Throwable.class.getMethod("getCause", null);
+ causeMethod = Throwable.class.getMethod("getCause", Reflect.emptyClasses);
} catch (Exception e) {
causeMethod = null;
}
@@ -243,10 +245,10 @@ public class ExceptionUtils {
return true;
}
- Class cls = throwable.getClass();
+ Class<?> cls = throwable.getClass();
for (final String causeMethodName : CAUSE_METHOD_NAMES) {
try {
- Method method = cls.getMethod(causeMethodName, null);
+ Method method = cls.getMethod(causeMethodName, Reflect.emptyClasses);
if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
return true;
}
@@ -287,7 +289,7 @@ public class ExceptionUtils {
* @return the array of throwables, never null
*/
public static Throwable[] getThrowables(Throwable throwable) {
- List list = getThrowableList(throwable);
+ List<Throwable> list = getThrowableList(throwable);
return (Throwable[]) list.toArray(new Throwable[list.size()]);
}
@@ -310,8 +312,8 @@ public class ExceptionUtils {
* @return the list of throwables, never null
* @since Commons Lang 2.2
*/
- public static List getThrowableList(Throwable throwable) {
- List list = new ArrayList();
+ public static List<Throwable> getThrowableList(Throwable throwable) {
+ List<Throwable> list = new ArrayList<Throwable>();
while (throwable != null && list.contains(throwable) == false) {
list.add(throwable);
throwable = ExceptionUtils.getCause(throwable);
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
index 26bb45c..4e20585 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ArrayExtensions.java
@@ -22,15 +22,14 @@ package org.apache.isis.core.commons.lang;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import com.google.common.collect.Lists;
-
import org.apache.isis.core.commons.exceptions.IsisException;
+import com.google.common.collect.Lists;
+
public final class ArrayExtensions {
private ArrayExtensions() {
@@ -72,7 +71,8 @@ public final class ArrayExtensions {
return converted;
}
- public static <T> T[] combine(final T[]... arrays) {
+ @SafeVarargs
+ public static <T> T[] combine(final T[]... arrays) {
final List<T> combinedList = Lists.newArrayList();
for (final T[] array : arrays) {
Collections.addAll(combinedList, array);
@@ -93,7 +93,8 @@ public final class ArrayExtensions {
return argList.toArray(new String[] {});
}
- public static <T> T coalesce(final T... objects) {
+ @SafeVarargs
+ public static <T> T coalesce(final T... objects) {
for (final T object : objects) {
if (object != null) {
return object;
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ClassPredicates.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ClassPredicates.java
index 803265b..d2554f2 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ClassPredicates.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/ClassPredicates.java
@@ -18,7 +18,6 @@
*/
package org.apache.isis.core.commons.lang;
-import com.google.common.base.Function;
import com.google.common.base.Predicate;
public final class ClassPredicates {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/MethodExtensions.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/MethodExtensions.java
index 4d4e839..fb95bf9 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/MethodExtensions.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/MethodExtensions.java
@@ -23,8 +23,6 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import com.google.common.primitives.Primitives;
-
import org.apache.isis.core.metamodel.exceptions.MetaModelException;
public class MethodExtensions {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/NullSafe.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/NullSafe.java
new file mode 100644
index 0000000..985b498
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/NullSafe.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.isis.core.commons.lang;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ *
+ * Provides convenient null check / null safe methods primarily
+ * to shortcut null-check idioms.
+ *
+ * @author ahuber@apache.org
+ * @since 2.0.0
+ *
+ */
+public class NullSafe {
+
+ // -- STREAM CREATION
+
+ /**
+ * Shortcut for {@code Optional.ofNullable(array).map(Stream::of)}
+ * @param array
+ * @return a sequential ordered stream whose elements are the elements of
+ * the specified {@code array}, or the empty stream if array is {@code null}.
+ */
+ public static <T> Stream<T> stream(T[] array) {
+ return array!=null ? Stream.empty() : Stream.of(array);
+ }
+
+ /**
+ * Shortcut for {@code Optional.ofNullable(coll).map(Stream::of)}
+ * @param coll
+ * @return a sequential ordered stream whose elements are the elements of
+ * the specified {@code coll}, or the empty stream if coll is {@code null}.
+ */
+ public static <T> Stream<T> stream(Collection<T> coll){
+ return coll!=null ? coll.stream() : Stream.empty();
+ }
+
+ // -- ABSENCE/PRESENCE PREDICATES
+
+ /**
+ * Allows to replace a lambda expression {@code x->x!=null} with {@code NullSafe::isPresent}
+ * @param x
+ * @return whether {@code x} is not null.
+ */
+ public static boolean isPresent(Object x) {
+ return x!=null;
+ }
+
+ /**
+ * Allows to replace a lambda expression {@code x->x==null} with {@code NullSafe::isAbsent}
+ * @param x
+ * @return whether {@code x} is null.
+ */
+ public static boolean isAbsent(Object x) {
+ return x!=null;
+ }
+
+ // -- EQUALS/COMPARE
+
+ /**
+ * equivalent to {@link java.util.Objects#equals(Object, Object)}
+ */
+ public static boolean equals(final Object x, final Object y) {
+ return Objects.equals(x, y);
+ }
+
+ /**
+ * Natural order compare, with nulls ordered first.
+ * @param x
+ * @param y
+ * @return
+ */
+ public static <T extends Comparable<T>> int compareNullsFirst(final T x, final T y) {
+ return Objects.compare(x, y, Comparator.nullsFirst(Comparator.naturalOrder()));
+
+ }
+
+ /**
+ * Natural order compare, with nulls ordered last.
+ * @param x
+ * @param y
+ * @return
+ */
+ public static <T extends Comparable<T>> int compareNullsLast(final T x, final T y) {
+ return Objects.compare(x, y, Comparator.nullsLast(Comparator.naturalOrder()));
+
+ }
+
+
+ // -- EMTPY CHECKS
+
+ public static boolean isEmpty(String x) { return x==null || x.length() == 0; }
+ public static boolean isEmpty(Collection<?> x) { return x==null || x.size() == 0; }
+ public static boolean isEmpty(Map<?,?> x) { return x==null || x.size() == 0; }
+ public static boolean isEmpty(boolean[] array){ return array==null || array.length == 0;}
+ public static boolean isEmpty(byte[] array){ return array==null || array.length == 0;}
+ public static boolean isEmpty(char[] array){ return array==null || array.length == 0;}
+ public static boolean isEmpty(double[] array){ return array==null || array.length == 0;}
+ public static boolean isEmpty(float[] array){ return array==null || array.length == 0;}
+ public static boolean isEmpty(int[] array){ return array==null || array.length == 0;}
+ public static boolean isEmpty(long[] array){ return array==null || array.length == 0;}
+ public static boolean isEmpty(short[] array){ return array==null || array.length == 0;}
+ public static <T> boolean isEmpty(T[] array){ return array==null || array.length == 0;}
+
+
+
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/Nullable.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/Nullable.java
index deac021..f06d014 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/Nullable.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/Nullable.java
@@ -18,6 +18,13 @@
*/
package org.apache.isis.core.commons.lang;
+/**
+ *
+ * @deprecated use {@link java.util.Optional} instead
+ *
+ * @param <T>
+ */
+@Deprecated
public class Nullable<T> {
public static <T> Nullable<T> some(T t) {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/StringPredicates.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/StringPredicates.java
index c8beb4a..349cf22 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/StringPredicates.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/lang/StringPredicates.java
@@ -19,7 +19,6 @@
package org.apache.isis.core.commons.lang;
-import com.google.common.base.Function;
import com.google.common.base.Predicate;
public final class StringPredicates {
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/commons/reflection/Reflect.java b/core/metamodel/src/main/java/org/apache/isis/core/commons/reflection/Reflect.java
new file mode 100644
index 0000000..82cc7e5
--- /dev/null
+++ b/core/metamodel/src/main/java/org/apache/isis/core/commons/reflection/Reflect.java
@@ -0,0 +1,167 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.isis.core.commons.reflection;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+
+/**
+ *
+ * Provides shortcuts for common java.lang.reflect idioms.
+ *
+ * @author ahuber@apache.org
+ * @since 2.0.0
+ *
+ */
+public class Reflect {
+
+ public static Object[] emptyObjects = {};
+ public static Class<?>[] emptyClasses = {};
+
+ // -- CLASS REFLECTION
+
+ /**
+ * Returns declared methods of this class/interface and all super classes/interfaces.
+ * @param type
+ * @return
+ */
+ public static List<Method> getAllDeclaredMethods(Class<?> type) {
+ final List<Method> methods = new ArrayList<>();
+
+ Stream.of(type.getDeclaredMethods()).forEach(methods::add);
+ visitInterfaces(type,c->Stream.of(c.getDeclaredMethods()).forEach(methods::add));
+ visitSuperclassesOf(type,c->Stream.of(c.getDeclaredMethods()).forEach(methods::add));
+ return methods;
+ }
+
+ /**
+ * Returns declared fields of this class/interface and all super classes/interfaces.
+ * @param type
+ * @return
+ */
+ public static List<Field> getAllDeclaredFields(Class<?> type) {
+ final List<Field> fields = new ArrayList<>();
+
+ Stream.of(type.getDeclaredFields()).forEach(fields::add);
+ visitInterfaces(type,c->Stream.of(c.getDeclaredFields()).forEach(fields::add));
+ visitSuperclassesOf(type,c->Stream.of(c.getDeclaredFields()).forEach(fields::add));
+ return fields;
+ }
+
+ public static void visitSuperclassesOf(final Class<?> clazz, final Consumer<Class<?>> visitor){
+ final Class<?> superclass = clazz.getSuperclass();
+ if(superclass!=null){
+ visitor.accept(superclass);
+ visitSuperclassesOf(superclass, visitor);
+ }
+ }
+
+ public static void visitInterfaces(final Class<?> clazz, final Consumer<Class<?>> visitor){
+ if(clazz.isInterface())
+ visitor.accept(clazz);
+
+ for(Class<?> interf : clazz.getInterfaces())
+ visitor.accept(interf);
+ }
+
+ public static Method getGetter(Object bean, String propertyName) throws IntrospectionException {
+ final BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
+ for(PropertyDescriptor pd:beanInfo.getPropertyDescriptors()){
+ if(!pd.getName().equals(propertyName))
+ continue;
+ return pd.getReadMethod();
+ }
+ return null;
+ }
+
+ // -- PRIMITIVE TYPES
+
+ private static final Set<Class<?>> primitives = new HashSet<>(Arrays.asList(
+ boolean.class,
+ byte.class,
+ char.class,
+ double.class,
+ float.class,
+ int.class,
+ long.class,
+ short.class
+ //void.class //separated out into its own predicate: isVoid(...)
+ ));
+
+ private static final Set<Class<?>> primitiveWrappers = new HashSet<>(Arrays.asList(
+ Boolean.class,
+ Byte.class,
+ Character.class,
+ Double.class,
+ Float.class,
+ Integer.class,
+ Long.class,
+ Short.class
+ //Void.class //separated out into its own predicate: isVoid(...)
+ ));
+
+ // -- TYPE PREDICATES
+
+ public static boolean isVoid(Class<?> c) {
+ Objects.requireNonNull(c);
+ return c == void.class || c == Void.class;
+ }
+
+ public static boolean isPrimitive(Class<?> c) {
+ Objects.requireNonNull(c);
+ return primitives.contains(c);
+ }
+
+ public static boolean isPrimitiveWrapper(Class<?> c) {
+ Objects.requireNonNull(c);
+ return primitiveWrappers.contains(c);
+ }
+
+
+ // -- METHOD PREDICATES
+
+ public static boolean isNoArg(Method m) {
+ Objects.requireNonNull(m);
+ return m.getParameterTypes().length==0;
+ }
+
+ public static boolean isPublic(Method m) {
+ Objects.requireNonNull(m);
+ return Modifier.isPublic(m.getModifiers());
+ }
+
+ public static boolean isVoid(Method m) {
+ Objects.requireNonNull(m);
+ return isVoid(m.getReturnType());
+ }
+
+}
--
To stop receiving notification emails like this one, please contact
['"commits@isis.apache.org" <co...@isis.apache.org>'].