This is an automated email from the ASF dual-hosted git repository. danhaywood pushed a commit to branch ISIS-2050 in repository https://gitbox.apache.org/repos/asf/isis.git
commit 34a56c1a1e958ae32ab4a2ea3e59422b973b7010 Author: danhaywood <d...@haywood-associates.co.uk> AuthorDate: Wed Dec 12 23:52:54 2018 +0100 ISIS-2050: extends IntrospectionState with additional states for type vs member introspection; inlining methods to simplify ... with the aim of exposing the IntrospectionState upTo so can pass through and honour the phases. Removed the guards in introspectTypeHierarchy, don't think they are needed any more since only ever called from its caller which checks the introspectionState anyway --- .../metamodel/specloader/SpecificationLoader.java | 69 ++++++++-------------- .../specloader/specimpl/IntrospectionState.java | 16 ++++- .../specimpl/ObjectSpecificationAbstract.java | 30 +++++++--- .../specimpl/dflt/ObjectSpecificationDefault.java | 23 ++------ .../ObjectSpecificationOnStandaloneList.java | 2 +- .../IntrospectionState_comparable_Test.java | 20 +++---- 6 files changed, 78 insertions(+), 82 deletions(-) diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java index 6c5632c..843851a 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/SpecificationLoader.java @@ -240,7 +240,7 @@ public class SpecificationLoader implements ApplicationScopedComponent { public Object call() { final ObjectSpecificationAbstract specSpi = (ObjectSpecificationAbstract) specification; - specSpi.introspectUpTo(IntrospectionState.INTROSPECTED); + specSpi.introspectUpTo(IntrospectionState.FULLY_INTROSPECTED); return null; } @@ -395,7 +395,7 @@ public class SpecificationLoader implements ApplicationScopedComponent { try { final Class<?> cls = loadBuiltIn(className); - return internalLoadSpecification(cls); + return internalLoadSpecification(cls, null, IntrospectionState.FULLY_INTROSPECTED); } catch (final ClassNotFoundException e) { final ObjectSpecification spec = cache.get(className); if (spec == null) { @@ -410,7 +410,7 @@ public class SpecificationLoader implements ApplicationScopedComponent { */ @Programmatic public ObjectSpecification loadSpecification(final Class<?> type) { - final ObjectSpecification spec = internalLoadSpecification(type); + final ObjectSpecification spec = internalLoadSpecification(type, null, IntrospectionState.FULLY_INTROSPECTED); if(spec == null) { return null; } @@ -427,61 +427,43 @@ public class SpecificationLoader implements ApplicationScopedComponent { return spec; } - private ObjectSpecification internalLoadSpecification(final Class<?> type) { - return internalLoadSpecification(type, null, IntrospectionState.INTROSPECTED); - } - private ObjectSpecification internalLoadSpecification( final Class<?> type, final NatureOfService natureFallback, final IntrospectionState upTo) { final Class<?> substitutedType = classSubstitutor.getClass(type); - return substitutedType != null - ? loadSpecificationForSubstitutedClass(substitutedType, natureFallback, upTo) - : null; - } - - private ObjectSpecification loadSpecificationForSubstitutedClass( - final Class<?> type, - final NatureOfService natureFallback, - final IntrospectionState upTo) { - Assert.assertNotNull(type); + if (substitutedType == null) { + return null; + } + Assert.assertNotNull(substitutedType); - final String typeName = type.getName(); - final ObjectSpecification spec = cache.get(typeName); + final String typeName = substitutedType.getName(); + ObjectSpecification spec = cache.get(typeName); if (spec != null) { return spec; } - return loadSpecificationForSubstitutedClassSynchronized(type, natureFallback, upTo); - } - - - private synchronized ObjectSpecification loadSpecificationForSubstitutedClassSynchronized( - final Class<?> type, - final NatureOfService natureOfServiceFallback, - final IntrospectionState upTo) { + synchronized (this) { + // inside the synchronized block + spec = cache.get(typeName); + if (spec != null) { + return spec; + } - final String typeName = type.getName(); - final ObjectSpecification spec = cache.get(typeName); - if (spec != null) { - // because caller isn't synchronized. - return spec; - } + final ObjectSpecification specification = createSpecification(substitutedType, natureFallback); - final ObjectSpecification specification = createSpecification(type, natureOfServiceFallback); + // put into the cache prior to introspecting, to prevent + // infinite loops + cache.cache(typeName, specification); - // put into the cache prior to introspecting, to prevent - // infinite loops - cache.cache(typeName, specification); + if (state == State.INTROSPECTING) { + final ObjectSpecificationAbstract specSpi = (ObjectSpecificationAbstract) specification; + specSpi.introspectUpTo(upTo); + } - if (state == State.INTROSPECTING) { - final ObjectSpecificationAbstract specSpi = (ObjectSpecificationAbstract) specification; - specSpi.introspectUpTo(upTo); + return specification; } - - return specification; } /** @@ -493,7 +475,8 @@ public class SpecificationLoader implements ApplicationScopedComponent { boolean anyLoadedAsNull = false; for (final Class<?> typeToLoad : typesToLoad) { if (typeToLoad != typeToIgnore) { - final ObjectSpecification objectSpecification = internalLoadSpecification(typeToLoad); + final ObjectSpecification objectSpecification = internalLoadSpecification(typeToLoad, null, + IntrospectionState.FULLY_INTROSPECTED); final boolean loadedAsNull = (objectSpecification == null); anyLoadedAsNull = loadedAsNull || anyLoadedAsNull; } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/IntrospectionState.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/IntrospectionState.java index 83c91c4..869e2d1 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/IntrospectionState.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/IntrospectionState.java @@ -21,13 +21,23 @@ public enum IntrospectionState implements Comparable<IntrospectionState> { * ObjectSpecIdFacet only. */ NOT_INTROSPECTED, + + /** + * Interim stage, to avoid infinite loops while on way to being {@link #PARTIALLY_INTROSPECTED} + */ + TYPE_BEING_INTROSPECTED, + /** + * Type has been introspected (but not its members). + */ + PARTIALLY_INTROSPECTED, + /** - * Interim stage, to avoid infinite loops while on way to being {@link #INTROSPECTED} + * Interim stage, to avoid infinite loops while on way to being {@link #FULLY_INTROSPECTED} */ - BEING_INTROSPECTED, + MEMBERS_BEING_INTROSPECTED, /** * Fully introspected... class and also its members. */ - INTROSPECTED + FULLY_INTROSPECTED } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java index f4a8f89..068ffed 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/ObjectSpecificationAbstract.java @@ -247,7 +247,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem } protected boolean isNotIntrospected() { - return !(introspectionState == IntrospectionState.INTROSPECTED); + return !(introspectionState == IntrospectionState.FULLY_INTROSPECTED); } //endregion @@ -268,24 +268,38 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem public void introspectUpTo(final IntrospectionState upTo) { while(this.introspectionState.compareTo(upTo) < 0) { + switch (introspectionState) { case NOT_INTROSPECTED: // set to avoid infinite loops - this.introspectionState = IntrospectionState.BEING_INTROSPECTED; + this.introspectionState = IntrospectionState.TYPE_BEING_INTROSPECTED; try { introspectTypeHierarchy(); updateFromFacetValues(); - - introspectMembers(); - this.introspectionState = IntrospectionState.INTROSPECTED; + this.introspectionState = IntrospectionState.PARTIALLY_INTROSPECTED; } catch(Exception ex) { this.introspectionState = IntrospectionState.NOT_INTROSPECTED; throw ex; } break; - case BEING_INTROSPECTED: - case INTROSPECTED: + case TYPE_BEING_INTROSPECTED: + // nothing to do + break; + case PARTIALLY_INTROSPECTED: + // set to avoid infinite loops + this.introspectionState = IntrospectionState.MEMBERS_BEING_INTROSPECTED; + try { + introspectMembers(); + this.introspectionState = IntrospectionState.FULLY_INTROSPECTED; + } catch(Exception ex) { + this.introspectionState = IntrospectionState.PARTIALLY_INTROSPECTED; + throw ex; + } + break; + case MEMBERS_BEING_INTROSPECTED: + // nothing to do + case FULLY_INTROSPECTED: // nothing to do break; } @@ -296,7 +310,7 @@ public abstract class ObjectSpecificationAbstract extends FacetHolderImpl implem protected abstract void introspectMembers(); - protected void updateSuperclass(final Class<?> superclass) { + protected void loadSpecOfSuperclass(final Class<?> superclass) { if (superclass == null) { return; } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java index 1c98335..3fb3efb 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/dflt/ObjectSpecificationDefault.java @@ -113,15 +113,10 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl @Override protected void introspectTypeHierarchy() { - metadataProperties = null; - if(isNotIntrospected()) { - metadataProperties = facetedMethodsBuilder.introspectClass(); - } + metadataProperties = facetedMethodsBuilder.introspectClass(); // name - if(isNotIntrospected()) { - addNamedFacetAndPluralFacetIfRequired(); - } + addNamedFacetAndPluralFacetIfRequired(); // go no further if a value if(this.containsFacet(ValueFacet.class)) { @@ -132,10 +127,8 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl } // superclass - if(isNotIntrospected()) { - final Class<?> superclass = getCorrespondingClass().getSuperclass(); - updateSuperclass(superclass); - } + final Class<?> superclass = getCorrespondingClass().getSuperclass(); + loadSpecOfSuperclass(superclass); // walk superinterfaces @@ -158,12 +151,8 @@ public class ObjectSpecificationDefault extends ObjectSpecificationAbstract impl } } - if(isNotIntrospected()) { - updateAsSubclassTo(interfaceSpecList); - } - if(isNotIntrospected()) { - updateInterfaces(interfaceSpecList); - } + updateAsSubclassTo(interfaceSpecList); + updateInterfaces(interfaceSpecList); } diff --git a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java index 63a432c..977a2a0 100644 --- a/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java +++ b/core/metamodel/src/main/java/org/apache/isis/core/metamodel/specloader/specimpl/standalonelist/ObjectSpecificationOnStandaloneList.java @@ -67,7 +67,7 @@ public class ObjectSpecificationOnStandaloneList extends ObjectSpecificationAbst @Override protected void introspectTypeHierarchy() { - updateSuperclass(Object.class); + loadSpecOfSuperclass(Object.class); addFacet(new CollectionFacetOnStandaloneList(this)); addFacet(new TypeOfFacetDefaultToObject(this, getSpecificationLoader()) { diff --git a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/IntrospectionState_comparable_Test.java b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/IntrospectionState_comparable_Test.java index eefda8e..91ec216 100644 --- a/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/IntrospectionState_comparable_Test.java +++ b/core/metamodel/src/test/java/org/apache/isis/core/metamodel/specloader/specimpl/IntrospectionState_comparable_Test.java @@ -5,8 +5,8 @@ import org.hamcrest.Matcher; import org.hamcrest.TypeSafeMatcher; import org.junit.Test; -import static org.apache.isis.core.metamodel.specloader.specimpl.IntrospectionState.BEING_INTROSPECTED; -import static org.apache.isis.core.metamodel.specloader.specimpl.IntrospectionState.INTROSPECTED; +import static org.apache.isis.core.metamodel.specloader.specimpl.IntrospectionState.MEMBERS_BEING_INTROSPECTED; +import static org.apache.isis.core.metamodel.specloader.specimpl.IntrospectionState.FULLY_INTROSPECTED; import static org.apache.isis.core.metamodel.specloader.specimpl.IntrospectionState.NOT_INTROSPECTED; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; @@ -16,16 +16,16 @@ public class IntrospectionState_comparable_Test { @Test public void all_of_em() throws Exception { assertComparison(NOT_INTROSPECTED, NOT_INTROSPECTED, equal()); - assertComparison(NOT_INTROSPECTED, BEING_INTROSPECTED, negative()); - assertComparison(NOT_INTROSPECTED, INTROSPECTED, negative()); + assertComparison(NOT_INTROSPECTED, MEMBERS_BEING_INTROSPECTED, negative()); + assertComparison(NOT_INTROSPECTED, FULLY_INTROSPECTED, negative()); - assertComparison(BEING_INTROSPECTED, NOT_INTROSPECTED, positive()); - assertComparison(BEING_INTROSPECTED, BEING_INTROSPECTED, equal()); - assertComparison(BEING_INTROSPECTED, INTROSPECTED, negative()); + assertComparison(MEMBERS_BEING_INTROSPECTED, NOT_INTROSPECTED, positive()); + assertComparison(MEMBERS_BEING_INTROSPECTED, MEMBERS_BEING_INTROSPECTED, equal()); + assertComparison(MEMBERS_BEING_INTROSPECTED, FULLY_INTROSPECTED, negative()); - assertComparison(INTROSPECTED, NOT_INTROSPECTED, positive()); - assertComparison(INTROSPECTED, BEING_INTROSPECTED, positive()); - assertComparison(INTROSPECTED, INTROSPECTED, equal()); + assertComparison(FULLY_INTROSPECTED, NOT_INTROSPECTED, positive()); + assertComparison(FULLY_INTROSPECTED, MEMBERS_BEING_INTROSPECTED, positive()); + assertComparison(FULLY_INTROSPECTED, FULLY_INTROSPECTED, equal()); } private Matcher<Integer> equal() {