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>'].