You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by da...@apache.org on 2018/10/03 19:26:20 UTC

[isis] branch ISIS-1974 created (now 0e19b19)

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

danhaywood pushed a change to branch ISIS-1974
in repository https://gitbox.apache.org/repos/asf/isis.git.


      at 0e19b19  ISIS-1974: also processes domain types, introduces notion

This branch includes the following new commits:

     new 0e19b19  ISIS-1974: also processes domain types, introduces notion

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[isis] 01/01: ISIS-1974: also processes domain types, introduces notion

Posted by da...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

danhaywood pushed a commit to branch ISIS-1974
in repository https://gitbox.apache.org/repos/asf/isis.git

commit 0e19b194cbf7978b70c23028cbd87f684094ce2a
Author: danhaywood <da...@haywood-associates.co.uk>
AuthorDate: Wed Oct 3 18:54:15 2018 +0100

    ISIS-1974: also processes domain types, introduces notion
    
    of stub processing vs complete
---
 .../java/org/apache/isis/applib/AppManifest.java   |  27 +++++-
 .../metamodel/specloader/SpecificationLoader.java  | 108 ++++++++++++---------
 .../IsisComponentProvider.java                     |   8 ++
 3 files changed, 98 insertions(+), 45 deletions(-)

diff --git a/core/applib/src/main/java/org/apache/isis/applib/AppManifest.java b/core/applib/src/main/java/org/apache/isis/applib/AppManifest.java
index 22c4fe4..ba1d991 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/AppManifest.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/AppManifest.java
@@ -32,7 +32,6 @@ import java.util.Set;
 import javax.jdo.annotations.PersistenceCapable;
 
 import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
 
 import org.reflections.vfs.SystemDir;
 import org.reflections.vfs.Vfs;
@@ -245,6 +244,32 @@ public interface AppManifest {
             urlTypes.addAll(Arrays.asList(Vfs.DefaultUrlTypes.values()));
 
             return urlTypes;
+
+        }
+
+        private Set<Class<?>> domainObjectTypes;
+        private Set<Class<?>> viewModelTypes;
+        private Set<Class<?>> xmlElementTypes;
+
+        public Set<Class<?>> getDomainObjectTypes() {
+            return domainObjectTypes;
+        }
+        public void setDomainObjectTypes(final Set<Class<?>> domainObjectTypes) {
+            this.domainObjectTypes = domainObjectTypes;
+        }
+
+        public Set<Class<?>> getViewModelTypes() {
+            return viewModelTypes;
+        }
+        public void setViewModelTypes(final Set<Class<?>> viewModelTypes) {
+            this.viewModelTypes = viewModelTypes;
+        }
+
+        public Set<Class<?>> getXmlElementTypes() {
+            return xmlElementTypes;
+        }
+        public void setXmlElementTypes(final Set<Class<?>> xmlElementTypes) {
+            this.xmlElementTypes = xmlElementTypes;
         }
         //endregion
 
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 7e52cf6..2120843 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
@@ -21,7 +21,6 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.Future;
 
@@ -188,8 +187,24 @@ public class SpecificationLoader implements ApplicationScopedComponent {
 
         state = State.CACHING;
 
-        loadSpecificationsForServices();
-        loadSpecificationsForMixins();
+        // need to completely load services and mixins (synchronously)
+        loadSpecificationsFor(
+                allServiceClasses(),
+                NatureOfService.DOMAIN, IntrospectionStrategy.STUB);
+        loadSpecificationsFor(
+                AppManifest.Registry.instance().getMixinTypes(),
+                null, IntrospectionStrategy.STUB);
+
+        loadSpecificationsFor(
+                AppManifest.Registry.instance().getDomainObjectTypes(),
+                null, IntrospectionStrategy.STUB);
+        loadSpecificationsFor(
+                AppManifest.Registry.instance().getViewModelTypes(),
+                null, IntrospectionStrategy.STUB);
+        loadSpecificationsFor(
+                AppManifest.Registry.instance().getXmlElementTypes(),
+                null, IntrospectionStrategy.STUB);
+
         cacheBySpecId();
 
         state = State.INTROSPECTING;
@@ -218,35 +233,22 @@ public class SpecificationLoader implements ApplicationScopedComponent {
 
     }
 
-    private void loadSpecificationsForServices() {
-        final Properties metadataProperties = new Properties();
-
-        List<Class<?>> classes = allServiceClasses();
-        for (final Class<?> serviceClass : classes) {
-            final DomainService domainService = serviceClass.getAnnotation(DomainService.class);
-            final NatureOfService nature = domainService != null ? domainService.nature() : NatureOfService.DOMAIN;
-            // will 'markAsService'
-            ObjectSpecification objectSpecification = internalLoadSpecification(serviceClass, nature);
-
-            facetProcessorObjectSpecId.process(
-                    serviceClass, metadataProperties,
-                    MethodRemoverConstants.NULL, objectSpecification);
+    private void loadSpecificationsFor(
+            final Collection<Class<?>> domainTypes,
+            final NatureOfService natureOfServiceFallback,
+            final IntrospectionStrategy introspectionStrategy) {
+        if(domainTypes == null || domainTypes.isEmpty()) {
+            return;
         }
-    }
-
-    private void loadSpecificationsForMixins() {
         final Properties metadataProperties = new Properties();
+        for (final Class<?> domainType : domainTypes) {
+
+            ObjectSpecification objectSpecification =
+                    internalLoadSpecification(domainType, natureOfServiceFallback, introspectionStrategy);
 
-        final Set<Class<?>> mixinTypes = AppManifest.Registry.instance().getMixinTypes();
-        if(mixinTypes == null) {
-            return;
-        }
-        for (final Class<?> mixinType : mixinTypes) {
-            ObjectSpecification objectSpecification = internalLoadSpecification(mixinType);
             facetProcessorObjectSpecId.process(
-                    mixinType, metadataProperties,
+                    domainType, metadataProperties,
                     MethodRemoverConstants.NULL, objectSpecification);
-
         }
     }
 
@@ -388,22 +390,26 @@ public class SpecificationLoader implements ApplicationScopedComponent {
         return spec;
     }
 
+    enum IntrospectionStrategy {STUB, COMPLETE}
     private ObjectSpecification internalLoadSpecification(final Class<?> type) {
-        // superclasses tend to be loaded via this method, implicitly.
-        // what can happen is that a subclass domain service, eg a fake one such as FakeLocationLookupService
-        // can be registered first prior to the "real" implementation.  As belt-n-braces, if that superclass is
-        // annotated using @DomainService, then we ensure its own spec is created correctly as a service spec.
-        final DomainService domainServiceIfAny = type.getAnnotation(DomainService.class);
-        final NatureOfService natureOfServiceIfAny = domainServiceIfAny != null ? domainServiceIfAny.nature() : null;
-        return internalLoadSpecification(type, natureOfServiceIfAny);
+        return internalLoadSpecification(type, null, IntrospectionStrategy.COMPLETE);
     }
 
-    private ObjectSpecification internalLoadSpecification(final Class<?> type, final NatureOfService nature) {
+    private ObjectSpecification internalLoadSpecification(
+            final Class<?> type,
+            final NatureOfService natureFallback,
+            final IntrospectionStrategy introspectionStrategy) {
+
         final Class<?> substitutedType = classSubstitutor.getClass(type);
-        return substitutedType != null ? loadSpecificationForSubstitutedClass(substitutedType, nature) : null;
+        return substitutedType != null
+                ? loadSpecificationForSubstitutedClass(substitutedType, natureFallback, introspectionStrategy)
+                : null;
     }
 
-    private ObjectSpecification loadSpecificationForSubstitutedClass(final Class<?> type, final NatureOfService nature) {
+    private ObjectSpecification loadSpecificationForSubstitutedClass(
+            final Class<?> type,
+            final NatureOfService natureFallback,
+            final IntrospectionStrategy introspectionStrategy) {
         Assert.assertNotNull(type);
 
         final String typeName = type.getName();
@@ -412,12 +418,14 @@ public class SpecificationLoader implements ApplicationScopedComponent {
             return spec;
         }
 
-        return loadSpecificationForSubstitutedClassSynchronized(type, nature);
+        return loadSpecificationForSubstitutedClassSynchronized(type, natureFallback, introspectionStrategy);
     }
 
+
     private synchronized ObjectSpecification loadSpecificationForSubstitutedClassSynchronized(
             final Class<?> type,
-            final NatureOfService natureOfService) {
+            final NatureOfService natureOfServiceFallback,
+            final IntrospectionStrategy introspectionStrategy) {
 
         final String typeName = type.getName();
         final ObjectSpecification spec = cache.get(typeName);
@@ -425,13 +433,16 @@ public class SpecificationLoader implements ApplicationScopedComponent {
             // because caller isn't synchronized.
             return spec;
         }
-        final ObjectSpecification specification = createSpecification(type, natureOfService);
+
+        final ObjectSpecification specification = createSpecification(type, natureOfServiceFallback);
 
         // put into the cache prior to introspecting, to prevent
         // infinite loops
         cache.cache(typeName, specification);
 
-        introspectIfRequired(specification);
+        if(introspectionStrategy == IntrospectionStrategy.COMPLETE) {
+            introspectIfRequired(specification);
+        }
 
         return specification;
     }
@@ -466,23 +477,32 @@ public class SpecificationLoader implements ApplicationScopedComponent {
      */
     private ObjectSpecification createSpecification(
             final Class<?> cls,
-            final NatureOfService natureOfServiceIfAny) {
+            final NatureOfService fallback) {
 
         // ... and create the specs
         if (FreeStandingList.class.isAssignableFrom(cls)) {
-            return new ObjectSpecificationOnStandaloneList(servicesInjector,
-                    facetProcessor);
+            return new ObjectSpecificationOnStandaloneList(servicesInjector, facetProcessor);
         } else {
             final ConfigurationServiceInternal configService = servicesInjector.lookupService(
                     ConfigurationServiceInternal.class);
             final FacetedMethodsBuilderContext facetedMethodsBuilderContext =
                     new FacetedMethodsBuilderContext(
                             this, facetProcessor, layoutMetadataReaders, configService);
+
+            final NatureOfService natureOfServiceIfAny = natureOfServiceFrom(cls, fallback);
+
             return new ObjectSpecificationDefault(cls, facetedMethodsBuilderContext,
                     servicesInjector, facetProcessor, natureOfServiceIfAny);
         }
     }
 
+    private NatureOfService natureOfServiceFrom(
+            final Class<?> type,
+            final NatureOfService fallback) {
+        final DomainService domainServiceIfAny = type.getAnnotation(DomainService.class);
+        return domainServiceIfAny != null ? domainServiceIfAny.nature() : fallback;
+    }
+
     private Class<?> loadBuiltIn(final String className) throws ClassNotFoundException {
         final Class<?> builtIn = ClassUtil.getBuiltIn(className);
         if (builtIn != null) {
diff --git a/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisComponentProvider.java b/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisComponentProvider.java
index 9773fa9..1e69806 100644
--- a/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisComponentProvider.java
+++ b/core/runtime/src/main/java/org/apache/isis/core/runtime/systemusinginstallers/IsisComponentProvider.java
@@ -26,6 +26,7 @@ import java.util.Set;
 
 import javax.annotation.Nullable;
 import javax.jdo.annotations.PersistenceCapable;
+import javax.xml.bind.annotation.XmlElement;
 
 import com.google.common.base.Function;
 import com.google.common.base.Joiner;
@@ -43,6 +44,7 @@ import org.apache.isis.applib.annotation.DomainObject;
 import org.apache.isis.applib.annotation.DomainService;
 import org.apache.isis.applib.annotation.Mixin;
 import org.apache.isis.applib.annotation.Nature;
+import org.apache.isis.applib.annotation.ViewModel;
 import org.apache.isis.applib.fixturescripts.FixtureScript;
 import org.apache.isis.applib.services.classdiscovery.ClassDiscoveryServiceUsingReflections;
 import org.apache.isis.core.commons.config.IsisConfiguration;
@@ -161,6 +163,9 @@ public abstract class IsisComponentProvider {
                 }))
         );
 
+        final Set<Class<?>> viewModelTypes = reflections.getTypesAnnotatedWith(ViewModel.class);
+        final Set<Class<?>> xmlElementTypes = reflections.getTypesAnnotatedWith(XmlElement.class);
+
         // add in any explicitly registered services...
         domainServiceTypes.addAll(appManifest.getAdditionalServices());
 
@@ -182,6 +187,9 @@ public abstract class IsisComponentProvider {
         registry.setPersistenceCapableTypes(within(packagesWithDotSuffix, persistenceCapableTypes));
         registry.setFixtureScriptTypes(within(packagesWithDotSuffix, fixtureScriptTypes));
         registry.setMixinTypes(within(packagesWithDotSuffix, mixinTypes));
+        registry.setDomainObjectTypes(within(packagesWithDotSuffix, domainObjectTypes));
+        registry.setViewModelTypes(within(packagesWithDotSuffix, viewModelTypes));
+        registry.setXmlElementTypes(within(packagesWithDotSuffix, xmlElementTypes));
     }
 
     static <T> Set<Class<? extends T>> within(