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);
- }
- }
- }
-
}