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 2019/09/30 23:28:17 UTC

[isis] branch v2 updated: ISIS-2158: spec-loading: fixing todo markers, removing hacks

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

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


The following commit(s) were added to refs/heads/v2 by this push:
     new 7dea892  ISIS-2158: spec-loading: fixing todo markers, removing hacks
7dea892 is described below

commit 7dea892a0cde917ae92f421a55dcebc4bca254f4
Author: Andi Huber <ah...@apache.org>
AuthorDate: Tue Oct 1 01:28:07 2019 +0200

    ISIS-2158: spec-loading: fixing todo markers, removing hacks
---
 .../apache/isis/commons/internal/debug/_Probe.java | 11 +++
 .../apache/isis/metamodel/spec/Hierarchical.java   | 18 ++---
 .../specloader/specimpl/FacetedMethodsBuilder.java | 60 +++++---------
 .../specimpl/ObjectSpecificationAbstract.java      | 94 ++++++++++++++--------
 .../specimpl/dflt/ObjectSpecificationDefault.java  | 23 +++---
 .../traverser/SpecificationTraverser.java          |  5 +-
 .../testspec/ObjectSpecificationStub.java          | 10 +--
 .../facets/object/query/VisitorForFromClause.java  |  9 ++-
 8 files changed, 118 insertions(+), 112 deletions(-)

diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/debug/_Probe.java b/core/commons/src/main/java/org/apache/isis/commons/internal/debug/_Probe.java
index 985d2e1..3bd851b 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/debug/_Probe.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/debug/_Probe.java
@@ -66,6 +66,7 @@ public class _Probe {
     private boolean silenced = false;
 
     private final LongAdder counter = new LongAdder();
+    private final LongAdder nanoCounter = new LongAdder();
 
     private _Probe(long maxCalls, MaxCallsReachedAction maxAction) {
         this.maxCalls = maxCalls;
@@ -176,6 +177,14 @@ public class _Probe {
         errOut("-------------------------------------");
         out=restore_out;
     }
+    
+    public void run(Runnable runnable) {
+        val t0 = System.nanoTime();
+        runnable.run();
+        val nanos = System.nanoTime() - t0;
+        nanoCounter.add(nanos);
+        println("total runtime %d ms", nanoCounter.longValue()/1000_000);
+    }
 
     // -- CONVENIENT DEBUG TOOLS (STATIC)
 
@@ -221,5 +230,7 @@ public class _Probe {
         out.println(String.format(emphasisFormat, message));
     }
 
+    
+
 
 }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/Hierarchical.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/Hierarchical.java
index b31ffff..8fb83de 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/Hierarchical.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/spec/Hierarchical.java
@@ -19,7 +19,7 @@
 
 package org.apache.isis.metamodel.spec;
 
-import java.util.List;
+import java.util.Collection;
 
 public interface Hierarchical {
 
@@ -30,10 +30,10 @@ public interface Hierarchical {
     boolean hasSubclasses();
 
     /**
-     * Get the list of specifications for all the interfaces that the class
+     * Get the set of specifications for all the interfaces that the class
      * represented by this specification implements.
      */
-    List<ObjectSpecification> interfaces();
+    Collection<ObjectSpecification> interfaces();
 
     /**
      * Determines if this specification represents the same specification, or a
@@ -52,18 +52,10 @@ public interface Hierarchical {
     }
 
     /**
-     * Direct subclasses only (same as {@link #subclasses(Depth)} with depth = {@link Depth#DIRECT}).
-     *
-     * @deprecated - use {@link #subclasses(Depth)}.
-     */
-    @Deprecated
-    List<ObjectSpecification> subclasses();
-
-    /**
-     * Get the list of specifications for the subclasses of the class
+     * Get the set of specifications for the subclasses of the class
      * represented by this specification
      */
-    List<ObjectSpecification> subclasses(Depth depth);
+    Collection<ObjectSpecification> subclasses(Depth depth);
 
     /**
      * Get the specification for this specification's class's superclass.
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
index cb43bb3..1f493cc 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/FacetedMethodsBuilder.java
@@ -31,7 +31,6 @@ import org.apache.isis.commons.exceptions.IsisException;
 import org.apache.isis.commons.internal.collections._Lists;
 import org.apache.isis.commons.internal.collections._Sets;
 import org.apache.isis.metamodel.MetaModelContext;
-import org.apache.isis.metamodel.commons.ListExtensions;
 import org.apache.isis.metamodel.commons.MethodUtil;
 import org.apache.isis.metamodel.commons.ToString;
 import org.apache.isis.metamodel.exceptions.MetaModelException;
@@ -341,60 +340,43 @@ public class FacetedMethodsBuilder {
         return actionFacetedMethods;
     }
 
-    private enum RecognisedHelpersStrategy {
-        SKIP, DONT_SKIP;
-        public boolean skip() {
-            return this == SKIP;
-        }
-    }
-
-    /**
-     * REVIEW: I'm not sure why we do two passes here.
-     *
-     * <p>
-     * Perhaps it's important to skip helpers first. I doubt it, though.
-     */
     private List<FacetedMethod> findActionFacetedMethods(
             final MethodScope methodScope) {
         if (log.isDebugEnabled()) {
             log.debug("introspecting {}: actions", getClassName());
         }
-        final List<FacetedMethod> actionFacetedMethods1 = findActionFacetedMethods(methodScope, RecognisedHelpersStrategy.SKIP);
-        final List<FacetedMethod> actionFacetedMethods2 = findActionFacetedMethods(methodScope, RecognisedHelpersStrategy.DONT_SKIP);
-        return ListExtensions.combineWith(actionFacetedMethods1, actionFacetedMethods2);
+        val actionFacetedMethods = _Lists.<FacetedMethod>newArrayList();
+        collectActionFacetedMethods(actionFacetedMethods, methodScope);
+        return actionFacetedMethods;
     }
 
-    private List<FacetedMethod> findActionFacetedMethods(
-            final MethodScope methodScope,
-            final RecognisedHelpersStrategy recognisedHelpersStrategy) {
+    private void collectActionFacetedMethods(
+            final List<FacetedMethod> actionFacetedMethods,
+            final MethodScope methodScope) {
 
         if (log.isDebugEnabled()) {
             log.debug("  looking for action methods");
         }
 
-        final List<FacetedMethod> actionFacetedMethods = _Lists.newArrayList();
-
         for (int i = 0; i < methods.size(); i++) {
             final Method method = methods.get(i);
             if (method == null) {
                 continue;
             }
-            final FacetedMethod actionPeer = findActionFacetedMethod(methodScope, recognisedHelpersStrategy, method);
+            final FacetedMethod actionPeer = findActionFacetedMethod(methodScope, method);
             if (actionPeer != null) {
                 methods.set(i, null);
                 actionFacetedMethods.add(actionPeer);
             }
         }
-
-        return actionFacetedMethods;
+        
     }
 
     private FacetedMethod findActionFacetedMethod(
             final MethodScope methodScope,
-            final RecognisedHelpersStrategy recognisedHelpersStrategy,
             final Method actionMethod) {
 
-        if (!representsAction(actionMethod, methodScope, recognisedHelpersStrategy)) {
+        if (!representsAction(actionMethod, methodScope)) {
             return null;
         }
 
@@ -434,8 +416,7 @@ public class FacetedMethodsBuilder {
 
     private boolean representsAction(
             final Method actionMethod,
-            final MethodScope methodScope,
-            final RecognisedHelpersStrategy recognisedHelpersStrategy) {
+            final MethodScope methodScope) {
 
         if (!MethodUtil.inScope(actionMethod, methodScope)) {
             return false;
@@ -455,26 +436,27 @@ public class FacetedMethodsBuilder {
             return false;
         }
 
+        // ensure we can load specs for all the params
         if (!loadParamSpecs(actionMethod)) {
             return false;
         }
 
-        if (getFacetProcessor().recognizes(actionMethod)) {
-            // a bit of a hack
-            if (actionMethod.getName().startsWith("set")) {
-                return false;
-            }
-            if (recognisedHelpersStrategy.skip()) {
-                log.debug("  skipping possible helper method {0}", actionMethod);
+        if(explicitActionAnnotationConfigured()) {
+            if(!Annotations.isAnnotationPresent(actionMethod, Action.class)) {
                 return false;
             }
-        }
+            // we have @Action, so fall through
+            
+        } else {
 
-        if(explicitActionAnnotationConfigured()) {
-            if(!Annotations.isAnnotationPresent(actionMethod, Action.class)) {
+            // exclude those that have eg. reserved prefixes
+            if (getFacetProcessor().recognizes(actionMethod)) {
                 return false;
             }
+            // we have a valid action candidate, so fall through
+            
         }
+        
         log.debug("  identified action {0}", actionMethod);
         return true;
     }
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
index ef972d8..85c7ad7 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java
@@ -19,9 +19,12 @@
 
 package org.apache.isis.metamodel.specloader.specimpl;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.function.Function;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -100,11 +103,30 @@ import lombok.Getter;
 import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
-@Log4j2
+@Log4j2 //@EqualsAndHashCode(of = "correspondingClass", callSuper = false)
 public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implements ObjectSpecification {
 
-    private static class SubclassList {
-        private final List<ObjectSpecification> classes = _Lists.newArrayList();
+//    private static class Subclasses {
+//        private final Set<ObjectSpecification> classes = new HashSet<>();
+//
+//        public void addSubclass(final ObjectSpecification subclass) {
+//            if(classes.contains(subclass)) {
+//                return;
+//            }
+//            classes.add(subclass);
+//        }
+//
+//        public boolean hasSubclasses() {
+//            return !classes.isEmpty();
+//        }
+//
+//        public Collection<ObjectSpecification> toCollection() {
+//            return Collections.unmodifiableSet(classes);
+//        }
+//    }
+
+    private static class Subclasses {
+        private final List<ObjectSpecification> classes = new ArrayList<>();
 
         public void addSubclass(final ObjectSpecification subclass) {
             if(classes.contains(subclass)) {
@@ -117,11 +139,12 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             return !classes.isEmpty();
         }
 
-        public List<ObjectSpecification> toList() {
+        public List<ObjectSpecification> toCollection() {
             return Collections.unmodifiableList(classes);
         }
     }
-
+    
+    
     // -- fields
 
     //protected final ServiceInjector servicesInjector;
@@ -146,9 +169,9 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
     }
 
     private final List<ObjectSpecification> interfaces = _Lists.newArrayList();
-    private final SubclassList directSubclasses = new SubclassList();
+    private final Subclasses directSubclasses = new Subclasses();
     // built lazily
-    private SubclassList transitiveSubclasses;
+    private Subclasses transitiveSubclasses;
 
     private final Class<?> correspondingClass;
     private final String fullName;
@@ -169,6 +192,11 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
 
     private IntrospectionState introspectionState = IntrospectionState.NOT_INTROSPECTED;
 
+    private final static Set<String> exclusions = _Sets.of( //TODO[2133] make this configurable, or find an alternative, perhaps a specific type annotation?
+            "org.apache.isis.extensions.fixtures.fixturescripts.FixtureResult",
+            "org.apache.isis.extensions.fixtures.fixturescripts.FixtureScript"
+            );
+    
 
     // -- Constructor
     public ObjectSpecificationAbstract(
@@ -181,13 +209,6 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
         this.fullName = introspectedClass.getName();
         this.shortName = shortName;
 
-        val exclusions = _Sets.of( //TODO[2133] make this configurable, or find an alternative, perhaps a specific type annotation?
-                "org.apache.isis.extensions.fixtures.legacy.fixturescripts.FixtureResult",
-                "org.apache.isis.extensions.fixtures.legacy.fixturescripts.FixtureScript",
-                "org.apache.isis.applib.fixturescripts.FixtureResult",
-                "org.apache.isis.applib.fixturescripts.FixtureScript"
-                );
-
         this.isAbstract = ClassExtensions.isAbstract(introspectedClass);
         this.excludedFromMetamodel = _Reflect
                 .streamTypeHierarchy(introspectedClass, /*includeInterfaces*/ false)
@@ -246,24 +267,29 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
         return fullName;
     }
 
-
     /**
      * Keeps introspecting up to the level required.
      */
     public void introspectUpTo(final IntrospectionState upTo) {
+        
+        if(!isLessThan(upTo)) {
+            return; // optimization
+        }
 
-        log.debug("introspectingUpTo: {}, {}", getFullIdentifier(), upTo);
-
+        if(log.isDebugEnabled()) {
+            log.debug("introspectingUpTo: {}, {}", getFullIdentifier(), upTo);
+        }
+        
         switch (introspectionState) {
         case NOT_INTROSPECTED:
-            if(this.introspectionState.compareTo(upTo) < 0) {
+            if(isLessThan(upTo)) {
                 // set to avoid infinite loops
                 this.introspectionState = IntrospectionState.TYPE_BEING_INTROSPECTED;
                 introspectTypeHierarchy();
                 updateFromFacetValues();
                 this.introspectionState = IntrospectionState.TYPE_INTROSPECTED;
             }
-            if(this.introspectionState.compareTo(upTo) < 0) {
+            if(isLessThan(upTo)) {
                 this.introspectionState = IntrospectionState.MEMBERS_BEING_INTROSPECTED;
                 introspectMembers();
                 this.introspectionState = IntrospectionState.TYPE_AND_MEMBERS_INTROSPECTED;
@@ -274,7 +300,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             // nothing to do
             break;
         case TYPE_INTROSPECTED:
-            if(this.introspectionState.compareTo(upTo) < 0) {
+            if(isLessThan(upTo)) {
                 // set to avoid infinite loops
                 this.introspectionState = IntrospectionState.MEMBERS_BEING_INTROSPECTED;
                 introspectMembers();
@@ -289,6 +315,11 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
         }
     }
 
+    private boolean isLessThan(IntrospectionState upTo) {
+        return this.introspectionState.compareTo(upTo) < 0;
+    }
+    
+    
     protected abstract void introspectTypeHierarchy();
     protected abstract void introspectMembers();
 
@@ -584,19 +615,14 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
     }
 
     @Override
-    public List<ObjectSpecification> interfaces() {
+    public Collection<ObjectSpecification> interfaces() {
         return Collections.unmodifiableList(interfaces);
     }
 
     @Override
-    public List<ObjectSpecification> subclasses() {
-        return subclasses(Depth.DIRECT);
-    }
-
-    @Override
-    public List<ObjectSpecification> subclasses(final Depth depth) {
+    public Collection<ObjectSpecification> subclasses(final Depth depth) {
         if (depth == Depth.DIRECT) {
-            return directSubclasses.toList();
+            return directSubclasses.toCollection();
         }
 
         // depth == Depth.TRANSITIVE)
@@ -604,11 +630,11 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
             transitiveSubclasses = transitiveSubclasses();
         }
 
-        return transitiveSubclasses.toList();
+        return transitiveSubclasses.toCollection();
     }
 
-    private synchronized SubclassList transitiveSubclasses() {
-        final SubclassList appendTo = new SubclassList();
+    private synchronized Subclasses transitiveSubclasses() {
+        final Subclasses appendTo = new Subclasses();
         appendSubclasses(this, appendTo);
         transitiveSubclasses = appendTo;
         return transitiveSubclasses;
@@ -616,9 +642,9 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
 
     private void appendSubclasses(
             final ObjectSpecification objectSpecification,
-            final SubclassList appendTo) {
+            final Subclasses appendTo) {
 
-        final List<ObjectSpecification> directSubclasses = objectSpecification.subclasses(Depth.DIRECT);
+        val directSubclasses = objectSpecification.subclasses(Depth.DIRECT);
         for (ObjectSpecification subclass : directSubclasses) {
             appendTo.addSubclass(subclass);
             appendSubclasses(subclass, appendTo);
@@ -1195,7 +1221,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem
         str.append("class", getFullIdentifier());
         return str.toString();
     }
-
+    
     // -- GUARDS
 
     private boolean contributeeAndMixedInAssociationsAdded;
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
index f8bbefc..d30e80c 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java
@@ -69,9 +69,10 @@ import org.apache.isis.metamodel.specloader.specimpl.OneToOneAssociationDefault;
 
 import static org.apache.isis.commons.internal.base._With.mapIfPresentElse;
 
+import lombok.val;
 import lombok.extern.log4j.Log4j2;
 
-@Log4j2
+@Log4j2 
 public class ObjectSpecificationDefault extends ObjectSpecificationAbstract implements FacetHolder {
 
     private static final ClassSubstitutor classSubstitutor = new ClassSubstitutor();
@@ -122,9 +123,9 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
             return;
         }
 
-        final DomainServiceFacet facet = getFacet(DomainServiceFacet.class);
-        final boolean serviceWithNatureOfDomain = facet != null && facet.getNatureOfService() == NatureOfService.DOMAIN;
-        if (serviceWithNatureOfDomain) {
+        val domainServiceFacet = getFacet(DomainServiceFacet.class);
+        val isServiceWithNatureOfDomain = domainServiceFacet != null && domainServiceFacet.getNatureOfService() == NatureOfService.DOMAIN;
+        if (isServiceWithNatureOfDomain) {
             if (log.isDebugEnabled()) {
                 log.debug("skipping type hierarchy introspection for domain service with natureOfService = DOMAIN {}", getFullIdentifier());
             }
@@ -148,10 +149,10 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
         //
         final Class<?>[] interfaceTypes = getCorrespondingClass().getInterfaces();
         final List<ObjectSpecification> interfaceSpecList = _Lists.newArrayList();
-        for (final Class<?> interfaceType : interfaceTypes) {
-            final Class<?> substitutedInterfaceType = classSubstitutor.getClass(interfaceType);
+        for (val interfaceType : interfaceTypes) {
+            val substitutedInterfaceType = classSubstitutor.getClass(interfaceType);
             if (substitutedInterfaceType != null) {
-                final ObjectSpecification interfaceSpec = getSpecificationLoader().loadSpecification(substitutedInterfaceType);
+                val interfaceSpec = getSpecificationLoader().loadSpecification(substitutedInterfaceType);
                 interfaceSpecList.add(interfaceSpec);
             }
         }
@@ -159,9 +160,9 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
         updateAsSubclassTo(interfaceSpecList);
         updateInterfaces(interfaceSpecList);
     }
-
+    
     @Override
-    protected synchronized void introspectMembers() {
+    protected void introspectMembers() {
 
         if(this.containsFacet(ValueFacet.class)) {
             if (log.isDebugEnabled()) {
@@ -171,10 +172,10 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl
         }
 
         // associations and actions
-        final List<ObjectAssociation> associations = createAssociations();
+        val associations = createAssociations();
         sortAndUpdateAssociations(associations);
 
-        final List<ObjectAction> actions = createActions();
+        val actions = createActions();
         sortCacheAndUpdateActions(actions);
 
         postProcess();
diff --git a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/traverser/SpecificationTraverser.java b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/traverser/SpecificationTraverser.java
index ad6df36..d5a86f1 100644
--- a/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/traverser/SpecificationTraverser.java
+++ b/core/metamodel/src/main/java/org/apache/isis/metamodel/specloader/traverser/SpecificationTraverser.java
@@ -32,10 +32,7 @@ public class SpecificationTraverser {
      * and the parameterized type.
      */
     public void traverseTypes(final Method method, final Collection<Class<?>> discoveredTypes) {
-        final TypeExtractorMethodReturn returnTypes = new TypeExtractorMethodReturn(method);
-        for (final Class<?> returnType : returnTypes) {
-            discoveredTypes.add(returnType);
-        }
+        new TypeExtractorMethodReturn(method).forEach(discoveredTypes::add);
     }
 
 }
diff --git a/core/metamodel/src/test/java/org/apache/isis/metamodel/testspec/ObjectSpecificationStub.java b/core/metamodel/src/test/java/org/apache/isis/metamodel/testspec/ObjectSpecificationStub.java
index 57e6550..5d22d6f 100644
--- a/core/metamodel/src/test/java/org/apache/isis/metamodel/testspec/ObjectSpecificationStub.java
+++ b/core/metamodel/src/test/java/org/apache/isis/metamodel/testspec/ObjectSpecificationStub.java
@@ -21,6 +21,7 @@ package org.apache.isis.metamodel.testspec;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Stream;
 
 import org.apache.isis.applib.Identifier;
@@ -51,7 +52,7 @@ public class ObjectSpecificationStub extends FacetHolderImpl implements ObjectSp
     private ObjectAction action;
     public List<ObjectAssociation> fields = _Lists.newArrayList();
     private final String name;
-    private List<ObjectSpecification> subclasses = Collections.emptyList();
+    private Set<ObjectSpecification> subclasses = Collections.emptySet();
     private String title;
     /**
      * lazily derived, see {@link #getSpecId()} 
@@ -237,16 +238,11 @@ public class ObjectSpecificationStub extends FacetHolderImpl implements ObjectSp
     }
 
     @Override
-    public List<ObjectSpecification> subclasses() {
+    public Set<ObjectSpecification> subclasses(final Depth depth) {
         return subclasses;
     }
 
     @Override
-    public List<ObjectSpecification> subclasses(final Depth depth) {
-        return subclasses();
-    }
-
-    @Override
     public ObjectSpecification superclass() {
         return null;
     }
diff --git a/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/facets/object/query/VisitorForFromClause.java b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/facets/object/query/VisitorForFromClause.java
index 135fad7..ffe3eb3 100644
--- a/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/facets/object/query/VisitorForFromClause.java
+++ b/core/plugins/jdo/common/src/main/java/org/apache/isis/jdo/metamodel/facets/object/query/VisitorForFromClause.java
@@ -18,7 +18,6 @@
  */
 package org.apache.isis.jdo.metamodel.facets.object.query;
 
-import java.util.List;
 import java.util.Objects;
 
 import org.apache.isis.applib.Identifier;
@@ -26,6 +25,8 @@ import org.apache.isis.metamodel.spec.Hierarchical;
 import org.apache.isis.metamodel.spec.ObjectSpecification;
 import org.apache.isis.metamodel.specloader.validator.ValidationFailures;
 
+import lombok.val;
+
 class VisitorForFromClause extends VisitorForClauseAbstract {
 
     VisitorForFromClause(
@@ -45,12 +46,12 @@ class VisitorForFromClause extends VisitorForClauseAbstract {
             final String query,
             final ValidationFailures validationFailures) {
 
-        final String className = objectSpec.getCorrespondingClass().getName();
+        val className = objectSpec.getCorrespondingClass().getName();
         if (Objects.equals(classNameFromClause, className)) {
             return;
         }
-        final ObjectSpecification fromSpec = getSpecificationLoader().loadSpecification(classNameFromClause);
-        List<ObjectSpecification> subclasses = fromSpec.subclasses(Hierarchical.Depth.TRANSITIVE);
+        val fromSpec = getSpecificationLoader().loadSpecification(classNameFromClause);
+        val subclasses = fromSpec.subclasses(Hierarchical.Depth.TRANSITIVE);
         if(subclasses.contains(objectSpec)) {
             return;
         }