You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@polygene.apache.org by pa...@apache.org on 2016/12/03 14:52:28 UTC

[3/3] zest-java git commit: typelookup: refine Jean-Michel’s contribution

typelookup: refine Jean-Michel\u2019s contribution

formatting, naming, documentation
no behavior change

Closes #2


Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/96080d0a
Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/96080d0a
Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/96080d0a

Branch: refs/heads/develop
Commit: 96080d0ac4cb948c4890964fa64040586d337d9b
Parents: 7ba5335
Author: Paul Merlin <pa...@apache.org>
Authored: Sat Dec 3 14:40:49 2016 +0100
Committer: Paul Merlin <pa...@apache.org>
Committed: Sat Dec 3 15:51:53 2016 +0100

----------------------------------------------------------------------
 .../zest/runtime/structure/TypeLookupImpl.java  | 194 ++++++++++---------
 1 file changed, 107 insertions(+), 87 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-java/blob/96080d0a/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookupImpl.java
----------------------------------------------------------------------
diff --git a/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookupImpl.java b/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookupImpl.java
index 5eac131..a030a20 100644
--- a/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookupImpl.java
+++ b/core/runtime/src/main/java/org/apache/zest/runtime/structure/TypeLookupImpl.java
@@ -153,20 +153,26 @@ class TypeLookupImpl
     @Override
     public List<EntityDescriptor> lookupEntityModels( final Class type )
     {
-        return entityModels.computeIfAbsent( type, key -> new TypeMatchingDescriptors<EntityDescriptor>(key).selectedFrom(allEntities()));
+        return entityModels.computeIfAbsent(
+            type,
+            key -> new TypeMatchesSelector<EntityDescriptor>( key ).selectFrom( allEntities() ) );
     }
 
     @Override
     public ModelDescriptor lookupServiceModel( Type serviceType )
     {
-        return serviceModels.computeIfAbsent( serviceType,
-                                              key -> new BestTypeMatchingDescriptors<ModelDescriptor>(key).selectedFrom(allServices()).bestMatchOrElse(null));
+        return serviceModels.computeIfAbsent(
+            serviceType,
+            key -> new BestTypeMatchSelector<ModelDescriptor>( key ).selectFrom( allServices() )
+                                                                    .bestMatchOrElse( null ) );
     }
 
     @Override
-    public List<? extends ModelDescriptor> lookupServiceModels( final Type type1 )
+    public List<? extends ModelDescriptor> lookupServiceModels( final Type type )
     {
-        return servicesReferences.computeIfAbsent( type1, type ->new TypeMatchingDescriptors<ModelDescriptor>(type).selectedFrom(allServices()));
+        return servicesReferences.computeIfAbsent(
+            type,
+            key -> new TypeMatchesSelector<ModelDescriptor>( key ).selectFrom( allServices() ) );
     }
 
     @Override
@@ -400,6 +406,102 @@ class TypeLookupImpl
     }
 
     /**
+     * Selects descriptors by combining {@link ExactTypeMatching} and {@link AssignableFromTypeMatching}.
+     *
+     * Selected descriptors are sorted, exact matches first, assignable ones second.
+     * Other than that, original order is preserved.
+     *
+     * <code>
+     *     [ assignable1, matching1, assignable2, assignable3, matching2, non-matching-nor-assignable ]
+     * </code>
+     * results in
+     * <code>
+     *     [ matching1, matching2, assignable1, assignable2, assignable3 ]
+     * </code>
+     *
+     * @param <T> Descriptor type
+     */
+    private static class TypeMatchesSelector<T extends HasTypes> extends ArrayList<T>
+    {
+        private final ExactTypeMatching<T> exactMatchPredicate;
+        private final AssignableFromTypeMatching<T> assignablePredicate;
+        private Integer lastMatchIndex;
+
+        private TypeMatchesSelector( Type type )
+        {
+            this.exactMatchPredicate = new ExactTypeMatching<>( type );
+            this.assignablePredicate = new AssignableFromTypeMatching<>( type );
+        }
+
+        List<T> selectFrom( Stream<? extends T> candidates )
+        {
+            candidates.forEach( this::addDescriptor );
+            return this;
+        }
+
+        private void addDescriptor( T descriptor )
+        {
+            if( contains( descriptor ) )
+            {
+                return;
+            }
+            if( exactMatchPredicate.test( descriptor ) )
+            {
+                Integer nextMatchIndex = lastMatchIndex == null ? 0 : lastMatchIndex + 1;
+                add( nextMatchIndex, descriptor );
+                lastMatchIndex = nextMatchIndex;
+            }
+            else if( assignablePredicate.test( descriptor ) )
+            {
+                add( descriptor );
+            }
+        }
+
+        boolean containsExactMatches()
+        {
+            return lastMatchIndex != null;
+        }
+    }
+
+    /**
+     * Selects the best matching descriptor by combining {@link ExactTypeMatching} and {@link AssignableFromTypeMatching}.
+     *
+     * Selected descriptor is the first exact match if it exists, the first assignable otherwise.
+     *
+     * @param <T> Descriptor type
+     */
+    private static class BestTypeMatchSelector<T extends HasTypes>
+    {
+        private TypeMatchesSelector<T> descriptors;
+
+        BestTypeMatchSelector( Type type )
+        {
+            this.descriptors = new TypeMatchesSelector<>( type );
+        }
+
+        BestTypeMatchSelector<T> selectFrom( Stream<? extends T> candidates )
+        {
+            candidates.forEach( this::addDescriptor );
+            return this;
+        }
+
+        T bestMatchOrElse( T or )
+        {
+            return !descriptors.isEmpty() ? descriptors.get( 0 ) : or;
+        }
+
+        private void addDescriptor( T descriptor )
+        {
+            // Until an exact match is found, even if we already found assignable ones,
+            // keep selecting in case the last element is an exact match.
+            if( !descriptors.containsExactMatches() )
+            {
+                descriptors.addDescriptor( descriptor );
+            }
+        }
+    }
+
+    /**
      * This Predicate will filter out all Models that doesn't have the same visibility as the first one.
      */
     private static class SameVisibility<T extends ModelDescriptor>
@@ -438,86 +540,4 @@ class TypeLookupImpl
             return value;
         }
     }
-    
-    private static class TypeMatchingDescriptors<T extends HasTypes> extends ArrayList<T> {
-
-        /**
-         * mutable :-( But performance is an issue here.
-         */
-        private Integer lastMatchingindex;
-        private final ExactTypeMatching<T> exactMatchingPredicate;
-        private final AssignableFromTypeMatching<T> assignablePredicate;
-
-        private TypeMatchingDescriptors(Type type) {
-            this.lastMatchingindex = null;
-            this.exactMatchingPredicate = new ExactTypeMatching<>(type);
-            this.assignablePredicate = new AssignableFromTypeMatching<>(type);
-        }
-
-        TypeMatchingDescriptors<T> selectedFrom(Stream<? extends T> candidates){
-            candidates.forEach(this::smartAddition);
-            return this;
-        }
-        /**
-         * Sorts the descriptors in a common list : matching ones first,
-         * assignable ones follow. The order of arrival is important :
-         * 
-         * "{assignable1, matching1, assignable2,assignable3,matching2,
-         * non-matching-or-assignable}" should result in "{ matching1,
-         * matching2, assignable1, assignable2, assignable3}"
-         */
-        private  void smartAddition(T descriptor) {
-            if (contains(descriptor)) {
-                return;
-            }
-            if ( exactMatchingPredicate.test(descriptor)) {
-                Integer nextMatchingIdx = lastMatchingindex == null ? 0 : lastMatchingindex + 1;
-                add(nextMatchingIdx, descriptor);
-                lastMatchingindex = nextMatchingIdx;
-                return;
-            }
-            if (assignablePredicate.test(descriptor)) {
-                add(descriptor);
-            }
-        }
-
-        private  boolean containsExactMatches() {
-            return lastMatchingindex != null;
-        }
-
-    }
-
-    private static class BestTypeMatchingDescriptors<T extends HasTypes> {
-
-        private TypeMatchingDescriptors<T> descriptors;
-
-        private  BestTypeMatchingDescriptors(Type type) {
-            this(new TypeMatchingDescriptors<>(type));
-        }
-
-        private  BestTypeMatchingDescriptors(TypeMatchingDescriptors<T> descriptors) {
-            this.descriptors = descriptors;
-        }
-
-        BestTypeMatchingDescriptors<T> selectedFrom(Stream<? extends T> candidates) {
-            candidates.forEach(this::smartAddition);
-            return this;
-        }
-        
-        private T bestMatchOrElse(T or) {
-            return !descriptors.isEmpty() ? descriptors.get(0) : or;
-        }
-
-        /**
-         * We want the first matching if exists, the first assignable otherwise.
-         * While there is no matching descriptor, even if we found assignable
-         * ones, we keep searching in case the last element is a matching type.
-         */
-        private void smartAddition(T descriptor) {
-            if (!descriptors.containsExactMatches()) {
-                descriptors.smartAddition(descriptor);
-            }
-        }
-    }
-
 }