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:27 UTC
[2/3] zest-java git commit: Improved descriptors sorting logic to
limit iterations on candidates list.
Improved descriptors sorting logic to limit iterations on candidates list.
Project: http://git-wip-us.apache.org/repos/asf/zest-java/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-java/commit/7ba5335c
Tree: http://git-wip-us.apache.org/repos/asf/zest-java/tree/7ba5335c
Diff: http://git-wip-us.apache.org/repos/asf/zest-java/diff/7ba5335c
Branch: refs/heads/develop
Commit: 7ba5335c3e5515821e9e6a9820843efd4a0579bb
Parents: e1dccf2
Author: Jean-Michel Tonneau <jm...@alchemytec.com>
Authored: Wed Nov 30 12:18:27 2016 +0000
Committer: Paul Merlin <pa...@apache.org>
Committed: Sat Dec 3 14:46:39 2016 +0100
----------------------------------------------------------------------
.../zest/runtime/structure/TypeLookupImpl.java | 102 ++++++++++++++++---
1 file changed, 86 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/zest-java/blob/7ba5335c/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 cd077b0..5eac131 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
@@ -22,6 +22,7 @@ package org.apache.zest.runtime.structure;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Predicate;
@@ -152,33 +153,20 @@ class TypeLookupImpl
@Override
public List<EntityDescriptor> lookupEntityModels( final Class type )
{
- return entityModels.computeIfAbsent( type, key ->
- concat(
- allEntities().filter( ref -> new ExactTypeMatching<>( key ).test( ref ) ),
- allEntities().filter( ref -> new AssignableFromTypeMatching<>( key ).test( ref ) )
- ).distinct().collect( toList() )
- );
+ return entityModels.computeIfAbsent( type, key -> new TypeMatchingDescriptors<EntityDescriptor>(key).selectedFrom(allEntities()));
}
@Override
public ModelDescriptor lookupServiceModel( Type serviceType )
{
return serviceModels.computeIfAbsent( serviceType,
- key -> lookupServiceModels( key ).stream().findFirst().orElse( null ) );
+ key -> new BestTypeMatchingDescriptors<ModelDescriptor>(key).selectedFrom(allServices()).bestMatchOrElse(null));
}
@Override
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( toList() );
- } );
+ return servicesReferences.computeIfAbsent( type1, type ->new TypeMatchingDescriptors<ModelDescriptor>(type).selectedFrom(allServices()));
}
@Override
@@ -450,4 +438,86 @@ 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);
+ }
+ }
+ }
+
}