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/04/12 11:25:23 UTC

[isis] branch master updated (d066032 -> 6031eba)

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

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


    from d066032  Update _ugvw_menubars-layout_file-based.adoc (#111)
     new 0ecd43c  ISIS-1932 Internal API _Collections: add 'unmodifiable collectors'
     new 770423b  ISIS-1932 Internal API: introduces _Arrays for common Array idioms.
     new 1c957f1  ISIS-1932 consolidate element type inference
     new 6031eba  ISIS-1932 consolidate array & collection idioms

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../isis/applib/internal/base/_NullSafe.java       |  16 ++
 .../internal/collections/_Array_Collector.java     |  99 +++++++
 .../collections/_Array_CollectorUnknownSize.java   |  82 ++++++
 .../isis/applib/internal/collections/_Arrays.java  | 138 ++++++++++
 .../applib/internal/collections/_Collections.java  | 294 +++++++++++++++++++++
 .../collections/_Collections_Collector.java        |  80 ++++++
 .../collections/_Collections_SortedSetOfList.java  | 149 +++++++++++
 .../isis/applib/internal/collections/_Lists.java   |  11 +
 .../isis/applib/internal/collections/_Sets.java    |  39 +++
 .../core/metamodel/facets/CollectionUtils.java     | 168 ++++++------
 .../isis/core/metamodel/facets/FacetedMethod.java  |   9 +-
 ...rCollectionIdentifyingFacetFactoryAbstract.java |  10 +-
 .../facets/actcoll/typeof/TypeOfFacet.java         |  21 +-
 .../action/ActionAnnotationFacetFactory.java       |   8 +-
 .../MethodIncompatibilityWorkaround.java           | 160 +----------
 .../CollectionAnnotationFacetFactory.java          |   4 +-
 .../javautilcollection/CollectionFacetFactory.java |   7 +-
 .../core/metamodel/services/ServicesInjector.java  |  24 +-
 .../core/metamodel/specloader/CollectionUtils.java | 137 +---------
 19 files changed, 1031 insertions(+), 425 deletions(-)
 create mode 100644 core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_Collector.java
 create mode 100644 core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_CollectorUnknownSize.java
 create mode 100644 core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
 create mode 100644 core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
 create mode 100644 core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections_Collector.java
 create mode 100644 core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections_SortedSetOfList.java

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

[isis] 03/04: ISIS-1932 consolidate element type inference

Posted by ah...@apache.org.
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

commit 1c957f1befc5e0ba86cb27993491e9be49715c4e
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Apr 12 10:59:50 2018 +0200

    ISIS-1932 consolidate element type inference
---
 .../isis/applib/internal/collections/_Arrays.java  |  4 +-
 .../applib/internal/collections/_Collections.java  | 48 +++++++++++++++++
 .../facets/actcoll/typeof/TypeOfFacet.java         | 13 ++---
 .../core/metamodel/services/ServicesInjector.java  |  9 ++--
 .../core/metamodel/specloader/CollectionUtils.java | 60 +---------------------
 5 files changed, 60 insertions(+), 74 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
index 8009627..4c59969 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
@@ -55,14 +55,14 @@ public class _Arrays {
         return _Collections.isCollectionType(cls) || _Arrays.isArrayType(cls);
     }
 	
-    // -- ELEMENT TYPE INFERENCE
+    // -- COMPONENT TYPE INFERENCE
     
     /**
      * Returns the inferred element type of the specified array type 
      * @param type of the array for which to infer the element type 
      * @return inferred type or null if inference fails
      */
-    public static @Nullable Class<?> inferElementTypeIfAny(@Nullable final Class<?> arrayType) {
+    public static @Nullable Class<?> inferComponentTypeIfAny(@Nullable final Class<?> arrayType) {
         if(!isArrayType(arrayType)) {
             return null;
         }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
index 80aef7e..9d14b39 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
@@ -19,6 +19,9 @@
 
 package org.apache.isis.applib.internal.collections;
 
+import java.lang.reflect.Field;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -209,6 +212,51 @@ public class _Collections {
 	
 	// -- ELEMENT TYPE INFERENCE
 	
+    /**
+     * If the {@code collectionType} represents a collection then returns returns the inferred element type of the 
+     * specified {@code genericType}     
+     * @param collectionType
+     * @param genericType as associated with {@code collectionType} (as available for fields or method parameters)
+     * @return inferred type or null if inference fails
+     */
+    public static @Nullable Class<?> inferElementTypeIfAny(
+    		@Nullable final Class<?> collectionType, 
+    		@Nullable final Type genericType) {
+    	
+    	if(collectionType == null || genericType==null) {
+    		return null;
+    	}
+    	
+    	if(!isCollectionType(collectionType)) {
+    		return null;
+    	}
+
+        if(genericType instanceof ParameterizedType) {
+            final ParameterizedType parameterizedType = (ParameterizedType) genericType;
+            final Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
+            if(actualTypeArguments.length == 1) {
+                final Type actualTypeArgument = actualTypeArguments[0];
+                if(actualTypeArgument instanceof Class) {
+                    final Class<?> actualType = (Class<?>) actualTypeArgument;
+                    return actualType;
+                }
+            }
+        }
+        
+        return null;
+    }
+	
+    /**
+     * If the {@code field} represents a collection then returns the inferred element type for this collection (if any).
+     *   
+     * @param field
+     * @return inferred type or null if inference fails
+     */
+    public static @Nullable Class<?> inferElementTypeIfAny(@Nullable final Field field) {
+    	        
+        return inferElementTypeIfAny(field.getType(), field.getGenericType());
+    }
+    
 	// --
 	
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
index bf18c01..9614100 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
@@ -30,7 +30,6 @@ import org.apache.isis.applib.internal.collections._Arrays;
 import org.apache.isis.applib.internal.collections._Collections;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.SingleClassValueFacet;
-import org.apache.isis.core.metamodel.specloader.CollectionUtils;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 
 /**
@@ -108,7 +107,7 @@ public interface TypeOfFacet extends SingleClassValueFacet {
                 final FacetHolder holder,
                 final Class<?> type,
                 final SpecificationLoader specificationLoader) {
-            final Class<?> elementType = _Arrays.inferElementTypeIfAny(type);
+            final Class<?> elementType = _Arrays.inferComponentTypeIfAny(type);
             return elementType != null
                     ? new TypeOfFacetInferredFromArray(elementType, holder, specificationLoader)
                     : null;
@@ -121,13 +120,9 @@ public interface TypeOfFacet extends SingleClassValueFacet {
                 final Type genericParameterType,
                 final SpecificationLoader specificationLoader) {
         	
-        	if(!_Collections.isCollectionType(parameterType)) {
-                return null;
-            }
-        	
-            final Class<?> actualType = CollectionUtils.inferElementTypeFromGenericType(genericParameterType);
-            return actualType != null
-                    ? new TypeOfFacetInferredFromGenerics(actualType, holder, specificationLoader)
+            final Class<?> elementType = _Collections.inferElementTypeIfAny(parameterType, genericParameterType);
+            return elementType != null
+                    ? new TypeOfFacetInferredFromGenerics(elementType, holder, specificationLoader)
                     : null;
         }
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
index 3f52cb4..fb372e0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
@@ -44,7 +44,6 @@ import org.apache.isis.core.metamodel.exceptions.MetaModelException;
 import org.apache.isis.core.metamodel.services.configinternal.ConfigurationServiceInternal;
 import org.apache.isis.core.metamodel.services.persistsession.PersistenceSessionServiceInternal;
 import org.apache.isis.core.metamodel.spec.InjectorMethodEvaluator;
-import org.apache.isis.core.metamodel.specloader.CollectionUtils;
 import org.apache.isis.core.metamodel.specloader.InjectorMethodEvaluatorDefault;
 import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
 import org.apache.isis.core.runtime.authentication.AuthenticationManager;
@@ -285,9 +284,9 @@ public class ServicesInjector implements ApplicationScopedComponent {
         }
 
         // inject matching services into a field of type Collection<T> if a generic type T is present
-        CollectionUtils.ifIsCollectionWithGenericTypeThen(field, (elementType)->{
-        	
-        	@SuppressWarnings("unchecked")
+        final Class<?> elementType = _Collections.inferElementTypeIfAny(field);
+		if(elementType!=null) {
+			@SuppressWarnings("unchecked")
 			final Class<? extends Collection<Object>> collectionTypeToBeInjected =
         			(Class<? extends Collection<Object>>) typeToBeInjected;
         	
@@ -297,7 +296,7 @@ public class ServicesInjector implements ApplicationScopedComponent {
                       .collect(_Collections.toUnmodifiableOfType(collectionTypeToBeInjected));
              
              invokeInjectorField(field, object, collectionOfServices);
-        });
+		}
         
         for (final Object service : services) {
             final Class<?> serviceClass = service.getClass();
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java
index b0ea59f..ce23a27 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java
@@ -19,10 +19,7 @@
 
 package org.apache.isis.core.metamodel.specloader;
 
-import java.lang.reflect.Field;
-import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
-import java.util.function.Consumer;
 
 import javax.annotation.Nullable;
 
@@ -51,67 +48,14 @@ public final class CollectionUtils {
     public static boolean isParamCollection(
     		@Nullable final Class<?> parameterType,
     		@Nullable final Type genericParameterType) {
-    	if(_Arrays.inferElementTypeIfAny(parameterType) != null) {
+    	if(_Arrays.inferComponentTypeIfAny(parameterType) != null) {
     		return true;
     	}
-    	if(_Collections.isCollectionType(parameterType) && inferElementTypeFromGenericType(genericParameterType)!=null) {
+    	if(_Collections.inferElementTypeIfAny(parameterType, genericParameterType)!=null) {
     		return true;
     	}
     	return false;
     }
 
 
-
-    // -- ELEMENT TYPE INFERENCE (FROM GENERIC TYPE)
-    
-    /**
-     * Returns the inferred element type of the specified array type
-     * @param collectionType
-     * @param genericParameterType
-     * @return inferred type or null if inference fails
-     */
-    public static @Nullable Class<?> inferElementTypeFromGenericType(@Nullable final Type genericType) {
-
-    	if(genericType==null) {
-    		return null;
-    	}
-
-        if(genericType instanceof ParameterizedType) {
-            final ParameterizedType parameterizedType = (ParameterizedType) genericType;
-            final Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
-            if(actualTypeArguments.length == 1) {
-                final Type actualTypeArgument = actualTypeArguments[0];
-                if(actualTypeArgument instanceof Class) {
-                    final Class<?> actualType = (Class<?>) actualTypeArgument;
-                    return actualType;
-                }
-            }
-        }
-        
-        return null;
-    }
-
-    // -- ELEMENT TYPE INFERENCE (FROM FIELD)
-    
-    /**
-	 * If field is of type (or a sub-type of) Collection&lt;T&gt; with generic type T present, 
-	 * then call action with the element type.
-	 * @param field
-	 * @param action
-	 */
-    public static void ifIsCollectionWithGenericTypeThen(Field field, Consumer<Class<?>> action) {
-		
-		final Class<?> fieldType = field.getType();
-		
-		if(_Collections.isCollectionType(fieldType)) {
-			
-			final Class<?> elementType = inferElementTypeFromGenericType(field.getGenericType());
-			
-			if(elementType!=null) {
-				action.accept(elementType);
-			}
-        }
-		
-	}
-
 }

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

[isis] 04/04: ISIS-1932 consolidate array & collection idioms

Posted by ah...@apache.org.
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

commit 6031ebae610fe45ac6d331e2b420dc11186f9897
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Apr 12 13:24:46 2018 +0200

    ISIS-1932 consolidate array & collection idioms
---
 .../isis/applib/internal/base/_NullSafe.java       |  16 ++
 .../internal/collections/_Array_Collector.java     |  99 ++++++++++++
 .../collections/_Array_CollectorUnknownSize.java   |  82 ++++++++++
 .../isis/applib/internal/collections/_Arrays.java  |  68 ++++++++-
 .../applib/internal/collections/_Collections.java  |  34 ++++-
 .../isis/applib/internal/collections/_Lists.java   |  11 ++
 .../isis/applib/internal/collections/_Sets.java    |  39 +++++
 .../core/metamodel/facets/CollectionUtils.java     | 168 ++++++++++-----------
 8 files changed, 424 insertions(+), 93 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/base/_NullSafe.java b/core/applib/src/main/java/org/apache/isis/applib/internal/base/_NullSafe.java
index 08cfef1..c6b4b99 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/base/_NullSafe.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/base/_NullSafe.java
@@ -23,6 +23,7 @@ import java.util.Comparator;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Objects;
+import java.util.function.Consumer;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
 
@@ -115,6 +116,21 @@ public final class _NullSafe {
 		return x==null;
 	}
 	
+	// -- PEEK OPERATOR
+	
+	/**
+	 * Unary identity operator that passes {@code obj} to {@code ifPresent} if {@code obj} is present.   
+	 * @param obj
+	 * @param ifPresent
+	 * @return {@code obj}
+	 */
+	public final static <T> T peek(T obj, Consumer<T> ifPresent) {
+		if(obj!=null) {
+			ifPresent.accept(obj);
+		}
+		return obj;
+	}
+	
 	// -- EQUALS/COMPARE
 	
 	/**
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_Collector.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_Collector.java
new file mode 100644
index 0000000..d0a7948
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_Collector.java
@@ -0,0 +1,99 @@
+/*
+ *  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.applib.internal.collections;
+
+import java.lang.reflect.Array;
+import java.util.Collections;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+import org.apache.isis.applib.internal.base._Casts;
+
+/**
+ * 
+ * package private mixin for utility class {@link _Arrays}
+ * 
+ * Collector for Arrays.
+ *
+ */
+class _Array_Collector<T> implements Collector<T, _Array_Collector.FastList<T>, T[]> {
+	
+	private final Class<T> componentType;
+	private final int size;
+	
+	_Array_Collector(Class<T> componentType, int size) {
+		this.componentType = componentType;
+		this.size = size;
+	}
+
+	@Override
+	public Supplier<FastList<T>> supplier() {
+		return ()->new FastList<>(componentType, size);
+	}
+
+	@Override
+	public BiConsumer<FastList<T>, T> accumulator() {
+		return FastList::add;
+	}
+
+	@Override
+	public BinaryOperator<FastList<T>> combiner() {
+		return (a,b)->a.addAll(b);
+	}
+
+	@Override
+	public Function<FastList<T>, T[]> finisher() {
+		return list->list.buffer;
+	}
+
+	@Override
+	public Set<Characteristics> characteristics() {
+		return Collections.emptySet();
+	}
+
+	// -- HELPER
+	
+	static final class FastList<T> {
+		private final T[] buffer;
+		private int offset=0;
+		
+		public FastList(Class<T> componentType, int size) {
+			this.buffer = _Casts.uncheckedCast(Array.newInstance(componentType, size));
+		}
+		public void add(T x){
+			buffer[offset++]=x;
+		}
+		public FastList<T> addAll(FastList<T> x){
+			System.arraycopy(x.buffer, 0, buffer, offset, x.offset);
+			return this;
+		}
+	}
+	
+	
+}
+
+
+	
+	
+
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_CollectorUnknownSize.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_CollectorUnknownSize.java
new file mode 100644
index 0000000..c318f20
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Array_CollectorUnknownSize.java
@@ -0,0 +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
+ *
+ *        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.applib.internal.collections;
+
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+import org.apache.isis.applib.internal.base._Casts;
+
+/**
+ * 
+ * package private mixin for utility class {@link _Arrays}
+ * 
+ * Collector for Arrays.
+ *
+ */
+class _Array_CollectorUnknownSize<T> implements Collector<T, List<T>, T[]> {
+	
+	private final Class<T> componentType;
+	
+	_Array_CollectorUnknownSize(Class<T> componentType) {
+		this.componentType = componentType;
+	}
+
+	@Override
+	public Supplier<List<T>> supplier() {
+		return ArrayList::new;
+	}
+
+	@Override
+	public BiConsumer<List<T>, T> accumulator() {
+		return List::add;
+	}
+
+	@Override
+	public BinaryOperator<List<T>> combiner() {
+		return (left, right) -> { left.addAll(right); return left; };
+	}
+
+	@Override
+	public Function<List<T>, T[]> finisher() {
+		final T[] arg = _Casts.uncheckedCast(Array.newInstance(componentType, 0));
+		return list->list.toArray(arg);
+	}
+
+	@Override
+	public Set<Characteristics> characteristics() {
+		return Collections.emptySet();
+	}
+	
+	
+}
+
+
+	
+	
+
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
index 4c59969..816aa06 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
@@ -19,8 +19,14 @@
 
 package org.apache.isis.applib.internal.collections;
 
+import java.util.Collection;
+import java.util.Objects;
+import java.util.stream.Collector;
+
 import javax.annotation.Nullable;
 
+import org.apache.isis.applib.internal.base._NullSafe;
+
 /**
  * <h1>- internal use only -</h1>
  * <p>
@@ -33,7 +39,9 @@ import javax.annotation.Nullable;
  * 
  * @since 2.0.0
  */
-public class _Arrays {
+public final class _Arrays {
+	
+	private _Arrays(){}
 	
     // -- PREDICATES
 
@@ -54,7 +62,63 @@ public class _Arrays {
     public static boolean isCollectionOrArrayType(final Class<?> cls) {
         return _Collections.isCollectionType(cls) || _Arrays.isArrayType(cls);
     }
-	
+    
+    // -- TO-ARRAY COLLECTORS
+    
+    /**
+     * Known-size Collector.
+     * @param componentType
+     * @param length
+     * @return
+     */
+    public static <T> Collector<T,?,T[]> toArray(final Class<T> componentType, final int length){
+    	Objects.requireNonNull(componentType);
+		return new _Array_Collector<T>(componentType, length);
+	}
+    
+    /**
+     * Unknown-size Collector.
+     * @param componentType
+     * @return
+     */
+    public static <T> Collector<T,?,T[]> toArray(final Class<T> componentType){
+    	Objects.requireNonNull(componentType);
+		return new _Array_CollectorUnknownSize<T>(componentType);
+	}
+
+    // -- CONSTRUCTION
+    
+    /**
+     * Copies a collection's elements into an array.
+     *
+     * @param iterable the iterable to copy
+     * @param type the type of the elements
+     * @return a newly-allocated array into which all the elements of the iterable
+     *     have been copied (non-null)
+     */
+	public static <T> T[] toArray(@Nullable final Collection<? extends T> collection, final Class<T> componentType) {
+		Objects.requireNonNull(componentType);
+		return _NullSafe.stream(collection)
+				.collect(toArray(componentType, collection!=null ? collection.size() : 0));
+	}
+    
+    /**
+     * Copies an iterable's elements into an array.
+     *
+     * @param iterable the iterable to copy
+     * @param type the type of the elements
+     * @return a newly-allocated array into which all the elements of the iterable
+     *     have been copied (non-null)
+     */
+	public static <T> T[] toArray(@Nullable final Iterable<? extends T> iterable, final Class<T> componentType) {
+		Objects.requireNonNull(componentType);
+		if(iterable!=null && (iterable instanceof Collection)) {
+			return toArray((Collection<? extends T>) iterable, componentType);
+		}
+		return _NullSafe.stream(iterable)
+				.collect(toArray(componentType));
+	}
+    
     // -- COMPONENT TYPE INFERENCE
     
     /**
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
index 9d14b39..dd117f0 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
@@ -33,11 +33,15 @@ import java.util.Objects;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
+import java.util.function.Function;
+import java.util.function.Supplier;
 import java.util.stream.Collector;
 import java.util.stream.Collectors;
 
 import javax.annotation.Nullable;
 
+import org.apache.isis.applib.internal.base._NullSafe;
+
 /**
  * <h1>- internal use only -</h1>
  * <p>
@@ -50,7 +54,9 @@ import javax.annotation.Nullable;
  * 
  * @since 2.0.0
  */
-public class _Collections {
+public final class _Collections {
+	
+	private _Collections(){}
 	
     // -- PREDICATES
 
@@ -210,6 +216,32 @@ public class _Collections {
 						typeOfCollection.getClass().getName()));
 	}
 	
+	// -- COLLECT FROM ITERABLE
+	
+	/*
+	 * package private utility for a slightly heap pollution reduced collection, 
+	 * if the iterable is a collection and we know the size of the result in advance
+	 * 
+	 * @param iterable
+	 * @param factory
+	 * @param elementCollector
+	 * @return
+	 */
+	static <T, R> R collectFromIterable(
+			@Nullable Iterable<T> iterable, 
+			Function<Collection<T>, R> factory, 
+			Supplier<Collector<T, ?, R>> elementCollector) {
+		
+		if(iterable==null) {
+			return factory.apply(null);
+		}
+		if(iterable instanceof Collection) {
+			return factory.apply((Collection<T>) iterable);
+		}
+		return _NullSafe.stream(iterable)
+				.collect(elementCollector.get());
+	}
+	
 	// -- ELEMENT TYPE INFERENCE
 	
     /**
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Lists.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Lists.java
index 6bf8059..e0e95cb 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Lists.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Lists.java
@@ -101,6 +101,11 @@ public final class _Lists {
 		return new ArrayList<T>(collection);
 	}
 	
+	public static <T> ArrayList<T> newArrayList(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Lists::newArrayList, 
+				()->Collectors.<T, ArrayList<T>>toCollection(ArrayList::new) );
+	}
+	
 	// -- LINKED LIST
 	
 	public static <T> LinkedList<T> newLinkedList() {
@@ -114,6 +119,11 @@ public final class _Lists {
 		return new LinkedList<T>(collection);
 	}
 	
+	public static <T> LinkedList<T> newLinkedList(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Lists::newLinkedList, 
+				()->Collectors.<T, LinkedList<T>>toCollection(LinkedList::new) );
+	}
+	
 	// -- TRANSFORMATION
 	
 	public static <T, R> List<R> transform(@Nullable List<T> input, Function<T, R> mapper) {
@@ -126,4 +136,5 @@ public final class _Lists {
 				.collect(Collectors.toList());
 	}
 	
+	
 }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java
index 9abbc1e..6556fb9 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Sets.java
@@ -21,10 +21,12 @@ package org.apache.isis.applib.internal.collections;
 
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.Objects;
 import java.util.Set;
+import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentHashMap.KeySetView;
 import java.util.stream.Collectors;
@@ -76,6 +78,27 @@ public final class _Sets {
 				.collect(Collectors.toSet()));
 	}
 	
+	// -- TREE SET
+	
+	public static <T> TreeSet<T> newTreeSet() {
+		return new TreeSet<T>();
+	}
+	
+	public static <T> TreeSet<T> newTreeSet(@Nullable Comparator<T> comparator) {
+		return comparator!=null ? new TreeSet<T>(comparator) : new TreeSet<T>();
+	}
+	
+	public static <T> TreeSet<T> newTreeSet(@Nullable Iterable<T> iterable) {
+		return _NullSafe.stream(iterable)
+				.collect(Collectors.<T, TreeSet<T>>toCollection(TreeSet::new));
+	}
+	
+	public static <T> TreeSet<T> newTreeSet(@Nullable Iterable<T> iterable, @Nullable Comparator<T> comparator) {
+		return _NullSafe.stream(iterable)
+				.collect(Collectors.<T, TreeSet<T>>toCollection(()->new TreeSet<T>(comparator)));
+	}
+	
+	
 	// -- HASH SET
 	
 	public static <T> HashSet<T> newHashSet() {
@@ -89,6 +112,11 @@ public final class _Sets {
 		return new HashSet<T>(collection);
 	}
 	
+	public static <T> HashSet<T> newHashSet(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Sets::newHashSet, 
+				()->Collectors.<T, HashSet<T>>toCollection(HashSet::new) );
+	}
+	
 	// -- LINKED HASH SET
 	
 	public static <T> LinkedHashSet<T> newLinkedHashSet() {
@@ -102,6 +130,11 @@ public final class _Sets {
 		return new LinkedHashSet<T>(collection);
 	}
 	
+	public static <T> LinkedHashSet<T> newLinkedHashSet(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Sets::newLinkedHashSet, 
+				()->Collectors.<T, LinkedHashSet<T>>toCollection(LinkedHashSet::new) );
+	}
+	
 	// -- CONCURRENT HASH SET
 	
 	public static <T> KeySetView<T, Boolean> newConcurrentHashSet() {
@@ -116,6 +149,12 @@ public final class _Sets {
 		return keySetView;
 	}
 	
+	public static <T> KeySetView<T, Boolean> newConcurrentHashSet(@Nullable Iterable<T> iterable) {
+		return _Collections.collectFromIterable(iterable, _Sets::newConcurrentHashSet, 
+				()->Collectors.<T, KeySetView<T, Boolean>>toCollection(ConcurrentHashMap::newKeySet) );
+	}
+	
+	
 	// -- SET OPERATIONS
 
 	/**
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java
index 033d4b3..8c188da 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/CollectionUtils.java
@@ -23,110 +23,98 @@ import java.util.AbstractList;
 import java.util.AbstractSet;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.SortedSet;
 import java.util.TreeSet;
 import java.util.concurrent.CopyOnWriteArrayList;
 import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.function.Function;
 
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-
+import org.apache.isis.applib.internal.base._Casts;
+import org.apache.isis.applib.internal.base._NullSafe;
+import org.apache.isis.applib.internal.collections._Arrays;
+import org.apache.isis.applib.internal.collections._Lists;
+import org.apache.isis.applib.internal.collections._Sets;
 import org.apache.isis.core.metamodel.adapter.ObjectAdapter;
 import org.apache.isis.core.metamodel.adapter.mgr.AdapterManager;
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
 
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
 public final class CollectionUtils {
-    private CollectionUtils() {
-    }
-
-    public static Object[] getCollectionAsObjectArray(final Object option, final ObjectSpecification spec, final AdapterManager adapterMap) {
-        final ObjectAdapter collection = adapterMap.adapterFor(option);
-        final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(collection);
-        final Object[] optionArray = new Object[facet.size(collection)];
-        int j = 0;
-        for (final ObjectAdapter nextElement : facet.iterable(collection)) {
-            optionArray[j++] = nextElement != null? nextElement.getObject(): null;
-        }
-        return optionArray;
-    }
-
-    /**
-     * Copies the iterable into the specified type.
-     */
-    public static Object copyOf(final Iterable<Object> iterable, final Class<?> requiredType) {
-
-        if(iterable == null) {
-            throw new IllegalArgumentException("Iterable must be provided");
-        }
-        if(requiredType == null) {
-            throw new IllegalArgumentException("RequiredType must be provided");
-        }
-
-        // specific list implementations
-        if (CopyOnWriteArrayList.class == requiredType) {
-            return Lists.newCopyOnWriteArrayList(iterable);
-        }
-        if (LinkedList.class == requiredType) {
-            return Lists.newLinkedList(iterable);
-        }
-        if (ArrayList.class == requiredType) {
-            return Lists.newArrayList(iterable);
-        }
-
-        if (AbstractList.class == requiredType) {
-            return Lists.newArrayList(iterable);
-        }
-
-        // specific set implementations
-        if (CopyOnWriteArraySet.class == requiredType) {
-            return Sets.newCopyOnWriteArraySet(iterable);
-        }
-        if (LinkedHashSet.class == requiredType) {
-            return Sets.newLinkedHashSet(iterable);
-        }
-        if (HashSet.class == requiredType) {
-            return Sets.newHashSet(iterable);
-        }
-        if (TreeSet.class == requiredType) {
-            Iterable rawIterable = iterable;
-            return Sets.newTreeSet(rawIterable);
-        }
-
-        if (AbstractSet.class == requiredType) {
-            return Sets.newLinkedHashSet(iterable);
-        }
-
-
-        // interfaces
-        if (List.class == requiredType) {
-            return Lists.newArrayList(iterable);
-        }
-        if (SortedSet.class == requiredType) {
-            Iterable rawIterable = iterable;
-            return Sets.newTreeSet(rawIterable);
-        }
-        if (Set.class == requiredType) {
-            return Sets.newLinkedHashSet(iterable);
-        }
-        if (Collection.class == requiredType) {
-            return Lists.newArrayList(iterable);
-        }
-
-        // array
-        if (requiredType.isArray()) {
-            Class<?> componentType = requiredType.getComponentType();
-            Iterable rawIterable = iterable;
-            return Iterables.toArray(rawIterable, componentType);
-        }
-
-        // not recognized
-        return null;
-    }
+
+	private CollectionUtils() {
+	}
+
+	public static Object[] getCollectionAsObjectArray(final Object option, final ObjectSpecification spec, final AdapterManager adapterMap) {
+		final ObjectAdapter collection = adapterMap.adapterFor(option);
+		final CollectionFacet facet = CollectionFacet.Utils.getCollectionFacetFromSpec(collection);
+		final Object[] optionArray = new Object[facet.size(collection)];
+		int j = 0;
+		for (final ObjectAdapter nextElement : facet.iterable(collection)) {
+			optionArray[j++] = nextElement != null? nextElement.getObject(): null;
+		}
+		return optionArray;
+	}
+
+	private final static Map<Class<?>, Function<Iterable<Object>, Object>> factoriesByType = _NullSafe.peek(
+			new HashMap<>(), map-> {
+				// specific list implementations
+				map.put(CopyOnWriteArrayList.class, Lists::newCopyOnWriteArrayList);
+				map.put(LinkedList.class, _Lists::newLinkedList);
+				map.put(ArrayList.class, _Lists::newArrayList);
+				map.put(AbstractList.class, _Lists::newArrayList);
+
+				// specific set implementations
+				map.put(CopyOnWriteArraySet.class, Sets::newCopyOnWriteArraySet);
+				map.put(LinkedHashSet.class, _Sets::newLinkedHashSet);
+				map.put(HashSet.class, _Sets::newHashSet);
+				map.put(TreeSet.class, _Sets::newTreeSet);
+				map.put(AbstractSet.class, _Sets::newLinkedHashSet);
+
+				// interfaces
+				map.put(List.class, _Lists::newArrayList);
+				map.put(SortedSet.class, _Sets::newTreeSet);
+				map.put(Set.class, _Sets::newLinkedHashSet);
+				map.put(Collection.class, _Lists::newArrayList);
+			});
+
+	/**
+	 * Copies the iterable into the specified type.
+	 */
+	public static Object copyOf(final Iterable<Object> iterable, final Class<?> requiredType) {
+
+		if(iterable == null) {
+			throw new IllegalArgumentException("Iterable must be provided");
+		}
+		if(requiredType == null) {
+			throw new IllegalArgumentException("RequiredType must be provided");
+		}
+
+		final Function<Iterable<Object>, Object> factory = factoriesByType.get(requiredType);
+		if(factory!=null) {
+			return factory.apply(iterable);
+		}
+
+		// array
+		if (requiredType.isArray()) {
+			Class<?> componentType = requiredType.getComponentType();
+			
+			@SuppressWarnings("rawtypes") Iterable rawIterable = iterable;
+			return _Arrays.toArray(_Casts.uncheckedCast(rawIterable), componentType);
+		}
+
+		// not recognized
+		return null;
+
+	}
+
 }

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

[isis] 02/04: ISIS-1932 Internal API: introduces _Arrays for common Array idioms.

Posted by ah...@apache.org.
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

commit 770423b358e7c81d803ca784adbd7460f00e8d4c
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Apr 12 10:09:02 2018 +0200

    ISIS-1932 Internal API: introduces _Arrays for common Array idioms.
---
 .../isis/applib/internal/collections/_Arrays.java  | 74 ++++++++++++++++++++++
 .../applib/internal/collections/_Collections.java  | 22 +++++++
 .../isis/core/metamodel/facets/FacetedMethod.java  |  9 +--
 ...rCollectionIdentifyingFacetFactoryAbstract.java | 10 +--
 .../facets/actcoll/typeof/TypeOfFacet.java         | 12 ++--
 .../action/ActionAnnotationFacetFactory.java       |  8 +--
 .../CollectionAnnotationFacetFactory.java          |  4 +-
 .../javautilcollection/CollectionFacetFactory.java |  7 +-
 .../core/metamodel/specloader/CollectionUtils.java | 33 ++--------
 9 files changed, 127 insertions(+), 52 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
new file mode 100644
index 0000000..8009627
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Arrays.java
@@ -0,0 +1,74 @@
+/*
+ *  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.applib.internal.collections;
+
+import javax.annotation.Nullable;
+
+/**
+ * <h1>- internal use only -</h1>
+ * <p>
+ * Common Array idioms.
+ * </p>
+ * <p>
+ * <b>WARNING</b>: Do <b>NOT</b> use any of the classes provided by this package! <br/> 
+ * These may be changed or removed without notice!
+ * </p>
+ * 
+ * @since 2.0.0
+ */
+public class _Arrays {
+	
+    // -- PREDICATES
+
+	/**
+	 * @param cls
+	 * @return whether {@code cls} represents an array
+	 */
+    public static boolean isArrayType(@Nullable final Class<?> cls) {
+        return cls!=null ? cls.isArray() : false;
+    }
+    
+    /**
+     * For convenience also provided in {@link _Collections}.
+     * @param cls
+     * @return whether {@code cls} implements the java.util.Collection interface 
+     * or represents an array
+     */
+    public static boolean isCollectionOrArrayType(final Class<?> cls) {
+        return _Collections.isCollectionType(cls) || _Arrays.isArrayType(cls);
+    }
+	
+    // -- ELEMENT TYPE INFERENCE
+    
+    /**
+     * Returns the inferred element type of the specified array type 
+     * @param type of the array for which to infer the element type 
+     * @return inferred type or null if inference fails
+     */
+    public static @Nullable Class<?> inferElementTypeIfAny(@Nullable final Class<?> arrayType) {
+        if(!isArrayType(arrayType)) {
+            return null;
+        }
+        return arrayType.getComponentType();
+    }
+    
+	// --
+	
+}
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
index 96c59e6..80aef7e 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
@@ -48,6 +48,26 @@ import javax.annotation.Nullable;
  * @since 2.0.0
  */
 public class _Collections {
+	
+    // -- PREDICATES
+
+	/**
+	 * @param cls
+	 * @return whether {@code cls} implements the java.util.Collection interface
+	 */
+    public static boolean isCollectionType(@Nullable final Class<?> cls) {
+        return cls!=null ? java.util.Collection.class.isAssignableFrom(cls) : false;
+    }
+    
+    /**
+     * For convenience also provided in {@link _Arrays}.
+     * @param cls
+     * @return whether {@code cls} implements the java.util.Collection interface 
+     * or represents an array
+     */
+    public static boolean isCollectionOrArrayType(final Class<?> cls) {
+        return _Collections.isCollectionType(cls) || _Arrays.isArrayType(cls);
+    }
 
 	// -- COLLECTION UNMODIFIABLE ADAPTERS (FOR LIST)
 
@@ -187,6 +207,8 @@ public class _Collections {
 						typeOfCollection.getClass().getName()));
 	}
 	
+	// -- ELEMENT TYPE INFERENCE
+	
 	// --
 	
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
index 7c4b64e..bb8fefe 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/FacetedMethod.java
@@ -24,9 +24,8 @@ import java.lang.reflect.Type;
 import java.util.Collections;
 import java.util.List;
 
-import com.google.common.collect.Lists;
-
 import org.apache.isis.applib.Identifier;
+import org.apache.isis.applib.internal.collections._Arrays;
 import org.apache.isis.core.commons.lang.StringExtensions;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
@@ -34,7 +33,9 @@ import org.apache.isis.core.metamodel.facetapi.IdentifiedHolder;
 import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacet;
 import org.apache.isis.core.metamodel.facets.collparam.semantics.CollectionSemanticsFacet;
 import org.apache.isis.core.metamodel.facets.collparam.semantics.CollectionSemanticsFacetDefault;
-import org.apache.isis.core.metamodel.specloader.*;
+import org.apache.isis.core.metamodel.specloader.SpecificationLoader;
+
+import com.google.common.collect.Lists;
 
 /**
  * non-final only so it can be mocked if need be.
@@ -137,7 +138,7 @@ public class FacetedMethod extends TypedHolderDefault implements IdentifiedHolde
                         specificationLoader);
 
                 if(typeOfFacet == null ) {
-                    if (org.apache.isis.core.metamodel.specloader.CollectionUtils.isArrayType(parameterType)) {
+                    if (_Arrays.isArrayType(parameterType)) {
                         typeOfFacet = TypeOfFacet.Util.inferFromArrayType(fmp, parameterType, specificationLoader);
                     }
                 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PropertyOrCollectionIdentifyingFacetFactoryAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PropertyOrCollectionIdentifyingFacetFactoryAbstract.java
index 6719694..197e407 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PropertyOrCollectionIdentifyingFacetFactoryAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/PropertyOrCollectionIdentifyingFacetFactoryAbstract.java
@@ -21,8 +21,8 @@ package org.apache.isis.core.metamodel.facets;
 
 import java.util.List;
 
+import org.apache.isis.applib.internal.collections._Collections;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
-import org.apache.isis.core.metamodel.specloader.CollectionUtils;
 
 public abstract class PropertyOrCollectionIdentifyingFacetFactoryAbstract
         extends MethodPrefixBasedFacetFactoryAbstract
@@ -33,14 +33,8 @@ public abstract class PropertyOrCollectionIdentifyingFacetFactoryAbstract
         super(featureTypes, OrphanValidation.DONT_VALIDATE, prefixes);
     }
 
-
-    // //////////////////////////////////////
-
     protected boolean isCollectionOrArray(final Class<?> cls) {
-        return CollectionUtils.isCollectionType(cls) || CollectionUtils.isArrayType(cls);
+        return _Collections.isCollectionOrArrayType(cls);
     }
 
-
-
-
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
index 8e79f74..bf18c01 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actcoll/typeof/TypeOfFacet.java
@@ -26,6 +26,8 @@ import java.lang.reflect.Type;
 import java.lang.reflect.TypeVariable;
 
 import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.internal.collections._Arrays;
+import org.apache.isis.applib.internal.collections._Collections;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facets.SingleClassValueFacet;
 import org.apache.isis.core.metamodel.specloader.CollectionUtils;
@@ -52,7 +54,7 @@ public interface TypeOfFacet extends SingleClassValueFacet {
                 final SpecificationLoader specificationLoader) {
 
             final Class<?> methodReturnType = method.getReturnType();
-            if (!CollectionUtils.isCollectionType(methodReturnType)) {
+            if (!_Collections.isCollectionType(methodReturnType)) {
                 return null;
             }
 
@@ -106,9 +108,9 @@ public interface TypeOfFacet extends SingleClassValueFacet {
                 final FacetHolder holder,
                 final Class<?> type,
                 final SpecificationLoader specificationLoader) {
-            final Class<?> componentType = CollectionUtils.inferElementTypeFromArrayType(type);
-            return componentType != null
-                    ? new TypeOfFacetInferredFromArray(componentType, holder, specificationLoader)
+            final Class<?> elementType = _Arrays.inferElementTypeIfAny(type);
+            return elementType != null
+                    ? new TypeOfFacetInferredFromArray(elementType, holder, specificationLoader)
                     : null;
         }
 
@@ -119,7 +121,7 @@ public interface TypeOfFacet extends SingleClassValueFacet {
                 final Type genericParameterType,
                 final SpecificationLoader specificationLoader) {
         	
-        	if(!CollectionUtils.isCollectionType(parameterType)) {
+        	if(!_Collections.isCollectionType(parameterType)) {
                 return null;
             }
         	
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
index 053eaf8..16c317c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/ActionAnnotationFacetFactory.java
@@ -22,9 +22,8 @@ package org.apache.isis.core.metamodel.facets.actions.action;
 import java.lang.reflect.Method;
 import java.util.List;
 
-import com.google.common.base.Strings;
-
 import org.apache.isis.applib.annotation.Action;
+import org.apache.isis.applib.internal.collections._Collections;
 import org.apache.isis.applib.services.HasTransactionId;
 import org.apache.isis.applib.services.eventbus.ActionDomainEvent;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
@@ -57,9 +56,10 @@ import org.apache.isis.core.metamodel.facets.actions.semantics.ActionSemanticsFa
 import org.apache.isis.core.metamodel.facets.all.hide.HiddenFacet;
 import org.apache.isis.core.metamodel.facets.members.order.annotprop.MemberOrderFacetForActionAnnotation;
 import org.apache.isis.core.metamodel.spec.ObjectSpecification;
-import org.apache.isis.core.metamodel.specloader.CollectionUtils;
 import org.apache.isis.core.metamodel.util.EventUtil;
 
+import com.google.common.base.Strings;
+
 public class ActionAnnotationFacetFactory extends FacetFactoryAbstract {
 
 
@@ -255,7 +255,7 @@ public class ActionAnnotationFacetFactory extends FacetFactoryAbstract {
         final FacetedMethod holder = processMethodContext.getFacetHolder();
 
         final Class<?> methodReturnType = method.getReturnType();
-        if (!CollectionUtils.isCollectionType(methodReturnType) && !CollectionUtils.isArrayType(methodReturnType)) {
+        if (!_Collections.isCollectionOrArrayType(methodReturnType)) {
             return;
         }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/collection/CollectionAnnotationFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/collection/CollectionAnnotationFacetFactory.java
index a182b77..4e94b4b 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/collection/CollectionAnnotationFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/collection/CollectionAnnotationFacetFactory.java
@@ -26,6 +26,7 @@ import java.lang.reflect.TypeVariable;
 import java.util.List;
 
 import org.apache.isis.applib.annotation.Collection;
+import org.apache.isis.applib.internal.collections._Collections;
 import org.apache.isis.applib.services.eventbus.CollectionDomainEvent;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FacetUtil;
@@ -55,7 +56,6 @@ import org.apache.isis.core.metamodel.facets.collections.modify.CollectionRemove
 import org.apache.isis.core.metamodel.facets.members.disabled.DisabledFacet;
 import org.apache.isis.core.metamodel.facets.propcoll.accessor.PropertyOrCollectionAccessorFacet;
 import org.apache.isis.core.metamodel.facets.propcoll.notpersisted.NotPersistedFacet;
-import org.apache.isis.core.metamodel.specloader.CollectionUtils;
 import org.apache.isis.core.metamodel.util.EventUtil;
 
 public class CollectionAnnotationFacetFactory extends FacetFactoryAbstract {
@@ -196,7 +196,7 @@ public class CollectionAnnotationFacetFactory extends FacetFactoryAbstract {
         final Method method = processMethodContext.getMethod();
 
         final Class<?> methodReturnType = method.getReturnType();
-        if (!CollectionUtils.isCollectionType(methodReturnType) && !CollectionUtils.isArrayType(methodReturnType)) {
+        if (!_Collections.isCollectionOrArrayType(methodReturnType)) {
             return;
         }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/CollectionFacetFactory.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/CollectionFacetFactory.java
index 39e7619..132c6ae 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/CollectionFacetFactory.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/collections/javautilcollection/CollectionFacetFactory.java
@@ -19,6 +19,8 @@
 
 package org.apache.isis.core.metamodel.facets.collections.javautilcollection;
 
+import org.apache.isis.applib.internal.collections._Arrays;
+import org.apache.isis.applib.internal.collections._Collections;
 import org.apache.isis.core.metamodel.facetapi.FacetHolder;
 import org.apache.isis.core.metamodel.facetapi.FeatureType;
 import org.apache.isis.core.metamodel.facets.FacetFactoryAbstract;
@@ -29,7 +31,6 @@ import org.apache.isis.core.metamodel.facets.actcoll.typeof.TypeOfFacetInferredF
 import org.apache.isis.core.metamodel.facets.collections.modify.CollectionFacet;
 import org.apache.isis.core.metamodel.services.ServicesInjector;
 import org.apache.isis.core.metamodel.services.persistsession.PersistenceSessionServiceInternal;
-import org.apache.isis.core.metamodel.specloader.CollectionUtils;
 
 public class CollectionFacetFactory extends FacetFactoryAbstract {
 
@@ -40,9 +41,9 @@ public class CollectionFacetFactory extends FacetFactoryAbstract {
     @Override
     public void process(final ProcessClassContext processClassContaxt) {
 
-        if (CollectionUtils.isCollectionType(processClassContaxt.getCls())) {
+        if (_Collections.isCollectionType(processClassContaxt.getCls())) {
             processCollectionType(processClassContaxt);
-        } else if (CollectionUtils.isArrayType(processClassContaxt.getCls())) {
+        } else if (_Arrays.isArrayType(processClassContaxt.getCls())) {
             processAsArrayType(processClassContaxt);
         }
 
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java
index 80a35a0..b0ea59f 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java
@@ -26,6 +26,9 @@ import java.util.function.Consumer;
 
 import javax.annotation.Nullable;
 
+import org.apache.isis.applib.internal.collections._Arrays;
+import org.apache.isis.applib.internal.collections._Collections;
+
 /**
  * Defines the types which are considered to be collections.
  * 
@@ -38,16 +41,6 @@ import javax.annotation.Nullable;
 public final class CollectionUtils {
 
     private CollectionUtils() {}
-
-    // -- PREDICATES
-    
-    public static boolean isCollectionType(@Nullable final Class<?> cls) {
-        return cls!=null ? java.util.Collection.class.isAssignableFrom(cls) : false;
-    }
-
-    public static boolean isArrayType(@Nullable final Class<?> cls) {
-        return cls!=null ? cls.isArray() : false;
-    }
     
     /**
      * 
@@ -58,28 +51,16 @@ public final class CollectionUtils {
     public static boolean isParamCollection(
     		@Nullable final Class<?> parameterType,
     		@Nullable final Type genericParameterType) {
-    	if(inferElementTypeFromArrayType(parameterType) != null) {
+    	if(_Arrays.inferElementTypeIfAny(parameterType) != null) {
     		return true;
     	}
-    	if(isCollectionType(parameterType) && inferElementTypeFromGenericType(genericParameterType)!=null) {
+    	if(_Collections.isCollectionType(parameterType) && inferElementTypeFromGenericType(genericParameterType)!=null) {
     		return true;
     	}
     	return false;
     }
 
-    // -- ELEMENT TYPE INFERENCE (ARRAY)
-    
-    /**
-     * Returns the inferred element type of the specified array type 
-     * @param type of the array for which to infer the element type 
-     * @return inferred type or null if inference fails
-     */
-    public static @Nullable Class<?> inferElementTypeFromArrayType(@Nullable final Class<?> type) {
-        if(!isArrayType(type)) {
-            return null;
-        }
-        return type.getComponentType();
-    }
+
 
     // -- ELEMENT TYPE INFERENCE (FROM GENERIC TYPE)
     
@@ -122,7 +103,7 @@ public final class CollectionUtils {
 		
 		final Class<?> fieldType = field.getType();
 		
-		if(isCollectionType(fieldType)) {
+		if(_Collections.isCollectionType(fieldType)) {
 			
 			final Class<?> elementType = inferElementTypeFromGenericType(field.getGenericType());
 			

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

[isis] 01/04: ISIS-1932 Internal API _Collections: add 'unmodifiable collectors'

Posted by ah...@apache.org.
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

commit 0ecd43cf7400520fddfeba61ae8249608a0b07dd
Author: Andi Huber <ah...@apache.org>
AuthorDate: Thu Apr 12 08:29:19 2018 +0200

    ISIS-1932 Internal API _Collections: add 'unmodifiable collectors'
---
 .../applib/internal/collections/_Collections.java  | 192 +++++++++++++++++++++
 .../collections/_Collections_Collector.java        |  80 +++++++++
 .../collections/_Collections_SortedSetOfList.java  | 149 ++++++++++++++++
 .../MethodIncompatibilityWorkaround.java           | 160 +----------------
 .../core/metamodel/services/ServicesInjector.java  |  15 +-
 .../core/metamodel/specloader/CollectionUtils.java |  52 ------
 6 files changed, 431 insertions(+), 217 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
new file mode 100644
index 0000000..96c59e6
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections.java
@@ -0,0 +1,192 @@
+/*
+ *  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.applib.internal.collections;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nullable;
+
+/**
+ * <h1>- internal use only -</h1>
+ * <p>
+ * Common Collection creation and adapting idioms.
+ * </p>
+ * <p>
+ * <b>WARNING</b>: Do <b>NOT</b> use any of the classes provided by this package! <br/> 
+ * These may be changed or removed without notice!
+ * </p>
+ * 
+ * @since 2.0.0
+ */
+public class _Collections {
+
+	// -- COLLECTION UNMODIFIABLE ADAPTERS (FOR LIST)
+
+	/**
+	 * Adapts the {@code list} as unmodifiable collection. 
+	 * Same as {@link Collections#unmodifiableCollection(List)}.
+	 * 
+	 * @param list
+	 * @return null if {@code list} is null
+	 */
+	public static <T> Collection<T> asUnmodifiableCollection(@Nullable final List<T> list) {
+		if(list==null) {
+			return null;
+		}
+		return Collections.unmodifiableCollection(list);
+	}
+	
+	/**
+	 * Adapts the {@code list} as unmodifiable list. 
+	 * Same as {@link Collections#unmodifiableList(List)}.
+	 * 
+	 * @param list
+	 * @return
+	 */
+	public static <T> List<T> asUnmodifiableList(@Nullable final List<T> list) {
+		if(list==null) {
+			return null;
+		}
+		return Collections.unmodifiableList(list);
+	}
+
+	/**
+	 * Preserves order, adapts the {@code list} as Set.<br/><br/> 
+	 * 
+	 * Any duplicate elements of the list will not be added to the set.
+	 * An element e1 is a duplicate of e2 if {@code e1.equals(e2) == true}.
+	 * 
+	 * @param list
+	 * @return null if {@code list} is null
+	 */
+	public static <T> Set<T> asUnmodifiableSet(@Nullable final List<T> list) {
+		if(list==null) {
+			return null;
+		}
+		return Collections.unmodifiableSet(
+				(Set<T>)
+				list.stream()
+				.collect(Collectors.toCollection(LinkedHashSet::new)));
+	}
+	
+	/**
+	 * Preserves order, adapts the {@code list} as SortedSet.<br/><br/>
+	 * 
+	 * Any duplicate elements of the list will not be added to the set.
+	 * An element e1 is a duplicate of e2 if {@code e1.equals(e2) == true}.
+	 * 
+	 * @param list
+	 * @return null if {@code list} is null
+	 */
+	public static <T> SortedSet<T> asUnmodifiableSortedSet(@Nullable final List<T> list) {
+		if(list==null) {
+			return null;
+		}
+		return _Collections_SortedSetOfList.of(list);
+	}
+
+	// -- STREAM TO UMODIFIABLE COLLECTION COLLECTORS
+	
+	/**
+	 * @return a collector that collects elements of a stream into an unmodifiable List 
+	 */
+	public static <T> Collector<T, List<T>, List<T>> toUnmodifiableList() {
+		return new _Collections_Collector<>(ArrayList::new, Collections::unmodifiableList);
+	}
+	
+	/**
+	 * @return a collector that collects elements of a stream into an unmodifiable Set 
+	 */
+	public static <T> Collector<T, Set<T>, Set<T>> toUnmodifiableSet() {
+		return new _Collections_Collector<>(HashSet::new, Collections::unmodifiableSet);
+	}
+	
+	/**
+	 * @return a collector that collects elements of a stream into an unmodifiable SortedSet 
+	 */
+	public static <T> Collector<T, SortedSet<T>, SortedSet<T>> toUnmodifiableSortedSet() {
+		return new _Collections_Collector<>(TreeSet::new, Collections::unmodifiableSortedSet);
+	}
+	
+	/**
+	 * @return a collector that collects elements of a stream into an unmodifiable Collection 
+	 */
+	public static <T> Collector<T, Collection<T>, Collection<T>> toUnmodifiableCollection() {
+		return new _Collections_Collector<>(ArrayList::new, Collections::unmodifiableCollection);
+	}
+	
+	/**
+	 * @return a collector that collects elements of a stream into an unmodifiable SortedSet 
+	 */
+	public static <T> Collector<T, SortedSet<T>, SortedSet<T>> toUnmodifiableSortedSet(
+			@Nullable Comparator<T> comparator) {
+		
+		if(comparator==null) {
+			return toUnmodifiableSortedSet();
+		}
+		return new _Collections_Collector<>(()->new TreeSet<>(comparator), Collections::unmodifiableSortedSet);
+	}
+	
+	/**
+	 * @return a collector that collects elements of a stream into an unmodifiable 
+	 * List, Set, SortedSet or Collection. 
+	 * @throws IllegalArgumentException if the {@link typeOfCollection} is not one of 
+	 * List, Set, SortedSet or Collection.
+	 */
+	public static <T> Collector<T, ?, ? extends Collection<T>> toUnmodifiableOfType(Class<?> typeOfCollection) {
+		
+		Objects.requireNonNull(typeOfCollection);
+		
+		if(SortedSet.class.equals(typeOfCollection)) {
+			return toUnmodifiableSortedSet();
+		}
+		
+		if(Set.class.equals(typeOfCollection)) {
+			return toUnmodifiableSet();
+		}
+		
+		if(List.class.equals(typeOfCollection)) {
+			return toUnmodifiableList();
+		}
+		
+		if(Collection.class.equals(typeOfCollection)) {
+			return toUnmodifiableCollection();
+		}
+		
+		throw new IllegalArgumentException(
+				String.format("Can not collect into %s. Only List, Set, SortedSet and Collection are supported.",
+						typeOfCollection.getClass().getName()));
+	}
+	
+	// --
+	
+}
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections_Collector.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections_Collector.java
new file mode 100644
index 0000000..10a8b7a
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections_Collector.java
@@ -0,0 +1,80 @@
+/*
+ *  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.applib.internal.collections;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+
+/**
+ * 
+ * package private mixin for utility class {@link _Collections}
+ * 
+ * Collector for Collections.
+ *
+ */
+class _Collections_Collector<T, C extends Collection<T>> implements Collector<T, C, C> {
+
+	private final Supplier<C> supplier;
+	private final Function<C, C> finisher;
+	
+	_Collections_Collector(Supplier<C> supplier, Function<C, C> finisher) {
+		this.supplier = Objects.requireNonNull(supplier);
+		this.finisher = Objects.requireNonNull(finisher);
+	}
+
+	@Override
+	public Supplier<C> supplier() {
+		return supplier;
+	}
+
+	@Override
+	public BiConsumer<C, T> accumulator() {
+		return Collection::add;
+	}
+
+	@Override
+	public BinaryOperator<C> combiner() {
+		return (left, right) -> { left.addAll(right); return left; };
+	}
+
+	@Override
+	public Function<C, C> finisher() {
+		return finisher;
+	}
+
+	@Override
+	public Set<Characteristics> characteristics() {
+		return Collections.emptySet();
+	}
+
+	
+}
+
+
+	
+	
+
diff --git a/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections_SortedSetOfList.java b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections_SortedSetOfList.java
new file mode 100644
index 0000000..add7d8a
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/internal/collections/_Collections_SortedSetOfList.java
@@ -0,0 +1,149 @@
+/*
+ *  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.applib.internal.collections;
+
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.SortedSet;
+
+/**
+ * 
+ * package private mixin for utility class {@link _Collections}
+ *
+ */
+class _Collections_SortedSetOfList<T> implements SortedSet<T> {
+	
+	private final static String JUST_AN_ADAPTER = 
+			"this set is just an adapter, it has no information about the intended comparator";
+	
+	static <T> _Collections_SortedSetOfList<T> of(List<T> list){
+		return new _Collections_SortedSetOfList<>(list);
+	}
+	
+	private final List<T> list;
+	
+	private _Collections_SortedSetOfList(List<T> list) {
+		this.list = list;
+	}
+
+	@Override
+	public int size() {
+		return list.size();
+	}
+
+	@Override
+	public boolean isEmpty() {
+		return list.isEmpty();
+	}
+
+	@Override
+	public boolean contains(Object o) {
+		throw new UnsupportedOperationException(JUST_AN_ADAPTER);
+	}
+
+	@Override
+	public Iterator<T> iterator() {
+		return list.iterator();
+	}
+
+	@Override
+	public Object[] toArray() {
+		return list.toArray();
+	}
+
+	@Override
+	public <X> X[] toArray(X[] a) {
+		return list.toArray(a);
+	}
+
+	@Override
+	public boolean add(T e) {
+		throw new UnsupportedOperationException("unmodifiable");
+	}
+
+	@Override
+	public boolean remove(Object o) {
+		throw new UnsupportedOperationException("unmodifiable");
+	}
+
+	@Override
+	public boolean containsAll(Collection<?> c) {
+		throw new UnsupportedOperationException(JUST_AN_ADAPTER);
+	}
+
+	@Override
+	public boolean addAll(Collection<? extends T> c) {
+		throw new UnsupportedOperationException("unmodifiable");
+	}
+
+	@Override
+	public boolean retainAll(Collection<?> c) {
+		throw new UnsupportedOperationException("unmodifiable");
+	}
+
+	@Override
+	public boolean removeAll(Collection<?> c) {
+		throw new UnsupportedOperationException("unmodifiable");
+	}
+
+	@Override
+	public void clear() {
+		throw new UnsupportedOperationException("unmodifiable");
+	}
+
+	@Override
+	public Comparator<? super T> comparator() {
+		throw new UnsupportedOperationException(JUST_AN_ADAPTER);
+	}
+
+	@Override
+	public SortedSet<T> subSet(T fromElement, T toElement) {
+		throw new UnsupportedOperationException(JUST_AN_ADAPTER);
+	}
+
+	@Override
+	public SortedSet<T> headSet(T toElement) {
+		throw new UnsupportedOperationException(JUST_AN_ADAPTER);
+	}
+
+	@Override
+	public SortedSet<T> tailSet(T fromElement) {
+		throw new UnsupportedOperationException(JUST_AN_ADAPTER);
+	}
+
+	@Override
+	public T first() {
+		if(size()==0) {
+			throw new NoSuchElementException("set is empty");
+		}
+		return list.get(0);
+	}
+
+	@Override
+	public T last() {
+		if(size()==0) {
+			throw new NoSuchElementException("set is empty");
+		}
+		return list.get(size()-1);
+	}
+}
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/MethodIncompatibilityWorkaround.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/MethodIncompatibilityWorkaround.java
index e8a2920..46000b4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/MethodIncompatibilityWorkaround.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/facets/actions/action/invocation/MethodIncompatibilityWorkaround.java
@@ -22,17 +22,12 @@ package org.apache.isis.core.metamodel.facets.actions.action.invocation;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
 import java.util.List;
-import java.util.NoSuchElementException;
 import java.util.Set;
 import java.util.SortedSet;
-import java.util.stream.Collectors;
 
 import org.apache.isis.applib.internal.base._NullSafe;
+import org.apache.isis.applib.internal.collections._Collections;
 
 /**
  * Package private utility for method invocation pre-processing. 
@@ -75,171 +70,26 @@ class MethodIncompatibilityWorkaround {
 		
 		// allow no side effects on Collection arguments
 		if(Collection.class.equals(parameterType)) {
-			return adaptAsCollection((List<?>)obj);
+			return _Collections.asUnmodifiableCollection((List<?>)obj);
 		}
 		
 		// allow no side effects on List arguments
 		if(List.class.equals(parameterType)) {
-			return adaptAsList((List<?>)obj);
+			return _Collections.asUnmodifiableList((List<?>)obj);
 		}
 
 		// adapt as Set (unmodifiable)
 		if(Set.class.equals(parameterType)) {
-			return adaptAsSet((List<?>)obj);
+			return _Collections.asUnmodifiableSet((List<?>)obj);
 		}
 		
 		// adapt as SortedSet (unmodifiable)
 		if(SortedSet.class.equals(parameterType)) {
-			return adaptAsSortedSet((List<?>)obj);
+			return _Collections.asUnmodifiableSortedSet((List<?>)obj);
 		}
 		
 		return obj;
 	}
 	
-	// -- COLLECTION ADAPTERS
-
-	/**
-	 * Adapts the list as unmodifiable collection.
-	 * @param list
-	 * @return
-	 */
-	private static <T> Collection<T> adaptAsCollection(final List<T> list) {
-		return Collections.unmodifiableCollection(list);
-	}
-	
-	/**
-	 * Adapts the list as unmodifiable list.
-	 * @param list
-	 * @return
-	 */
-	private static <T> List<T> adaptAsList(final List<T> list) {
-		return Collections.unmodifiableList(list);
-	}
-
-	/**
-	 * Preserves order, adapts the Set interface.
-	 * @param list
-	 * @return
-	 */
-	private static <T> Set<T> adaptAsSet(final List<T> list) {
-		return Collections.unmodifiableSet(
-				(Set<T>)
-				list.stream()
-				.collect(Collectors.toCollection(LinkedHashSet::new)));
-	}
-
-	private final static String JUST_AN_ADAPTER = 
-			"this set is just an adapter, it has no information about the intended comparator";
-	
-	/**
-	 * Preserves order, adapts the SortedSet interface.
-	 * @param list
-	 * @return
-	 */
-	private static <T> SortedSet<T> adaptAsSortedSet(final List<T> list) {
-		return new SortedSet<T>() {
-			
-			@Override
-			public int size() {
-				return list.size();
-			}
-
-			@Override
-			public boolean isEmpty() {
-				return list.isEmpty();
-			}
-
-			@Override
-			public boolean contains(Object o) {
-				throw new UnsupportedOperationException(JUST_AN_ADAPTER);
-			}
-
-			@Override
-			public Iterator<T> iterator() {
-				return list.iterator();
-			}
-
-			@Override
-			public Object[] toArray() {
-				return list.toArray();
-			}
-
-			@Override
-			public <X> X[] toArray(X[] a) {
-				return list.toArray(a);
-			}
-
-			@Override
-			public boolean add(T e) {
-				throw new UnsupportedOperationException("unmodifiable");
-			}
-
-			@Override
-			public boolean remove(Object o) {
-				throw new UnsupportedOperationException("unmodifiable");
-			}
-
-			@Override
-			public boolean containsAll(Collection<?> c) {
-				throw new UnsupportedOperationException(JUST_AN_ADAPTER);
-			}
-
-			@Override
-			public boolean addAll(Collection<? extends T> c) {
-				throw new UnsupportedOperationException("unmodifiable");
-			}
-
-			@Override
-			public boolean retainAll(Collection<?> c) {
-				throw new UnsupportedOperationException("unmodifiable");
-			}
-
-			@Override
-			public boolean removeAll(Collection<?> c) {
-				throw new UnsupportedOperationException("unmodifiable");
-			}
-
-			@Override
-			public void clear() {
-				throw new UnsupportedOperationException("unmodifiable");
-			}
-
-			@Override
-			public Comparator<? super T> comparator() {
-				throw new UnsupportedOperationException(JUST_AN_ADAPTER);
-			}
-
-			@Override
-			public SortedSet<T> subSet(T fromElement, T toElement) {
-				throw new UnsupportedOperationException(JUST_AN_ADAPTER);
-			}
-
-			@Override
-			public SortedSet<T> headSet(T toElement) {
-				throw new UnsupportedOperationException(JUST_AN_ADAPTER);
-			}
-
-			@Override
-			public SortedSet<T> tailSet(T fromElement) {
-				throw new UnsupportedOperationException(JUST_AN_ADAPTER);
-			}
-
-			@Override
-			public T first() {
-				if(size()==0) {
-					throw new NoSuchElementException("set is empty");
-				}
-				return list.get(0);
-			}
-
-			@Override
-			public T last() {
-				if(size()==0) {
-					throw new NoSuchElementException("set is empty");
-				}
-				return list.get(size()-1);
-			}
-		};
-	}
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
index b9d9773..3f52cb4 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/services/ServicesInjector.java
@@ -28,6 +28,7 @@ import java.util.stream.Collectors;
 
 import org.apache.isis.applib.annotation.Programmatic;
 import org.apache.isis.applib.internal.base._NullSafe;
+import org.apache.isis.applib.internal.collections._Collections;
 import org.apache.isis.applib.internal.collections._Lists;
 import org.apache.isis.applib.internal.collections._Maps;
 import org.apache.isis.applib.internal.collections._Multimaps;
@@ -290,16 +291,10 @@ public class ServicesInjector implements ApplicationScopedComponent {
 			final Class<? extends Collection<Object>> collectionTypeToBeInjected =
         			(Class<? extends Collection<Object>>) typeToBeInjected;
         	
-        	 final Collection<Object> collectionOfServices =
-        			 CollectionUtils.collectIntoUnmodifiableCompatibleWithCollectionType(
-        					 
-        					 collectionTypeToBeInjected,
-        					 
-                     		 _NullSafe.stream(services)
-                              .filter(_NullSafe::isPresent)
-                              .filter(isOfType(elementType))
-                              
-                     		);
+        	 final Collection<Object> collectionOfServices = _NullSafe.stream(services)
+                      .filter(_NullSafe::isPresent)
+                      .filter(isOfType(elementType))
+                      .collect(_Collections.toUnmodifiableOfType(collectionTypeToBeInjected));
              
              invokeInjectorField(field, object, collectionOfServices);
         });
diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java
index 7d8fe7b..80a35a0 100644
--- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java
+++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/CollectionUtils.java
@@ -22,17 +22,7 @@ package org.apache.isis.core.metamodel.specloader;
 import java.lang.reflect.Field;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
 import java.util.function.Consumer;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 import javax.annotation.Nullable;
 
@@ -142,47 +132,5 @@ public final class CollectionUtils {
         }
 		
 	}
-    
-    // -- COLLECT ELEMENTS FROM STREAM
-
-	/**
-	 * Collects elements from stream into a collection that is compatible with the given typeOfCollection.
-	 * @param typeOfCollection
-	 * @param elementStream
-	 * @return
-	 * 
-	 * @throws IllegalArgumentException if the given typeOfCollection is not supported 
-	 */
-	public static <T> Collection<T> collectIntoUnmodifiableCompatibleWithCollectionType (
-			Class<?> typeOfCollection, Stream<? extends T> elementStream) {
-
-		if(SortedSet.class.equals(typeOfCollection)) {
-			return Collections.unmodifiableSortedSet(
-					elementStream.collect(Collectors.<T, SortedSet<T>>toCollection(TreeSet::new))
-			);
-		}
-		
-		if(Set.class.equals(typeOfCollection)) {
-			return Collections.unmodifiableSet(
-					elementStream.collect(Collectors.<T, Set<T>>toCollection(HashSet::new))
-			);
-		}
-		
-		if(List.class.equals(typeOfCollection)) {
-			return Collections.unmodifiableList(
-					elementStream.collect(Collectors.<T, List<T>>toCollection(ArrayList::new))
-			);
-		}
-		
-		if(Collection.class.equals(typeOfCollection)) {
-			return Collections.unmodifiableCollection(
-					elementStream.collect(Collectors.toCollection(ArrayList::new))
-			);
-		}
-		
-		throw new IllegalArgumentException(
-				String.format("Can not collect into %s. Only List, Set, SortedSet and Collection are supported.",
-						typeOfCollection.getClass().getName()));
-	}
 
 }

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