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 2017/12/07 15:01:08 UTC

[isis] 12/18: ISIS-1782: generalises Module and introduces AppManifestAbstract2

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

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

commit 94628acc6aed00afc14d2d36c961dd87dafd1d89
Author: Dan Haywood <da...@haywood-associates.co.uk>
AuthorDate: Wed Dec 6 06:25:37 2017 +0000

    ISIS-1782: generalises Module and introduces AppManifestAbstract2
    
    ... so that Module can also provide add configuration properties, and that app manifest can provide transitive list of refdata and teardown fixtures
---
 .../java/org/apache/isis/applib/AppManifest2.java  |  12 +-
 .../apache/isis/applib/AppManifestAbstract.java    |  73 ++++--
 .../apache/isis/applib/AppManifestAbstract2.java   | 121 ++++++++++
 .../org/apache/isis/applib/AppManifestBuilder.java |  52 +++++
 .../apache/isis/applib/{modules => }/Module.java   |   3 +-
 .../org/apache/isis/applib/ModuleAbstract.java     | 252 +++++++++++++++++++++
 .../apache/isis/applib/modules/ModuleAbstract.java | 114 ----------
 .../Module_Util_transitiveDependenciesOf_Test.java |  12 +-
 8 files changed, 500 insertions(+), 139 deletions(-)

diff --git a/example/application/simpleapp/application/src/main/java/domainapp/application/fixture/DomainAppApplicationModuleFixtureSubmodule.java b/core/applib/src/main/java/org/apache/isis/applib/AppManifest2.java
similarity index 78%
rename from example/application/simpleapp/application/src/main/java/domainapp/application/fixture/DomainAppApplicationModuleFixtureSubmodule.java
rename to core/applib/src/main/java/org/apache/isis/applib/AppManifest2.java
index ad6f10e..52154f7 100644
--- a/example/application/simpleapp/application/src/main/java/domainapp/application/fixture/DomainAppApplicationModuleFixtureSubmodule.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/AppManifest2.java
@@ -16,8 +16,14 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package domainapp.application.fixture;
 
-public final class DomainAppApplicationModuleFixtureSubmodule {
-    private DomainAppApplicationModuleFixtureSubmodule(){}
+package org.apache.isis.applib;
+
+import org.apache.isis.applib.fixturescripts.FixtureScript;
+
+public interface AppManifest2 extends AppManifest {
+
+    FixtureScript getTeardownFixture();
+    FixtureScript getRefDataSetupFixture();
+
 }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/AppManifestAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/AppManifestAbstract.java
index 54678a6..f3a49b3 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/AppManifestAbstract.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/AppManifestAbstract.java
@@ -24,9 +24,11 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 
 import org.apache.isis.applib.fixturescripts.FixtureScript;
 
@@ -41,26 +43,48 @@ public abstract class AppManifestAbstract implements AppManifest {
     private final List<Class<? extends FixtureScript>> fixtures;
     private final Map<String, String> configurationProperties;
 
-    public AppManifestAbstract(final Builder builder) {
+    public AppManifestAbstract(final AppManifestBuilder<?> builder) {
 
-        final List<Class<?>> builderModules = builder.modules;
+        final List<Class<?>> builderModules = builder.getAllModulesAsClass();
         overrideModules(builderModules);
         this.modules = builderModules;
 
-        final List<Class<?>> builderAdditionalServices = builder.additionalServices;
+        final List<Class<?>> builderAdditionalServices = Lists.newArrayList(builder.getAllAdditionalServices());
         overrideAdditionalServices(builderAdditionalServices);
 
         this.additionalServices = builderAdditionalServices;
 
+        this.authMechanism = determineAuthMechanism(builder);
+        this.fixtures = determineFixtures(builder);
+
+        // note uses this.fixtures, so must come afterwards...
+        this.configurationProperties = createConfigurationProperties(
+                builder.getAllPropertyResources(), builder.getAllIndividualConfigProps(),
+                this.fixtures);
+    }
+
+    private String determineAuthMechanism(final AppManifestBuilder<?> builder) {
         final String overriddenAuthMechanism = overrideAuthMechanism();
-        this.authMechanism = overriddenAuthMechanism != null ? overriddenAuthMechanism : builder.authMechanism;
+        if (overriddenAuthMechanism != null) {
+            return overriddenAuthMechanism;
+        } else {
+            if(builder instanceof Builder) {
+                return ((Builder) builder).authMechanism;
+            } else {
+                return null;
+            }
+        }
+    }
 
-        final List<Class<? extends FixtureScript>> builderFixtures = builder.fixtures;
+    private List<Class<? extends FixtureScript>> determineFixtures(final AppManifestBuilder<?> builder) {
+        final List<Class<? extends FixtureScript>> builderFixtures;
+        if(builder instanceof Builder) {
+            builderFixtures = ((Builder) builder).fixtures;
+        } else {
+            builderFixtures = Lists.newArrayList();
+        }
         overrideFixtures(builderFixtures);
-        this.fixtures = builderFixtures;
-
-        // note uses this.fixtures, so must come afterwards...
-        this.configurationProperties = createConfigurationProperties(builder.propertyResources, builder.individualConfigProps, this.fixtures);
+        return builderFixtures;
     }
 
     private Map<String, String> createConfigurationProperties(
@@ -174,13 +198,12 @@ public abstract class AppManifestAbstract implements AppManifest {
 
     /**
      * Used to build an {@link AppManifest} either {@link #build() directly}, or implicitly by passing into
-     * {@link AppManifestAbstract}'s {@link AppManifestAbstract#AppManifestAbstract(Builder) constructor}.
+     * {@link AppManifestAbstract}'s {@link AppManifestAbstract#AppManifestAbstract(AppManifestBuilder) constructor}.
      */
-    public static class Builder {
-
+    public static class Builder implements AppManifestBuilder<Builder> {
 
         final List<Class<?>> modules = Lists.newArrayList();
-        List<Class<?>> additionalServices  = Lists.newArrayList();
+        Set<Class<?>> additionalServices = Sets.newLinkedHashSet();
         String authMechanism = "shiro";
         List<Class<? extends FixtureScript>> fixtures = Lists.newArrayList();
 
@@ -189,7 +212,7 @@ public abstract class AppManifestAbstract implements AppManifest {
 
         private Map<String,String> configurationProperties = Maps.newHashMap();
 
-        private Builder() {}
+        Builder() {}
 
         /**
          * Factory method.
@@ -226,7 +249,7 @@ public abstract class AppManifestAbstract implements AppManifest {
             if(additionalServices == null) {
                 throw new IllegalArgumentException("List of additional services must not be null");
             }
-            this.additionalServices = Lists.newArrayList(additionalServices);
+            this.additionalServices = Sets.newLinkedHashSet(additionalServices);
             return this;
         }
 
@@ -269,6 +292,26 @@ public abstract class AppManifestAbstract implements AppManifest {
             return this;
         }
 
+        @Override
+        public List<Class<?>> getAllModulesAsClass() {
+            return modules;
+        }
+
+        @Override
+        public Set<Class<?>> getAllAdditionalServices() {
+            return additionalServices;
+        }
+
+        @Override
+        public List<PropertyResource> getAllPropertyResources() {
+            return propertyResources;
+        }
+
+        @Override
+        public List<ConfigurationProperty> getAllIndividualConfigProps() {
+            return individualConfigProps;
+        }
+
         public AppManifest build() {
             return new AppManifestAbstract(this) {};
         }
diff --git a/core/applib/src/main/java/org/apache/isis/applib/AppManifestAbstract2.java b/core/applib/src/main/java/org/apache/isis/applib/AppManifestAbstract2.java
new file mode 100644
index 0000000..9facefd
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/AppManifestAbstract2.java
@@ -0,0 +1,121 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.isis.applib.annotation.Programmatic;
+import org.apache.isis.applib.fixturescripts.FixtureScript;
+
+/**
+ * Convenience adapter, configured using an {@link Builder}.
+ */
+public abstract class AppManifestAbstract2 extends AppManifestAbstract implements AppManifest2 {
+
+    public static class Builder2 extends Builder {
+
+        private final Module module;
+
+        private Builder2(Module module) {
+            this.module = module;
+
+            final List<Module> transitiveDependencies = Module.Util.transitiveDependenciesOf(module);
+            final Class[] moduleTransitiveDependencies = asClasses(transitiveDependencies);
+
+            final List<Class<?>> additionalModules = Module.Util.transitiveDependenciesAsClassOf(module);
+            final List<Class<?>> additionalServices = Module.Util.transitiveAdditionalServicesOf(module);
+
+            withAdditionalModules(moduleTransitiveDependencies);
+            withAdditionalModules(additionalModules);
+            withAdditionalServices(additionalServices);
+        }
+
+        public static Builder2 forModule(Module module) {
+            return new Builder2(module);
+        }
+
+        private static Class[] asClasses(final List<Module> dependencies) {
+            final List<Class<? extends Module>> list = new ArrayList<>();
+            for (Module dependency : dependencies) {
+                Class<? extends Module> aClass = dependency.getClass();
+                list.add(aClass);
+            }
+            return list.toArray(new Class[] {});
+        }
+
+        @Override
+        public AppManifest build() {
+            return new AppManifestAbstract2(this) {};
+        }
+
+    }
+
+    private final Module module;
+    public AppManifestAbstract2(final Builder builder) {
+        super(builder);
+        if (!(builder instanceof Builder2)) {
+            throw new IllegalArgumentException("Requires an AppManifestAbstract2.Builder2");
+        }
+        Builder2 builder2 = (Builder2) builder;
+        this.module = builder2.module;
+    }
+
+    @Programmatic
+    public Module getModule() {
+        return module;
+    }
+
+    @Programmatic
+    public FixtureScript getRefDataSetupFixture() {
+        return new FixtureScript() {
+            @Override
+            protected void execute(final ExecutionContext executionContext) {
+                List<Module> modules = Module.Util.transitiveDependenciesOf(module);
+                for (Module module : modules) {
+                    FixtureScript fixtureScript = module.getRefDataSetupFixture();
+                    if(fixtureScript != null) {
+                        executionContext.executeChild(this, fixtureScript);
+                    }
+                }
+            }
+        };
+    }
+
+    @Programmatic
+    public FixtureScript getTeardownFixture() {
+        return new FixtureScript() {
+            @Override
+            protected void execute(final ExecutionContext executionContext) {
+                List<Module> modules = Module.Util.transitiveDependenciesOf(module);
+                Collections.reverse(modules);
+                for (Module module : modules) {
+                    final FixtureScript fixtureScript = module.getTeardownFixture();
+                    if(fixtureScript != null) {
+                        executionContext.executeChild(this, fixtureScript);
+                    }
+                }
+            }
+        };
+    }
+
+
+
+}
diff --git a/core/applib/src/main/java/org/apache/isis/applib/AppManifestBuilder.java b/core/applib/src/main/java/org/apache/isis/applib/AppManifestBuilder.java
new file mode 100644
index 0000000..fe1431b
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/AppManifestBuilder.java
@@ -0,0 +1,52 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+interface AppManifestBuilder<T> {
+
+    T withAdditionalModules(final Class<?>... modules);
+
+    T withAdditionalModules(final List<Class<?>> modules);
+
+    T withAdditionalServices(final Class<?>... additionalServices);
+
+    T withAdditionalServices(final List<Class<?>> additionalServices);
+
+    T withConfigurationProperties(final Map<String,String> configurationProperties);
+
+    T withConfigurationPropertiesFile(final String propertiesFile);
+
+    T withConfigurationPropertiesFile(
+            final Class<?> propertiesFileContext, final String propertiesFile, final String... furtherPropertiesFiles);
+
+    T withConfigurationProperty(final String key, final String value);
+
+
+    List<Class<?>> getAllModulesAsClass();
+
+    Set<Class<?>> getAllAdditionalServices();
+
+    List<AppManifestAbstract.PropertyResource> getAllPropertyResources();
+
+    List<AppManifestAbstract.ConfigurationProperty> getAllIndividualConfigProps();
+}
\ No newline at end of file
diff --git a/core/applib/src/main/java/org/apache/isis/applib/modules/Module.java b/core/applib/src/main/java/org/apache/isis/applib/Module.java
similarity index 98%
rename from core/applib/src/main/java/org/apache/isis/applib/modules/Module.java
rename to core/applib/src/main/java/org/apache/isis/applib/Module.java
index 122346f..ce3542b 100644
--- a/core/applib/src/main/java/org/apache/isis/applib/modules/Module.java
+++ b/core/applib/src/main/java/org/apache/isis/applib/Module.java
@@ -16,7 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-package org.apache.isis.applib.modules;
+package org.apache.isis.applib;
 
 import java.util.ArrayList;
 import java.util.LinkedHashSet;
@@ -26,7 +26,6 @@ import java.util.Set;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 
-import org.apache.isis.applib.AppManifestAbstract;
 import org.apache.isis.applib.fixturescripts.FixtureScript;
 
 public interface Module {
diff --git a/core/applib/src/main/java/org/apache/isis/applib/ModuleAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/ModuleAbstract.java
new file mode 100644
index 0000000..eaa9911
--- /dev/null
+++ b/core/applib/src/main/java/org/apache/isis/applib/ModuleAbstract.java
@@ -0,0 +1,252 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.isis.applib;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+import org.apache.isis.applib.fixturescripts.FixtureScript;
+
+public abstract class ModuleAbstract implements Module, AppManifestBuilder<ModuleAbstract> {
+
+
+    /**
+     * As per Maven's &lt;dependencies&gt;&lt;/dependencies&gt; element; in the future might be derived (code generated?) from java 9's <code>module-info.java</code> metadata
+     *
+     * <p>
+     *     We use Set (rather than List) because we rely on {@link Module} being a value type based solely on its
+     *     class.  What this means is that each module can simply instantiate its dependencies, and the framework will
+     *     be able to eliminate duplicates.
+     * </p>
+     */
+    @Override
+    @XmlTransient
+    public Set<Module> getDependencies() {
+        return Collections.emptySet();
+    }
+
+    /**
+     * Support for "legacy" modules that do not implement {@link Module}.
+     */
+    @Override
+    @XmlTransient
+    public Set<Class<?>> getDependenciesAsClass() {
+        return modules;
+    }
+
+    @Override
+    @XmlTransient
+    public FixtureScript getRefDataSetupFixture() {
+        return null;
+    }
+
+    @Override
+    @XmlTransient
+    public FixtureScript getTeardownFixture() {
+        return null;
+    }
+
+
+    @Override
+    @XmlTransient
+    public Set<Class<?>> getAdditionalServices() {
+        return additionalServices;
+    }
+
+
+    @XmlAttribute(required = true)
+    public String getName() {
+        return getClass().getSimpleName();
+    }
+
+    private String getFullName() {
+        return getClass().getName();
+    }
+
+
+    @XmlElement(name = "module", required = true)
+    private Set<ModuleAbstract> getModuleDependencies() {
+        return (Set) getDependencies();
+    }
+
+
+
+
+    private final Set<Class<?>> modules = Sets.newLinkedHashSet();
+    private final Set<Class<?>> additionalServices  = Sets.newLinkedHashSet();
+
+    private final List<AppManifestAbstract.ConfigurationProperty> individualConfigProps = Lists.newArrayList();
+    private final List<AppManifestAbstract.PropertyResource> propertyResources = Lists.newArrayList();
+
+    private Map<String,String> configurationProperties = Maps.newHashMap();
+
+    public ModuleAbstract withAdditionalModules(final Class<?>... modules) {
+        return withAdditionalModules(Arrays.asList(modules));
+    }
+
+    public ModuleAbstract withAdditionalModules(final List<Class<?>> modules) {
+        if(modules == null) {
+            throw new IllegalArgumentException("List of modules must not be null");
+        }
+        this.modules.addAll(modules);
+        return this;
+    }
+
+    public ModuleAbstract withAdditionalServices(final Class<?>... additionalServices) {
+        return withAdditionalServices(Arrays.asList(additionalServices));
+    }
+
+    public ModuleAbstract withAdditionalServices(final List<Class<?>> additionalServices) {
+        if(additionalServices == null) {
+            throw new IllegalArgumentException("List of additional services must not be null");
+        }
+        this.additionalServices.addAll(additionalServices);
+        return this;
+    }
+
+    public ModuleAbstract withConfigurationProperties(final Map<String,String> configurationProperties) {
+        this.configurationProperties.putAll(configurationProperties);
+        return this;
+    }
+
+    public ModuleAbstract withConfigurationPropertiesFile(final String propertiesFile) {
+        return withConfigurationPropertiesFile(getClass(), propertiesFile);
+    }
+
+    public ModuleAbstract withConfigurationPropertiesFile(
+            final Class<?> propertiesFileContext, final String propertiesFile, final String... furtherPropertiesFiles) {
+        addPropertyResource(propertiesFileContext, propertiesFile);
+        for (final String otherFile : furtherPropertiesFiles) {
+            addPropertyResource(propertiesFileContext, otherFile);
+        }
+        return this;
+    }
+
+    private void addPropertyResource(final Class<?> propertiesFileContext, final String propertiesFile) {
+        propertyResources.add(new AppManifestAbstract.PropertyResource(propertiesFileContext, propertiesFile));
+    }
+
+    public ModuleAbstract withConfigurationProperty(final String key, final String value) {
+        individualConfigProps.add(new AppManifestAbstract.ConfigurationProperty(key,value));
+        return this;
+    }
+
+
+    @XmlTransient
+    @Override
+    public List<Class<?>> getAllModulesAsClass() {
+
+        final List<Class<?>> modules = Lists.newArrayList();
+
+        final List<Module> transitiveDependencies = Module.Util.transitiveDependenciesOf(this);
+        final List<Class<? extends Module>> moduleTransitiveDependencies = asClasses(transitiveDependencies);
+        modules.addAll(moduleTransitiveDependencies);
+
+        final List<Class<?>> additionalModules = Module.Util.transitiveDependenciesAsClassOf(this);
+        modules.addAll(additionalModules);
+
+        return modules;
+    }
+
+
+    private static List<Class<? extends Module>> asClasses(final List<Module> dependencies) {
+        final List<Class<? extends Module>> list = new ArrayList<>();
+        for (Module dependency : dependencies) {
+            Class<? extends Module> aClass = dependency.getClass();
+            list.add(aClass);
+        }
+        return list;
+    }
+
+    @Override
+    @XmlTransient
+    public final Set<Class<?>> getAllAdditionalServices() {
+        final List<Class<?>> additionalServices = Module.Util.transitiveAdditionalServicesOf(this);
+        return Sets.newLinkedHashSet(additionalServices);
+    }
+
+    @XmlTransient
+    @Override
+    public final List<AppManifestAbstract.PropertyResource> getAllPropertyResources() {
+
+        List<AppManifestAbstract.PropertyResource> transitivePropertyResources = Lists.newArrayList();
+
+        final List<Module> transitiveDependencies = Module.Util.transitiveDependenciesOf(this);
+        for (Module transitiveDependency : transitiveDependencies) {
+            if(transitiveDependency instanceof ModuleAbstract) {
+                ModuleAbstract moduleAbstract = (ModuleAbstract) transitiveDependency;
+                transitivePropertyResources.addAll(moduleAbstract.propertyResources);
+            }
+        }
+
+        return transitivePropertyResources;
+    }
+
+    @XmlTransient
+    @Override
+    public List<AppManifestAbstract.ConfigurationProperty> getAllIndividualConfigProps() {
+        List<AppManifestAbstract.ConfigurationProperty> transitiveIndividualConfigProps = Lists.newArrayList();
+
+        final List<Module> transitiveDependencies = Module.Util.transitiveDependenciesOf(this);
+        for (Module transitiveDependency : transitiveDependencies) {
+            if(transitiveDependency instanceof ModuleAbstract) {
+                ModuleAbstract moduleAbstract = (ModuleAbstract) transitiveDependency;
+                transitiveIndividualConfigProps.addAll(moduleAbstract.individualConfigProps);
+            }
+        }
+        return transitiveIndividualConfigProps;
+    }
+
+
+
+
+    @Override
+    public String toString() {
+        return getFullName();
+    }
+
+    public boolean equals(final Object o) {
+        if (o == this) {
+            return true;
+        }
+        if (!(o instanceof ModuleAbstract)) {
+            return false;
+        }
+        final ModuleAbstract other = (ModuleAbstract) o;
+        return Objects.equals(getFullName(), other.getFullName());
+    }
+
+    public int hashCode() {
+        return getFullName().hashCode();
+    }
+
+}
\ No newline at end of file
diff --git a/core/applib/src/main/java/org/apache/isis/applib/modules/ModuleAbstract.java b/core/applib/src/main/java/org/apache/isis/applib/modules/ModuleAbstract.java
deleted file mode 100644
index 2f2405a..0000000
--- a/core/applib/src/main/java/org/apache/isis/applib/modules/ModuleAbstract.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.isis.applib.modules;
-
-import java.util.Collections;
-import java.util.Objects;
-import java.util.Set;
-
-import javax.xml.bind.annotation.XmlAttribute;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlTransient;
-
-import org.apache.isis.applib.fixturescripts.FixtureScript;
-
-public abstract class ModuleAbstract implements Module {
-
-
-    /**
-     * As per Maven's &lt;dependencies&gt;&lt;/dependencies&gt; element; in the future might be derived (code generated?) from java 9's <code>module-info.java</code> metadata
-     *
-     * <p>
-     *     We use Set (rather than List) because we rely on {@link Module} being a value type based solely on its
-     *     class.  What this means is that each module can simply instantiate its dependencies, and the framework will
-     *     be able to eliminate duplicates.
-     * </p>
-     */
-    @Override
-    @XmlTransient
-    public Set<Module> getDependencies() {
-        return Collections.emptySet();
-    }
-
-    /**
-     * Support for "legacy" modules that do not implement {@link Module}.
-     */
-    @Override
-    @XmlTransient
-    public Set<Class<?>> getDependenciesAsClass() {
-        return Collections.emptySet();
-    }
-
-    @Override
-    @XmlTransient
-    public FixtureScript getRefDataSetupFixture() {
-        return null;
-    }
-
-    @Override
-    @XmlTransient
-    public FixtureScript getTeardownFixture() {
-        return null;
-    }
-
-    @Override
-    @XmlTransient
-    public Set<Class<?>> getAdditionalServices() {
-        return Collections.emptySet();
-    }
-
-
-
-
-    @XmlAttribute(required = true)
-    public String getName() {
-        return getClass().getSimpleName();
-    }
-
-    private String getFullName() {
-        return getClass().getName();
-    }
-
-
-    @XmlElement(name = "module", required = true)
-    private Set<ModuleAbstract> getModuleDependencies() {
-        return (Set) getDependencies();
-    }
-
-    @Override
-    public String toString() {
-        return getFullName();
-    }
-
-    public boolean equals(final Object o) {
-        if (o == this) {
-            return true;
-        }
-        if (!(o instanceof ModuleAbstract)) {
-            return false;
-        }
-        final ModuleAbstract other = (ModuleAbstract) o;
-        return Objects.equals(getFullName(), other.getFullName());
-    }
-
-    public int hashCode() {
-        return getFullName().hashCode();
-    }
-
-}
\ No newline at end of file
diff --git a/core/applib/src/test/java/org/apache/isis/applib/modules/Module_Util_transitiveDependenciesOf_Test.java b/core/applib/src/test/java/org/apache/isis/applib/modules/Module_Util_transitiveDependenciesOf_Test.java
index 5394cff..ce0bf06 100644
--- a/core/applib/src/test/java/org/apache/isis/applib/modules/Module_Util_transitiveDependenciesOf_Test.java
+++ b/core/applib/src/test/java/org/apache/isis/applib/modules/Module_Util_transitiveDependenciesOf_Test.java
@@ -12,6 +12,9 @@ import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
 
+import org.apache.isis.applib.Module;
+import org.apache.isis.applib.ModuleAbstract;
+
 import static org.junit.Assert.assertTrue;
 
 public class Module_Util_transitiveDependenciesOf_Test {
@@ -40,8 +43,8 @@ public class Module_Util_transitiveDependenciesOf_Test {
 
     final Module moduleF = new ModuleImpl("F");
     final Module moduleE = new ModuleImpl("E") {
-        @Override public Set<Class<?>> getAdditionalServices() {
-            return Sets.<Class<?>>newHashSet(ServiceX.class);
+        {
+            withAdditionalServices(ServiceX.class);
         }
         @Override
         public Set<Class<?>> getDependenciesAsClass() {
@@ -62,9 +65,8 @@ public class Module_Util_transitiveDependenciesOf_Test {
         public Set<Class<?>> getDependenciesAsClass() {
             return Sets.newHashSet(ModuleQ.class, ModuleR.class);
         }
-        @Override
-        public Set<Class<?>> getAdditionalServices() {
-            return Sets.newHashSet(ServiceY.class, ServiceZ.class);
+        {
+            withAdditionalServices(ServiceY.class, ServiceZ.class);
         }
     };
     final Module moduleB = new ModuleImpl("B") {

-- 
To stop receiving notification emails like this one, please contact
"commits@isis.apache.org" <co...@isis.apache.org>.