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 2018/02/28 22:16:19 UTC

[isis] branch master updated: ISIS-1841 reinventing ObjectContracts moving previous version to legacy

This is an automated email from the ASF dual-hosted git repository.

ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git


The following commit(s) were added to refs/heads/master by this push:
     new 6a279e1  ISIS-1841 reinventing ObjectContracts moving previous version to legacy
6a279e1 is described below

commit 6a279e14ac117529e70742791715f20158036384
Author: Andi Huber <ah...@apache.org>
AuthorDate: Wed Feb 28 23:16:15 2018 +0100

    ISIS-1841 reinventing ObjectContracts moving previous version to legacy
---
 .../apache/isis/applib/internal/base/_Strings.java |   4 +-
 .../java/org/apache/isis/applib/util/Equality.java |  57 ++++
 .../java/org/apache/isis/applib/util/Hashing.java  |  48 +++
 .../apache/isis/applib/util/ObjectContracts.java   | 352 +++++----------------
 .../java/org/apache/isis/applib/util/ToString.java |  63 ++++
 5 files changed, 244 insertions(+), 280 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/base/_Strings.java b/core/applib/src/main/java/org/apache/isis/applib/internal/base/_Strings.java
index c7340fb..247e89c 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/base/_Strings.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/base/_Strings.java
@@ -60,7 +60,7 @@ public final class _Strings {
 	 * (a duplicate of in {@link _Constants.emptyStringArray} )
 	 */
 	public final static String[] emptyArray = new String[0];
-
+	
 	// -- BASIC PREDICATES
 
 	/**
@@ -211,7 +211,7 @@ public final class _Strings {
 		}
 		return sb.toString();
 	}
-
+	
 	// -- SPLITTING
 
 	/**
diff --git a/core/applib/src/main/java/org/apache/isis/applib/util/Equality.java b/core/applib/src/main/java/org/apache/isis/applib/util/Equality.java
new file mode 100644
index 0000000..20d1c0c
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/util/Equality.java
@@ -0,0 +1,57 @@
+package org.apache.isis.applib.util;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+
+import org.apache.isis.applib.internal.base._Casts;
+import org.apache.isis.applib.internal.collections._Lists;
+
+/**
+ * Fluent Object Equality Composition.
+ * 
+ * @param <T>
+ * @since 2.0.0
+ */
+public class Equality<T> {
+
+	public static <T> Equality<T> checkEquals(Function<T, ?> getter) {
+		Objects.requireNonNull(getter);
+		return new Equality<>(getter);
+	}
+	
+	private final List<Function<T, ?>> chain = _Lists.newArrayList();
+
+	private Equality(Function<T, ?> getter) {
+		chain.add(getter);
+	}
+	
+	public Equality<T> thenCheckEquals(Function<T, ?> getter){
+		Objects.requireNonNull(getter);
+		chain.add(getter);
+		return this;
+	}
+
+	public boolean equals(T target, Object other){
+		if(target==null && other==null) {
+            return true;
+        }
+        if(target==null || other==null) {
+            return false;
+        }
+        if(target.getClass() != other.getClass()) {
+            return false;
+        }
+		final T o = _Casts.uncheckedCast(other);
+		
+		for(Function<T, ?> getter : chain) {
+			if(!Objects.equals(getter.apply(target), getter.apply(o)))
+				return false;
+		}
+		
+		return true;
+	}
+
+	
+	
+}
diff --git a/core/applib/src/main/java/org/apache/isis/applib/util/Hashing.java b/core/applib/src/main/java/org/apache/isis/applib/util/Hashing.java
new file mode 100644
index 0000000..9f5fdd8
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/util/Hashing.java
@@ -0,0 +1,48 @@
+package org.apache.isis.applib.util;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+
+import org.apache.isis.applib.internal.collections._Lists;
+
+/**
+ * Fluent Object Hash Code Composition.
+ *  
+ * @param <T>
+ * @since 2.0.0
+ *
+ */
+public class Hashing<T> {
+
+	public static <T> Hashing<T> hashing(Function<T, ?> getter){
+		return new Hashing<>(getter);
+	}
+	
+	private final List<Function<T, ?>> getters = _Lists.newArrayList();
+
+	private Hashing(Function<T, ?> getter) {
+		getters.add(getter);
+	}
+	
+	public Hashing<T> thenHashing(Function<T, ?> getter){
+		Objects.requireNonNull(getter);
+		getters.add(getter);
+		return this;
+	}
+
+	public int hashCode(T object){
+		if(object==null) {
+			return 0;
+		}
+		int result = 1;
+		for(Function<T, ?> getter : getters) {
+			final Object element = getter.apply(object); 
+			result = 31 * result + (element == null ? 0 : element.hashCode());
+		}
+		return result;
+	}
+
+
+	
+}
diff --git a/core/applib/src/main/java/org/apache/isis/applib/util/ObjectContracts.java b/core/applib/src/main/java/org/apache/isis/applib/util/ObjectContracts.java
index b7ecb23..2f1bfb2 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/util/ObjectContracts.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/util/ObjectContracts.java
@@ -1,286 +1,82 @@
-/**
- *  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
+/*
+ *  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
+ *        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.
+ *  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.applib.util;
 
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import org.apache.isis.applib.internal.base._Casts;
-import org.apache.isis.applib.internal.base._NullSafe;
-import org.apache.isis.applib.internal.base._Strings;
-import org.apache.isis.applib.internal.collections._Lists;
-
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Objects.ToStringHelper;
-import com.google.common.collect.ComparisonChain;
-import com.google.common.collect.Ordering;
+import java.util.function.Function;
 
+/**
+ * Provides fluent composition for Objects' equals, hashCode and toString.
+ * 
+ * Sample usage by composing getters ...
+ * 
+ *  
+ * <pre>    
+ * private final static Equality<ApplicationFeature> equality = 
+ * 		ObjectContracts.checkEquals(ApplicationFeature::getFeatureId);
+ * 
+ * private final static Hashing<ApplicationFeature> hashing = 
+ * 		ObjectContracts.hashing(ApplicationFeature::getFeatureId);
+ * 
+ * private final static ToString<ApplicationFeature> toString = 
+ * 		ObjectContracts.toString("featureId", ApplicationFeature::getFeatureId);
+ * 
+ * public boolean equals(final Object obj) {
+ * 	return equality.equals(this, obj);
+ * }
+ * 
+ * public int hashCode() {
+ * 	return hashing.hashCode(this);
+ * }
+ * 
+ * public String toString() {
+ * 	return toString.toString(this);
+ * }
+ * </pre>
+ * 
+ * For 'compareTo' use JDK's comparator composition ...
+ * 
+ * <pre>
+ * private final static Comparator<ApplicationFeature> comparator = 
+ * 		Comparator.comparing(ApplicationFeature::getFeatureId);
+ * 		
+ * public int compareTo(final ApplicationFeature other) {
+ * 	return comparator.compare(this, other);
+ * }
+ * </pre>
+ * 
+ * @since 2.0.0 (re-invented)
+ *
+ */
 public class ObjectContracts {
-
-    //region > compare
-
-    /**
-     * Evaluates which of p and q is first.
-     *
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #compare(Object, Object, String...) varargs} overloaded version of this method.
-     */
-    @Deprecated
-    public static <T> int compare(final T p, final T q, final String propertyNames) {
-        final Iterable<String> propertyNamesIter = csvToIterable(propertyNames);
-        return compare(p, q, propertyNamesIter);
-    }
-
-    /**
-     * Evaluates which of p and q is first.
-     *
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     */
-    @Deprecated
-    public static <T> int compare(final T p, final T q, final String... propertyNames) {
-        final Iterable<String> propertyNamesIter = varargsToIterable(propertyNames);
-        return compare(p, q, propertyNamesIter);
-    }
-
-    private static <T> int compare(final T p, final T q, final Iterable<String> propertyNamesIter) {
-        if(p == null) { return -1;}
-        if(q == null) { return +1;}
-        if(p.getClass() != q.getClass()) {
-            // just sort on the class type
-            return Ordering.natural().onResultOf((Function<Object, String>) o -> o.getClass().getSimpleName()).compare(p, q);
-        }
-
-        final Iterable<Clause> clauses = clausesFor(propertyNamesIter);
-        ComparisonChain chain = ComparisonChain.start();
-        for (final Clause clause : clauses) {
-            final Comparable<T> propertyValueOfP = _Casts.uncheckedCast(clause.getValueOf(p));
-            final Comparable<T> propertyValueOfQ = _Casts.uncheckedCast(clause.getValueOf(q));
-            chain = chain.compare(propertyValueOfP, propertyValueOfQ, clause.getDirection().getOrdering());
-        }
-        return chain.result();
-    }
-    //endregion
-
-    //region > compareBy
-    /**
-     * Returns a {@link Comparator} to evaluate objects by their property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #compareBy(String...)} varargs} overloaded version of this method.
-     */
-    @Deprecated
-    public static <T> Comparator<T> compareBy(final String propertyNames){
-        return (p, q) -> compare(p, q, propertyNames);
-    }
-    /**
-     * Returns a {@link Comparator} to evaluate objects by their property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     */
-    @Deprecated
-    public static <T> Comparator<T> compareBy(final String... propertyNames){
-        return (p, q) -> compare(p, q, propertyNames);
-    }
-    //endregion
-
-    //region > toString
-
-    /**
-     * Returns a string representation of the object consisting of the specified property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #toString(Object, String...)} varargs} overloaded version of this method.
-     */
-    @Deprecated
-    public static String toString(Object p, String propertyNames) {
-        return new ObjectContracts().toStringOf(p, propertyNames);
-    }
-    /**
-     * Returns a string representation of the object consisting of the specified property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     */
-    @Deprecated
-    public static String toString(Object p, String... propertyNames) {
-        return new ObjectContracts().toStringOf(p, propertyNames);
-    }
-    //endregion
-
-    //region > hashCode
-    /**
-     * Returns the hashCode for the object using the specified property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #hashCode(Object, String...)} varargs} overloaded version of this method.
-     */
-    @Deprecated
-    public static int hashCode(Object obj, String propertyNames) {
-        final Iterable<String> propertyNamesIter = csvToIterable(propertyNames);
-        return hashCode(obj, propertyNamesIter);
-    }
-
-    /**
-     * Returns the hashCode for the object using the specified property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     */
-    @Deprecated
-    public static int hashCode(Object obj, String... propertyNames) {
-        final Iterable<String> propertyNamesIter = varargsToIterable(propertyNames);
-        return hashCode(obj, propertyNamesIter);
-    }
-
-    private static int hashCode(final Object obj, final Iterable<String> propertyNamesIter) {
-        final List<Object> propertyValues = _Lists.newArrayList();
-        for (final Clause clause : clausesFor(propertyNamesIter)) {
-            final Object propertyValue = clause.getValueOf(obj);
-            if(propertyValue != null) {
-                propertyValues.add(propertyValue);
-            }
-        }
-        return Objects.hashCode(propertyValues.toArray());
-    }
-    //endregion
-
-    //region > equals
-
-    /**
-     * Returns whether two objects are equal, considering just the specified property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #equals(Object, Object, String...)} varargs} overloaded version of this method.
-     */
-    @Deprecated
-    public static boolean equals(Object p, Object q, String propertyNames) {
-        if(p==null && q==null) {
-            return true;
-        }
-        if(p==null || q==null) {
-            return false;
-        }
-        if(p.getClass() != q.getClass()) {
-            return false;
-        }
-        final Iterable<String> propertyNamesIter = csvToIterable(propertyNames);
-        return equals(p, q, propertyNamesIter);
-    }
-
-    /**
-     * Returns whether two objects are equal, considering just the specified property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     */
-    @Deprecated
-    public static boolean equals(Object p, Object q, String... propertyNames) {
-        if(p==null && q==null) {
-            return true;
-        }
-        if(p==null || q==null) {
-            return false;
-        }
-        if(p.getClass() != q.getClass()) {
-            return false;
-        }
-        final Iterable<String> propertyNamesIter = varargsToIterable(propertyNames);
-        return equals(p, q, propertyNamesIter);
-    }
-
-    private static boolean equals(final Object p, final Object q, final Iterable<String> propertyNamesIter) {
-        final Iterable<Clause> clauses = clausesFor(propertyNamesIter);
-        for (final Clause clause : clauses) {
-            final Object pValue = clause.getValueOf(p);
-            final Object qValue = clause.getValueOf(q);
-            if(!Objects.equal(pValue, qValue)) {
-                return false;
-            }
-        }
-        return true;
-    }
-    //endregion
-
-    //region > helpers
-    private static Iterable<Clause> clausesFor(final Iterable<String> iterable) {
-        return _NullSafe.stream(iterable)
-        		.map(Clause::parse)
-        		.collect(Collectors.toList());
-    }
-
-    private static Iterable<String> csvToIterable(final String propertyNames) {
-        return _Strings.splitThenStream(propertyNames, ",")
-        		.collect(Collectors.toList());
-    }
-
-    private static List<String> varargsToIterable(final String[] iterable) {
-        return Arrays.asList(iterable);
-    }
-    //endregion
-
-    //region > toStringOf
-
-    public interface ToStringEvaluator {
-        boolean canEvaluate(Object o);
-        String evaluate(Object o);
-    }
-    
-    private final List<ToStringEvaluator> evaluators = _Lists.newArrayList();
-
-    public ObjectContracts with(ToStringEvaluator evaluator) {
-        evaluators.add(evaluator);
-        return this;
-    }
-
-    /**
-     * Returns a string representation of two objects, considering just the specified property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     * @param propertyNames - the property name or names, CSV format.  If multiple properties, use the {@link #toString(Object, String...)} varargs} overloaded version of this method.
-     */
-    @Deprecated
-    public String toStringOf(Object p, String propertyNames) {
-        final Iterable<String> propertyNamesIter = csvToIterable(propertyNames);
-        return toStringOf(p, propertyNamesIter);
-    }
-
-    /**
-     * Returns a string representation of two objects, considering just the specified property name(s).
-     * @deprecated - please be aware that this utility heavily uses reflection.  We don't actually intend to deprecate this method (it's useful while prototyping), but we wanted to bring this to your attention!
-     */
-    @Deprecated
-    public String toStringOf(Object p, String... propertyNames) {
-        final Iterable<String> propertyNamesIter = varargsToIterable(propertyNames);
-        return toStringOf(p, propertyNamesIter);
-    }
-
-    private String toStringOf(final Object p, final Iterable<String> propertyNamesIter) {
-        final ToStringHelper stringHelper = Objects.toStringHelper(p);
-        for (final Clause clause : clausesFor(propertyNamesIter)) {
-            stringHelper.add(clause.getPropertyName(), asString(clause, p));
-        }
-        return stringHelper.toString();
-    }
-
-    private String asString(final Clause clause, Object p) {
-        final Object value = clause.getValueOf(p);
-        if(value == null) {
-            return null;
-        }
-        for (ToStringEvaluator evaluator : evaluators) {
-            if(evaluator.canEvaluate(value)) {
-                return evaluator.evaluate(value);
-            }
-        }
-        return value.toString();
-    }
-
-    //endregion
-
-
+	
+	public static <T> ToString<T> toString(String name, Function<T, ?> getter) {
+		return ToString.toString(name, getter);
+	}
+	
+	public static <T> Equality<T> checkEquals(Function<T, ?> getter) {
+		return Equality.checkEquals(getter);
+	}
+	
+	public static <T> Hashing<T> hashing(Function<T, ?> getter) {
+		return Hashing.hashing(getter);
+	}
+
+	
+	
 }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/util/ToString.java b/core/applib/src/main/java/org/apache/isis/applib/util/ToString.java
new file mode 100644
index 0000000..3b99fa2
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/util/ToString.java
@@ -0,0 +1,63 @@
+package org.apache.isis.applib.util;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import org.apache.isis.applib.internal.collections._Lists;
+
+/**
+ * Fluent Object to String Composition.
+ *  
+ * @param <T>
+ * @since 2.0.0
+ *
+ */
+public class ToString<T> {
+
+	public static <T> ToString<T> toString(String name, Function<T, ?> getter) {
+		Objects.requireNonNull(name);
+		Objects.requireNonNull(getter);		
+		return new ToString<>(name, getter);
+	}
+	
+	private final List<String> names = _Lists.newArrayList();
+	private final List<Function<T, ?>> getters = _Lists.newArrayList();
+
+	private ToString(String name, Function<T, ?> getter) {
+		names.add(name);
+		getters.add(getter);
+	}
+	
+	public ToString<T> thenToString(String name, Function<T, ?> getter){
+		Objects.requireNonNull(name);
+		Objects.requireNonNull(getter);
+		names.add(name);
+		getters.add(getter);
+		return this;
+	}
+
+	public String toString(T target){
+		if(target==null) {
+			return "null";
+		}
+		
+		final Iterator<String> nameIterator = names.iterator();
+		
+		return String.format("%s{%s}", 
+				
+				target.getClass().getSimpleName(), 
+				
+				getters.stream()
+				.map(getter->getter.apply(target))
+				.map(value->nameIterator.next()+"="+value)
+				.collect(Collectors.joining(", "))	
+				
+				);
+	}
+
+	
+	
+}

-- 
To stop receiving notification emails like this one, please contact
ahuber@apache.org.