runtime: refine TypeLookup

Remove stream terminal operations here and there
Remove method that didn’t belong here
Add caching for frequently called methods


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

Branch: refs/heads/develop
Commit: d313c1329cf83265365ea1dfa2c28b6832847cf8
Parents: b4c2644
Author: Paul Merlin <[email protected]>
Authored: Mon Nov 28 15:49:02 2016 +0100
Committer: Paul Merlin <[email protected]>
Committed: Mon Nov 28 15:49:02 2016 +0100

----------------------------------------------------------------------
 .../apache/zest/api/structure/TypeLookup.java   |  30 ++-
 .../zest/runtime/structure/ModuleInstance.java  |  10 +-
 .../zest/runtime/structure/TypeLookupImpl.java  | 263 +++++++++++--------
 .../runtime/unitofwork/ModuleUnitOfWork.java    |   2 +-
 4 files changed, 185 insertions(+), 120 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-java/blob/d313c132/core/api/src/main/java/org/apache/zest/api/structure/TypeLookup.java
----------------------------------------------------------------------
diff --git 
a/core/api/src/main/java/org/apache/zest/api/structure/TypeLookup.java 
b/core/api/src/main/java/org/apache/zest/api/structure/TypeLookup.java
index ee2f9ec..2ea55bf 100644
--- a/core/api/src/main/java/org/apache/zest/api/structure/TypeLookup.java
+++ b/core/api/src/main/java/org/apache/zest/api/structure/TypeLookup.java
@@ -27,7 +27,6 @@ import org.apache.zest.api.composite.ModelDescriptor;
 import org.apache.zest.api.composite.TransientDescriptor;
 import org.apache.zest.api.entity.EntityDescriptor;
 import org.apache.zest.api.object.ObjectDescriptor;
-import org.apache.zest.api.service.ServiceReference;
 import org.apache.zest.api.value.ValueDescriptor;
 
 public interface TypeLookup
@@ -106,7 +105,7 @@ public interface TypeLookup
     /**
      * Lookup all Entity Models matching the given Type.
      *
-     * <p>Returned Iterable contains, in order, Entity Models that: </p>
+     * <p>Returned List contains, in order, Entity Models that: </p>
      *
      * <ul>
      * <li>exactly match the given type, in Visibility then Assembly order 
;</li>
@@ -125,7 +124,7 @@ public interface TypeLookup
      *
      * @return All matching Entity Models
      */
-    Iterable<? extends EntityDescriptor> lookupEntityModels( Class<?> type );
+    List<EntityDescriptor> lookupEntityModels( Class<?> type );
 
     /**
      * Lookup first ServiceDescriptor/ImportedServiceDescriptor matching the 
given Type.
@@ -161,15 +160,28 @@ public interface TypeLookup
      */
     List<? extends ModelDescriptor> lookupServiceModels( Type type );
 
-    Stream<? extends ObjectDescriptor> allObjects();
+    /**
+     * @return All visible Objects, in visibility order
+     */
+    Stream<ObjectDescriptor> allObjects();
 
-    Stream<? extends TransientDescriptor> allTransients();
+    /**
+     * @return All visible Transients, in visibility order
+     */
+    Stream<TransientDescriptor> allTransients();
 
-    Stream<? extends ValueDescriptor> allValues();
+    /**
+     * @return All visible Values, in visibility order
+     */
+    Stream<ValueDescriptor> allValues();
 
-    Stream<? extends EntityDescriptor> allEntities();
+    /**
+     * @return All visible Entities, in visibility order
+     */
+    Stream<EntityDescriptor> allEntities();
 
+    /**
+     * @return All visible Services, in visibility order
+     */
     Stream<? extends ModelDescriptor> allServices();
-
-    Stream<Class<?>> allVisibleObjects();
 }

http://git-wip-us.apache.org/repos/asf/zest-java/blob/d313c132/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleInstance.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleInstance.java
 
b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleInstance.java
index 96278ed..36a2f46 100644
--- 
a/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleInstance.java
+++ 
b/core/runtime/src/main/java/org/apache/zest/runtime/structure/ModuleInstance.java
@@ -26,6 +26,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Collectors;
@@ -58,6 +59,7 @@ import org.apache.zest.api.structure.LayerDescriptor;
 import org.apache.zest.api.structure.Module;
 import org.apache.zest.api.structure.ModuleDescriptor;
 import org.apache.zest.api.structure.TypeLookup;
+import org.apache.zest.api.type.HasTypes;
 import org.apache.zest.api.unitofwork.UnitOfWorkException;
 import org.apache.zest.api.unitofwork.UnitOfWorkFactory;
 import org.apache.zest.api.util.NullArgumentException;
@@ -173,7 +175,8 @@ public class ModuleInstance
 
         if( model == null )
         {
-            throw new NoSuchObjectException( mixinType.getName(), name(), 
typeLookup.allVisibleObjects() );
+            throw new NoSuchObjectException( mixinType.getName(), name(),
+                                             typeLookup.allObjects().flatMap( 
HasTypes::types ) );
         }
 
         InjectionContext injectionContext = new InjectionContext( 
model.module(), UsesInstance.EMPTY_USES.use( uses ) );
@@ -189,7 +192,8 @@ public class ModuleInstance
 
         if( model == null )
         {
-            throw new NoSuchObjectException( instance.getClass().getName(), 
name(), typeLookup.allVisibleObjects() );
+            throw new NoSuchObjectException( instance.getClass().getName(), 
name(),
+                                             typeLookup.allObjects().flatMap( 
HasTypes::types ) );
         }
 
         InjectionContext injectionContext = new InjectionContext( 
model.module(), UsesInstance.EMPTY_USES.use( uses ) );
@@ -398,7 +402,7 @@ public class ModuleInstance
         //noinspection unchecked
         return serviceModels.stream()
             .map( this::findServiceReferenceInstance )
-            .filter( ref -> ref != null )
+            .filter( Objects::nonNull )
             .filter( ref -> ref.hasType( serviceType ) )
             .map( ref -> (ServiceReference<T>) ref )
             .collect( Collectors.toList() );

http://git-wip-us.apache.org/repos/asf/zest-java/blob/d313c132/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 a36a65d..f9cc137 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
@@ -25,7 +25,7 @@ import java.lang.reflect.WildcardType;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Predicate;
-import java.util.stream.Collectors;
+import java.util.function.Supplier;
 import java.util.stream.Stream;
 import org.apache.zest.api.common.Visibility;
 import org.apache.zest.api.composite.AmbiguousTypeException;
@@ -38,6 +38,7 @@ import org.apache.zest.api.structure.TypeLookup;
 import org.apache.zest.api.type.HasTypes;
 import org.apache.zest.api.value.ValueDescriptor;
 
+import static java.util.stream.Collectors.toList;
 import static java.util.stream.Stream.concat;
 import static org.apache.zest.api.common.Visibility.application;
 import static org.apache.zest.api.common.Visibility.layer;
@@ -54,13 +55,18 @@ class TypeLookupImpl
     private final ModuleDescriptor moduleModel;
 
     // Eager instance objects
+    private final LazyValue<List<ObjectDescriptor>> allObjects;
+    private final LazyValue<List<TransientDescriptor>> allTransients;
+    private final LazyValue<List<ValueDescriptor>> allValues;
+    private final LazyValue<List<EntityDescriptor>> allEntities;
+    private final LazyValue<List<? extends ModelDescriptor>> allServices;
     private final ConcurrentHashMap<Class<?>, ObjectDescriptor> objectModels;
     private final ConcurrentHashMap<Class<?>, TransientDescriptor> 
transientModels;
     private final ConcurrentHashMap<Class<?>, ValueDescriptor> valueModels;
-    private final ConcurrentHashMap<Class<?>, List<? extends 
EntityDescriptor>> allEntityModels;
+    private final ConcurrentHashMap<Class<?>, List<EntityDescriptor>> 
allEntityModels;
     private final ConcurrentHashMap<Class<?>, EntityDescriptor> 
unambiguousEntityModels;
     private final ConcurrentHashMap<Type, ModelDescriptor> serviceModels;
-    private final ConcurrentHashMap<Type, List<ModelDescriptor>> 
servicesReferences;
+    private final ConcurrentHashMap<Type, List<? extends ModelDescriptor>> 
servicesReferences;
 
     /**
      * Create a new TypeLookup bound to the given moduleModel.
@@ -73,6 +79,11 @@ class TypeLookupImpl
         this.moduleModel = module;
 
         // Eager instance objects
+        allObjects = new LazyValue<>();
+        allTransients = new LazyValue<>();
+        allValues = new LazyValue<>();
+        allEntities = new LazyValue<>();
+        allServices = new LazyValue<>();
         objectModels = new ConcurrentHashMap<>();
         transientModels = new ConcurrentHashMap<>();
         valueModels = new ConcurrentHashMap<>();
@@ -102,7 +113,7 @@ class TypeLookupImpl
     {
         return objectModels.computeIfAbsent( type, key ->
         {
-            List<ObjectDescriptor> allModels = allObjects().collect( 
Collectors.toList() );
+            List<? extends ObjectDescriptor> allModels = getAllObjects();
             ObjectDescriptor model = ambiguityMatching( key, allModels, new 
ExactTypeMatching<>( key ) );
             if( model == null )
             {
@@ -132,7 +143,7 @@ class TypeLookupImpl
     {
         return transientModels.computeIfAbsent( type, key ->
         {
-            List<TransientDescriptor> allModels = allTransients().collect( 
Collectors.toList() );
+            List<? extends TransientDescriptor> allModels = getAllTransients();
             TransientDescriptor model = ambiguityMatching( key, allModels, new 
ExactTypeMatching<>( key ) );
             if( model == null )
             {
@@ -162,7 +173,7 @@ class TypeLookupImpl
     {
         return valueModels.computeIfAbsent( type, key ->
         {
-            List<ValueDescriptor> allModels = allValues().collect( 
Collectors.toList() );
+            List<? extends ValueDescriptor> allModels = getAllValues();
             ValueDescriptor model = ambiguityMatching( key, allModels, new 
ExactTypeMatching<>( key ) );
             if( model == null )
             {
@@ -195,7 +206,7 @@ class TypeLookupImpl
     {
         return unambiguousEntityModels.computeIfAbsent( type, key ->
         {
-            List<EntityDescriptor> allModels = allEntities().collect( 
Collectors.toList() );
+            List<? extends EntityDescriptor> allModels = getAllEntities();
             EntityDescriptor model = ambiguityMatching( key, allModels, new 
ExactTypeMatching<>( key ) );
             if( model == null )
             {
@@ -228,13 +239,13 @@ class TypeLookupImpl
      * @return All matching Entity Models
      */
     @Override
-    public Iterable<? extends EntityDescriptor> lookupEntityModels( final 
Class type )
+    public List<EntityDescriptor> lookupEntityModels( final Class type )
     {
         return allEntityModels.computeIfAbsent( type, key ->
             concat(
                 allEntities().filter( ref -> new ExactTypeMatching<>( key 
).test( ref ) ),
                 allEntities().filter( ref -> new AssignableFromTypeMatching<>( 
key ).test( ref ) )
-            ).distinct().collect( Collectors.toList() )
+            ).distinct().collect( toList() )
         );
     }
 
@@ -246,144 +257,163 @@ class TypeLookupImpl
     }
 
     @Override
-    public List<? extends ModelDescriptor> lookupServiceModels( Type type1 )
+    public List<? extends ModelDescriptor> lookupServiceModels( final Type 
type1 )
     {
         return servicesReferences.computeIfAbsent( type1, type ->
         {
             // There is a requirement that "exact match" services must be 
returned before "assignable match"
             // services, hence the dual streams instead of a OR filter.
-            return Stream.concat(
-                allServices()
-                    .filter( new ExactTypeMatching<>( type ) ),
-                allServices()
-                    .filter( new AssignableFromTypeMatching<>( type ) ) )
-                .distinct()
-                .collect( Collectors.toList() );
+            return Stream.concat( allServices().filter( new 
ExactTypeMatching<>( type ) ),
+                                  allServices().filter( new 
AssignableFromTypeMatching<>( type ) ) )
+                         .distinct()
+                         .collect( toList() );
         } );
     }
 
     @Override
-    public Stream<Class<?>> allVisibleObjects()
+    public Stream<ObjectDescriptor> allObjects()
     {
-        return allObjects().flatMap( HasTypes::types );
+        return getAllObjects().stream();
     }
 
-    @Override
-    public Stream<? extends ObjectDescriptor> allObjects()
+    private List<ObjectDescriptor> getAllObjects()
     {
-        return concat( moduleModel.objects(),
-                       concat(
-                           concat(
-                               moduleModel.layer().visibleObjects( layer ),
-                               moduleModel.layer().visibleObjects( application 
)
-                           ),
-                           moduleModel.layer()
-                               .usedLayers()
-                               .layers()
-                               .flatMap( layer -> layer.visibleObjects( 
application ) )
-                       )
+        return allObjects.computeIfAbsent(
+            () -> concat( moduleModel.objects(),
+                          concat(
+                              concat(
+                                  moduleModel.layer().visibleObjects( layer ),
+                                  moduleModel.layer()
+                                             .visibleObjects( application )
+                              ),
+                              moduleModel.layer()
+                                         .usedLayers()
+                                         .layers()
+                                         .flatMap( layer -> 
layer.visibleObjects( application ) )
+                          )
+            ).collect( toList() )
         );
     }
 
     @Override
-    public Stream<? extends TransientDescriptor> allTransients()
+    public Stream<TransientDescriptor> allTransients()
+    {
+        return getAllTransients().stream();
+    }
+
+    private List<TransientDescriptor> getAllTransients()
     {
-        return concat( moduleModel.transientComposites(),
-                       concat(
-                           concat(
-                               moduleModel.layer().visibleTransients( layer ),
-                               moduleModel.layer().visibleTransients( 
application )
-                           ),
-                           moduleModel.layer()
-                               .usedLayers()
-                               .layers()
-                               .flatMap( layer -> layer.visibleTransients( 
application ) )
-                       )
+        return allTransients.computeIfAbsent(
+            () -> concat( moduleModel.transientComposites(),
+                          concat(
+                              concat(
+                                  moduleModel.layer().visibleTransients( layer 
),
+                                  moduleModel.layer().visibleTransients( 
application )
+                              ),
+                              moduleModel.layer()
+                                         .usedLayers()
+                                         .layers()
+                                         .flatMap( layer -> 
layer.visibleTransients( application ) )
+                          )
+            ).collect( toList() )
         );
     }
 
     @Override
-    public Stream<? extends ValueDescriptor> allValues()
+    public Stream<ValueDescriptor> allValues()
     {
+        return getAllValues().stream();
+    }
 
-        return concat( moduleModel.valueComposites(),
-                       concat(
-                           concat( moduleModel.layer().visibleValues( layer ),
-                                   moduleModel.layer().visibleValues( 
application )
-                           ),
-                           moduleModel.layer()
-                               .usedLayers()
-                               .layers()
-                               .flatMap( layer1 -> layer1.visibleValues( 
application ) )
-                       )
+    private List<ValueDescriptor> getAllValues()
+    {
+        return allValues.computeIfAbsent(
+            () -> concat( moduleModel.valueComposites(),
+                          concat(
+                              concat( moduleModel.layer().visibleValues( layer 
),
+                                      moduleModel.layer().visibleValues( 
application )
+                              ),
+                              moduleModel.layer()
+                                         .usedLayers()
+                                         .layers()
+                                         .flatMap( layer1 -> 
layer1.visibleValues( application ) )
+                          )
+            ).collect( toList() )
         );
     }
 
     @Override
-    public Stream<? extends EntityDescriptor> allEntities()
+    public Stream<EntityDescriptor> allEntities()
+    {
+        return getAllEntities().stream();
+    }
+
+    private List<EntityDescriptor> getAllEntities()
     {
-        return concat( moduleModel.entityComposites(),
-                       concat(
-                           concat(
-                               moduleModel.layer().visibleEntities( layer ),
-                               moduleModel.layer().visibleEntities( 
application )
-                           ),
-                           moduleModel.layer()
-                               .usedLayers()
-                               .layers()
-                               .flatMap( layer -> layer.visibleEntities( 
application ) )
-                       )
+        return allEntities.computeIfAbsent(
+            () -> concat( moduleModel.entityComposites(),
+                          concat(
+                              concat(
+                                  moduleModel.layer().visibleEntities( layer ),
+                                  moduleModel.layer().visibleEntities( 
application )
+                              ),
+                              moduleModel.layer()
+                                         .usedLayers()
+                                         .layers()
+                                         .flatMap( layer -> 
layer.visibleEntities( application ) )
+                          )
+            ).collect( toList() )
         );
     }
 
     @Override
     public Stream<? extends ModelDescriptor> allServices()
     {
-        Stream<? extends ModelDescriptor> managedServices =
-            concat( moduleModel.serviceComposites(),
-                    concat(
+        return getAllServices().stream();
+    }
+
+    public List<? extends ModelDescriptor> getAllServices()
+    {
+        return allServices.computeIfAbsent(
+            () -> concat(
+                concat( moduleModel.serviceComposites(),
                         concat(
+                            concat(
+                                moduleModel.layer().visibleServices( layer ),
+                                moduleModel.layer().visibleServices( 
application )
+                            ),
                             moduleModel.layer()
-                                .visibleServices( layer ),
-                            moduleModel.layer()
-                                .visibleServices( application )
-                        ),
-                        moduleModel.layer()
-                            .usedLayers()
-                            .layers()
-                            .flatMap( layer -> layer.visibleServices( 
application ) )
-                    )
-            );
-        Stream<? extends ModelDescriptor> importedServices =
-            concat( moduleModel.importedServices(),
-                    concat(
+                                       .usedLayers()
+                                       .layers()
+                                       .flatMap( layer -> 
layer.visibleServices( application ) )
+                        )
+                ),
+                concat( moduleModel.importedServices(),
                         concat(
+                            concat(
+                                moduleModel.layer().visibleServices( layer ),
+                                moduleModel.layer().visibleServices( 
application )
+                            ),
                             moduleModel.layer()
-                                .visibleServices( layer ),
-                            moduleModel.layer()
-                                .visibleServices( application )
-                        ),
-                        moduleModel.layer()
-                            .usedLayers()
-                            .layers()
-                            .flatMap( layer -> layer.visibleServices( 
application ) )
-                    )
-            );
-        return concat( managedServices, importedServices );
+                                       .usedLayers()
+                                       .layers()
+                                       .flatMap( layer -> 
layer.visibleServices( application ) )
+                        )
+                )
+            ).collect( toList() )
+        );
     }
 
-    private <T extends ModelDescriptor> T ambiguityMatching(
+    private static <T extends ModelDescriptor> T ambiguityMatching(
         Class type,
         List<T> modelModules,
         TypeMatching<T> matching
     )
     {
         List<T> models = modelModules.stream()
-            .filter( matching )
-            .filter( new SameVisibility<>() )
-            .distinct()
-            .collect( Collectors.toList() );
-
+                                     .filter( matching.and( new 
SameVisibility<>() ) )
+                                     .distinct()
+                                     .collect( toList() );
         if( models.size() > 1 )
         {
             throw new AmbiguousTypeException( "More than one type matches " + 
type.getName() + ": " + models + "]" );
@@ -420,7 +450,7 @@ class TypeLookupImpl
                     // First check Foo
                     ParameterizedType parameterizedType = (ParameterizedType) 
lookedUpType;
                     Type rawType = parameterizedType.getRawType();
-                    if( !model.types().anyMatch( checkMatch( rawType ) ) )
+                    if( model.types().noneMatch( checkMatch( rawType ) ) )
                     {
                         return false;
                     }
@@ -438,7 +468,7 @@ class TypeLookupImpl
         protected abstract Predicate<Type> checkMatch( Type matchTo );
     }
 
-    private static final class ExactTypeMatching<T extends HasTypes> extends 
TypeMatching<T>
+    private static class ExactTypeMatching<T extends HasTypes> extends 
TypeMatching<T>
     {
         private ExactTypeMatching( Type lookedUpType )
         {
@@ -451,7 +481,7 @@ class TypeLookupImpl
         }
     }
 
-    private static final class AssignableFromTypeMatching<T extends HasTypes> 
extends TypeMatching<T>
+    private static class AssignableFromTypeMatching<T extends HasTypes> 
extends TypeMatching<T>
     {
         private AssignableFromTypeMatching( Type lookedUpType )
         {
@@ -464,17 +494,16 @@ class TypeLookupImpl
 //            if( matchTo instanceof Class )
             {
                 Class<?> clazz = (Class<?>) matchTo;
-                return candidate ->
-                    !candidate.equals( matchTo ) && clazz.isAssignableFrom( 
(Class<?>) candidate );
+                return candidate -> !candidate.equals( matchTo ) && 
clazz.isAssignableFrom( (Class<?>) candidate );
             }
 //            return candidate -> candidate.equals( matchTo );
         }
     }
 
     /**
-     * This Predicate will filter out all Models that doesn't have the same 
visisbility as the first one.
+     * This Predicate will filter out all Models that doesn't have the same 
visibility as the first one.
      */
-    private class SameVisibility<T extends ModelDescriptor>
+    private static class SameVisibility<T extends ModelDescriptor>
         implements Predicate<T>
     {
         private Visibility current = null;
@@ -490,4 +519,24 @@ class TypeLookupImpl
             return current == model.visibility();
         }
     }
+
+    private static class LazyValue<T>
+    {
+        private volatile T value;
+
+        public T computeIfAbsent( Supplier<T> supplier )
+        {
+            if( value == null )
+            {
+                synchronized( this )
+                {
+                    if( value == null )
+                    {
+                        value = supplier.get();
+                    }
+                }
+            }
+            return value;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/zest-java/blob/d313c132/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java
----------------------------------------------------------------------
diff --git 
a/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java
 
b/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java
index beadcf0..0d1e3bb 100644
--- 
a/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java
+++ 
b/core/runtime/src/main/java/org/apache/zest/runtime/unitofwork/ModuleUnitOfWork.java
@@ -293,7 +293,7 @@ public class ModuleUnitOfWork
     public <T> T get( Class<T> type, Identity identity )
         throws NoSuchEntityTypeException, NoSuchEntityException
     {
-        Iterable<? extends EntityDescriptor> models = 
module.typeLookup().lookupEntityModels( type );
+        Iterable<EntityDescriptor> models = 
module.typeLookup().lookupEntityModels( type );
 
         if( !models.iterator().hasNext() )
         {

Reply via email to