New way to structure the bootstrap code, to make it easier than the low-level 
primitives that are required under the hood. It betters suits the mental model, 
rather than the internal programming model.


Project: http://git-wip-us.apache.org/repos/asf/zest-qi4j/repo
Commit: http://git-wip-us.apache.org/repos/asf/zest-qi4j/commit/b86b66d4
Tree: http://git-wip-us.apache.org/repos/asf/zest-qi4j/tree/b86b66d4
Diff: http://git-wip-us.apache.org/repos/asf/zest-qi4j/diff/b86b66d4

Branch: refs/heads/develop
Commit: b86b66d4ec80e51dceb0f608082a5b0b4062d16c
Parents: 454154e
Author: Niclas Hedhman <[email protected]>
Authored: Wed Jun 17 10:39:36 2015 +0800
Committer: Niclas Hedhman <[email protected]>
Committed: Wed Jun 17 10:39:36 2015 +0800

----------------------------------------------------------------------
 core/bootstrap/src/docs/bootstrap.txt           |  86 +++++++--
 .../bootstrap/builder/ApplicationBuilder.java   |  19 +-
 .../qi4j/bootstrap/layered/LayerAssembler.java  |  10 +
 .../layered/LayeredApplicationAssembler.java    | 189 +++++++++++++++++++
 .../layered/LayeredLayerAssembler.java          |  62 ++++++
 .../qi4j/bootstrap/layered/ModuleAssembler.java |  11 ++
 .../LayeredApplicationAssemblerTest.java        |  23 +++
 .../bootstrap/assembly/TestApplication.java     |  43 +++++
 .../assembly/config/ConfigurationLayer.java     |  15 ++
 .../connectivity/ConnectivityLayer.java         |  17 ++
 .../bootstrap/assembly/domain/DomainLayer.java  |  17 ++
 .../assembly/domain/InvoicingModule.java        |  17 ++
 .../bootstrap/assembly/domain/OrderModule.java  |  38 ++++
 .../assembly/infrastructure/IndexingModule.java |  26 +++
 .../infrastructure/InfrastructureLayer.java     |  29 +++
 .../infrastructure/SerializationModule.java     |  18 ++
 .../assembly/infrastructure/StorageModule.java  |  26 +++
 .../assembly/service/ServiceLayer.java          |  17 ++
 18 files changed, 647 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/docs/bootstrap.txt
----------------------------------------------------------------------
diff --git a/core/bootstrap/src/docs/bootstrap.txt 
b/core/bootstrap/src/docs/bootstrap.txt
index 80da48e..22165c9 100644
--- a/core/bootstrap/src/docs/bootstrap.txt
+++ b/core/bootstrap/src/docs/bootstrap.txt
@@ -30,7 +30,8 @@ to a module and visibility rules define default behaviors, 
enforcement of archit
 The _assembly_ is preceeded by the creation of the _Qi4j Runtime_. The 
_assembly_ can be declared fully by defining
 all modules and layers, and how the layers are sitting on top of each other, 
OR one can utilize one of the two
 convenience assemblies, one for a _pancake_ pattern, where all layers are top 
on each other, or one with a single module
-in a single layer, useful for small applications, spikes and tests.
+in a single layer, useful for small applications, spikes and tests. The 
+bootstrap+ system has several ways to acheive
+this, and they are listed below in <<core-bootstrap-assembly-layered>>.
 
 During _assembly_, the application (JVM level) architecture and the 
application model is defined. You define which
 layers exist and how they relate to each other. For each layer, you define 
which modules it contains. And for each
@@ -125,15 +126,6 @@ tag=properties-defaults
 == Setting meta information on assembled types ==
 
 
-== Facilities ==
-
-=== Assembly Specifications ===
-
-=== Class Scanner ===
-
-=== Application Builder ===
-
-
 == Using Assemblers ==
 Many <<libraries,libraries>> and <<extensions,extensions>> provides a 
cookie-cutter _Assembler_, to simplify the set up
 of such component. Often these are suitable, but sometimes they won't fit the 
application in hand, in which case the
@@ -173,6 +165,44 @@ tag=UsingAssembler
 --------------
 
 
+[[core-bootstrap-assembly-layered,Layered Application Assembler]]
+== Layered Application Assembler (RECOMMENDED!) ==
+
+In 2.1, a new way to instantiate Qi4j applications was introduced. It starts 
with subclassing the
++LayeredApplicationAssembler+, and implementing the +assembleLayers()+ method.
+
+In the +assembleLayers()+ method, one is epected to either call the 
+createLayer()+ method in the super class
+with the Class of the LayerAssembler,
+
+[source,java]
+----
+    LayerAssembly domainLayer = createLayer( DomainLayer.class );
+----
+
+OR manually instantiate and call the LayerAssembler.
+
+[source,java]
+----
+    LayerAssembly infraLayer = new InfrastructureLayer( configModule 
).assemble( assembly.layer( InfrastructureLayer.NAME  ));
+----
+
+This is to make the normal case as simple as possible, yet allow the special 
needs that occssionally surfaces.
+
+Each LayerAssembler implementation may optionally extend the 
+LayeredLayerAssembler+, to get access to the
++createModule()+ method, which again simplifies the creation of modules in the 
+assemble()+ method.
+
+[source,java]
+----
+    createModule( layer, InvoicingModule.class );
+----
+
++ModuleAssembler+ implementations typically use +Assembler+ classes to put 
together, or call the +entities()+,
++values()+ methods described elsewhere on this page. There is no superclass to 
use.
+
++ModuleAssembler+ implementations should have a name ending with "Module" and 
the naming will insert a human-readable
+space within the module name, e.g. +InvoicingModule+ will be named "Invoicing 
Module".
+
+For example code, see the tutorial <<howto-assemble-application>>.
 
 
 == Singleton Assembler ==
@@ -193,7 +223,39 @@ Once the SingletonAssembler constructor returns, the Qi4j 
application is up and
 The SingletonAssembler also makes common system resources available from the 
bootstrap code, such as
 Module, UnitOfWorkFactory and others. This is possible since there is only one 
Module.
 
-
+== Application Builder ==
+Some applications has no need for runtime determination of the exact 
application structure, and no need for
+advanced alterations to a staright-forward layered application structure. By 
using the +ApplicationBuilder+
+it is possible to define the application structure from a JSON document, AND 
call the provided +main()+ class,
+taking the JSON document as input on +System.in+.
+
+The format of the JSON document, directly reflects the application structure, 
such as
+[source,json]
+----
+{
+    "name": "Build from JSON test.",
+    "layers": [
+        { "name": "service", "uses": [ "domain", "config"] },
+        { "name": "donfig" },
+        {
+            "name": "domain",
+            "modules" : [
+                {
+                    "name" : "Invoicing",
+                    "assemblers" : [
+                        "org.hedhman.niclas.bootstrap.InvoicingAssembler"
+                    ]
+                }
+            ]
+        }
+    ]
+}
+----
+
+At the moment, the JSON format only support +Assembler+ classes to do the work.
+
+Another way to use the +ApplicationBuilder+ is to subclass it, optionally use 
the +configureFromJSON()+ method,
+and then programmatically enhance the structure before calling 
+newApplication()+.
 
 == Pancake Assembly ==
 There is one case that stands out as a common case, and forms a reasonable 
middle-ground. It is where each layer sits
@@ -210,8 +272,6 @@ 
source=core/bootstrap/src/test/java/org/qi4j/bootstrap/DocumentationSupport.java
 tag=pancake
 --------------
 
-
-
 == Full Assembly ==
 Full Assembly means that you have the opportunity to create any layer/module 
hierarchy that are within the rules of the
 Qi4j runtime. It requires more support in your code to be useful, and the 
example below is by no means a recommended way

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/ApplicationBuilder.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/ApplicationBuilder.java
 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/ApplicationBuilder.java
index c008e5f..d68a3d5 100644
--- 
a/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/ApplicationBuilder.java
+++ 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/builder/ApplicationBuilder.java
@@ -180,6 +180,19 @@ public class ApplicationBuilder
     {
         String applicationName = root.getString( "name" );
         ApplicationBuilder builder = new ApplicationBuilder( applicationName );
+        builder.configureWithJson( root );
+        return builder;
+    }
+
+    /** Configures the application struucture from a JSON document.
+     *
+     * @param root The JSON document root.
+     * @throws JSONException if the JSON document isn't valid.
+     * @throws AssemblyException if probelms in the Assemblers provided in the 
JSON document.
+     */
+    protected void configureWithJson( JSONObject root )
+        throws JSONException, AssemblyException
+    {
         JSONArray layers = root.optJSONArray( "layers" );
         if( layers != null )
         {
@@ -187,7 +200,7 @@ public class ApplicationBuilder
             {
                 JSONObject layerObject = layers.getJSONObject( i );
                 String layerName = layerObject.getString( "name" );
-                LayerDeclaration layerDeclaration = builder.withLayer( 
layerName );
+                LayerDeclaration layerDeclaration = withLayer( layerName );
                 JSONArray using = layerObject.optJSONArray( "uses" );
                 if( using != null )
                 {
@@ -209,14 +222,14 @@ public class ApplicationBuilder
                         {
                             for( int m = 0; m < assemblers.length(); m++ )
                             {
-                                moduleDeclaration.withAssembler( 
assemblers.getString( m ) );
+                                String string = assemblers.getString( m );
+                                moduleDeclaration.withAssembler( string );
                             }
                         }
                     }
                 }
             }
         }
-        return builder;
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayerAssembler.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayerAssembler.java 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayerAssembler.java
new file mode 100644
index 0000000..b922b98
--- /dev/null
+++ 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayerAssembler.java
@@ -0,0 +1,10 @@
+package org.qi4j.bootstrap.layered;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+
+public interface LayerAssembler
+{
+    LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException;
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredApplicationAssembler.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredApplicationAssembler.java
 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredApplicationAssembler.java
new file mode 100644
index 0000000..7eb00d5
--- /dev/null
+++ 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredApplicationAssembler.java
@@ -0,0 +1,189 @@
+package org.qi4j.bootstrap.layered;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import org.qi4j.api.activation.ActivationException;
+import org.qi4j.api.activation.PassivationException;
+import org.qi4j.api.structure.Application;
+import org.qi4j.api.structure.ApplicationDescriptor;
+import org.qi4j.bootstrap.ApplicationAssembler;
+import org.qi4j.bootstrap.ApplicationAssembly;
+import org.qi4j.bootstrap.ApplicationAssemblyFactory;
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.Energy4Java;
+import org.qi4j.bootstrap.LayerAssembly;
+
+public abstract class LayeredApplicationAssembler
+    implements ApplicationAssembler
+{
+    protected Application application;
+    protected String name;
+    protected String version;
+    private final Application.Mode mode;
+    private ApplicationAssembly assembly;
+
+    private HashMap<Class<? extends LayerAssembler>, LayerAssembler> 
assemblers = new HashMap<>();
+
+    public LayeredApplicationAssembler( String name, String version, 
Application.Mode mode )
+        throws AssemblyException
+    {
+        this.name = name;
+        this.version = version;
+        this.mode = mode;
+        Energy4Java qi4j = new Energy4Java();
+        ApplicationDescriptor model = qi4j.newApplicationModel( this );
+        onModelCreated( model );
+        instantiateApplication( qi4j, model );
+    }
+
+    /**
+     * This method is called from the constructor to instantiate the Qi4j 
application from the application model.
+     *
+     * <p>
+     * The default implementation simply calls;
+     * <pre><code>
+     *   application = model.newInstance( qi4j.spi() );
+     * </code></pre>
+     * </p>
+     *
+     * @param qi4j  The Qi4j runtime engine.
+     * @param model The application model descriptor.
+     */
+    protected void instantiateApplication( Energy4Java qi4j, 
ApplicationDescriptor model )
+    {
+        application = model.newInstance( qi4j.spi() );
+    }
+
+    /**
+     * This method is called after the Application Model has been created, 
before the instantiation of the Qi4j
+     * application.
+     *
+     * <p>
+     * The default implementation does nothing. Applications may have advanced 
features to inspect or
+     * modify the model prior to instantiation, and this is the place where 
such advanced manipulation is
+     * expected to take place.
+     * </p>
+     *
+     * @param model
+     */
+    protected void onModelCreated( ApplicationDescriptor model )
+    {
+    }
+
+    public Application application()
+    {
+        return application;
+    }
+
+    public void start()
+        throws ActivationException
+    {
+        application.activate();
+    }
+
+    public void stop()
+        throws PassivationException
+    {
+        application.passivate();
+    }
+
+    @Override
+    public ApplicationAssembly assemble( ApplicationAssemblyFactory 
applicationFactory )
+        throws AssemblyException
+    {
+        assembly = applicationFactory.newApplicationAssembly();
+        assembly.setName( name );
+        assembly.setVersion( version );
+        assembly.setMode( mode );
+        assembleLayers( assembly );
+        return assembly;
+    }
+
+    protected LayerAssembly createLayer( Class<? extends LayerAssembler> 
layerAssemblerClass )
+        throws IllegalArgumentException
+    {
+        try
+        {
+            String classname = layerAssemblerClass.getSimpleName();
+            if( classname.endsWith( "Layer" ) )
+            {
+                classname = classname.substring( 0, classname.length() - 5 ) + 
" Layer";
+            }
+            setNameIfPresent( layerAssemblerClass, classname );
+            LayerAssembly layer = assembly.layer( classname );
+
+            LayerAssembler layerAssembler = instantiateAssembler( 
layerAssemblerClass, layer );
+            assemblers.put( layerAssemblerClass, layerAssembler );
+            LayerAssembly assembly = layerAssembler.assemble( layer );
+            if( assembly == null )
+            {
+                // Assume that people forgot, and let's not require a "return 
layer", since we can do that ourselves.
+                return layer;
+            }
+            return assembly;
+        }
+        catch( Exception e )
+        {
+            throw new IllegalArgumentException( "Unable to instantiate layer 
with " + layerAssemblerClass.getSimpleName(), e );
+        }
+    }
+
+    private LayerAssembler instantiateAssembler( Class<? extends 
LayerAssembler> layerAssemblerClass,
+                                                 LayerAssembly layer
+    )
+        throws InstantiationException, IllegalAccessException, 
java.lang.reflect.InvocationTargetException
+    {
+        LayerAssembler layerAssembler;
+        try
+        {
+            Constructor<? extends LayerAssembler> assemblyConstructor = 
layerAssemblerClass.getConstructor( LayerAssembly.class );
+            layerAssembler = assemblyConstructor.newInstance( layer );
+        }
+        catch( NoSuchMethodException e )
+        {
+            // Use default constructor then.
+            layerAssembler = layerAssemblerClass.newInstance();
+        }
+        return layerAssembler;
+    }
+
+    static void setNameIfPresent( Class<?> clazz, String classname )
+        throws IllegalAccessException
+    {
+        try
+        {
+            Field field = clazz.getDeclaredField( "NAME" );
+            if( Modifier.isStatic( field.getModifiers() ) )
+            {
+                field.setAccessible( true );
+                field.set( null, classname );
+            }
+        }
+        catch( Exception e )
+        {
+            // Ignore and consider normal.
+        }
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected <T extends LayerAssembler> T assemblerOf( Class<T> 
layerAssemblerClass )
+    {
+        return (T) assemblers.get( layerAssemblerClass );
+    }
+
+    /**
+     * Called from the constructor to assemble the layers in the applcation.
+     *
+     * <p>
+     * This method must be implemented, and is typically a list of 
LayerAssmebler instantitations, followed
+     * by {@link LayerAssembly#uses(LayerAssembly...)} declarations.
+     * <pre><code>
+     *
+     * </code></pre>
+     * </p>
+     */
+    protected abstract void assembleLayers( ApplicationAssembly assembly )
+        throws AssemblyException;
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredLayerAssembler.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredLayerAssembler.java
 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredLayerAssembler.java
new file mode 100644
index 0000000..91ca286
--- /dev/null
+++ 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/LayeredLayerAssembler.java
@@ -0,0 +1,62 @@
+package org.qi4j.bootstrap.layered;
+
+import java.lang.reflect.Constructor;
+import java.util.HashMap;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+
+public abstract class LayeredLayerAssembler
+    implements LayerAssembler
+{
+    private HashMap<Class<? extends ModuleAssembler>, ModuleAssembler> 
assemblers = new HashMap<>();
+
+    protected ModuleAssembly createModule( LayerAssembly layer, Class<? 
extends ModuleAssembler> modulerAssemblerClass )
+    {
+        try
+        {
+            ModuleAssembler moduleAssembler = instantiateAssembler( layer, 
modulerAssemblerClass );
+            String classname = modulerAssemblerClass.getSimpleName();
+            if( classname.endsWith( "Module" ) )
+            {
+                classname = classname.substring( 0, classname.length() - 6 ) + 
" Module";
+            }
+            LayeredApplicationAssembler.setNameIfPresent( 
modulerAssemblerClass, classname );
+            ModuleAssembly module = layer.module( classname );
+            assemblers.put( modulerAssemblerClass, moduleAssembler );
+            ModuleAssembly assembly = moduleAssembler.assemble( layer, module 
);
+            if( assembly == null )
+            {
+                return module;
+            }
+            return assembly;
+        }
+        catch( Exception e )
+        {
+            throw new IllegalArgumentException( "Unable to instantiate module 
with " + modulerAssemblerClass.getSimpleName(), e );
+        }
+    }
+
+    private ModuleAssembler instantiateAssembler( LayerAssembly layer,
+                                                  Class<? extends 
ModuleAssembler> modulerAssemblerClass
+    )
+        throws InstantiationException, IllegalAccessException, 
java.lang.reflect.InvocationTargetException
+    {
+        ModuleAssembler moduleAssembler;
+        try
+        {
+            Constructor<? extends ModuleAssembler> assemblyConstructor = 
modulerAssemblerClass.getConstructor( ModuleAssembly.class );
+            moduleAssembler = assemblyConstructor.newInstance( layer );
+        }
+        catch( NoSuchMethodException e )
+        {
+            moduleAssembler = modulerAssemblerClass.newInstance();
+        }
+        return moduleAssembler;
+    }
+
+    @SuppressWarnings( "unchecked" )
+    protected <T extends ModuleAssembler> T assemblerOf( Class<T> 
moduleAssemblerType )
+    {
+        return (T) assemblers.get( moduleAssemblerType );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/ModuleAssembler.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/ModuleAssembler.java 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/ModuleAssembler.java
new file mode 100644
index 0000000..d09bac5
--- /dev/null
+++ 
b/core/bootstrap/src/main/java/org/qi4j/bootstrap/layered/ModuleAssembler.java
@@ -0,0 +1,11 @@
+package org.qi4j.bootstrap.layered;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+
+public interface ModuleAssembler
+{
+    ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module )
+        throws AssemblyException;
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/LayeredApplicationAssemblerTest.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/LayeredApplicationAssemblerTest.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/LayeredApplicationAssemblerTest.java
new file mode 100644
index 0000000..c63a3bd
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/LayeredApplicationAssemblerTest.java
@@ -0,0 +1,23 @@
+package org.qi4j.bootstrap.assembly;
+
+import org.junit.Test;
+import org.qi4j.api.activation.ActivationException;
+import org.qi4j.api.structure.Application;
+import org.qi4j.bootstrap.AssemblyException;
+
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class LayeredApplicationAssemblerTest
+{
+    @Test
+    public void validateThatAssemblerCreatesApplication()
+        throws AssemblyException, ActivationException
+    {
+        TestApplication assembler = new TestApplication( "Test Application", 
"1.0.1", Application.Mode.test );
+        assembler.start();
+
+        assertThat( assembler.application().name(), equalTo("Test 
Application") );
+        assertThat( assembler.application().version(), equalTo("1.0.1") );
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/TestApplication.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/TestApplication.java 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/TestApplication.java
new file mode 100644
index 0000000..4f44c7f
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/TestApplication.java
@@ -0,0 +1,43 @@
+package org.qi4j.bootstrap.assembly;
+
+import org.qi4j.api.structure.Application;
+import org.qi4j.bootstrap.ApplicationAssembly;
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.layered.LayeredApplicationAssembler;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+import org.qi4j.bootstrap.assembly.config.ConfigurationLayer;
+import org.qi4j.bootstrap.assembly.connectivity.ConnectivityLayer;
+import org.qi4j.bootstrap.assembly.domain.DomainLayer;
+import org.qi4j.bootstrap.assembly.infrastructure.InfrastructureLayer;
+import org.qi4j.bootstrap.assembly.service.ServiceLayer;
+
+// START SNIPPET: application
+public class TestApplication extends LayeredApplicationAssembler
+{
+
+    public TestApplication( String name, String version, Application.Mode mode 
)
+        throws AssemblyException
+    {
+        super( name, version, mode );
+    }
+
+    @Override
+    protected void assembleLayers( ApplicationAssembly assembly )
+        throws AssemblyException
+    {
+        LayerAssembly configLayer = createLayer( ConfigurationLayer.class );
+        ModuleAssembly configModule = configLayer.module( "Configuration 
Module" );
+        LayerAssembly infraLayer = new InfrastructureLayer( configModule 
).assemble( assembly.layer( InfrastructureLayer.NAME  ));
+        LayerAssembly domainLayer = createLayer( DomainLayer.class );
+        LayerAssembly serviceLayer = createLayer( ServiceLayer.class );
+        LayerAssembly connectivityLayer = createLayer( ConnectivityLayer.class 
);
+
+        connectivityLayer.uses( serviceLayer );
+        connectivityLayer.uses( domainLayer );
+        serviceLayer.uses( domainLayer );
+        domainLayer.uses( infraLayer );
+        infraLayer.uses( configLayer );
+    }
+}
+// END SNIPPET: application

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/config/ConfigurationLayer.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/config/ConfigurationLayer.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/config/ConfigurationLayer.java
new file mode 100644
index 0000000..419a789
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/config/ConfigurationLayer.java
@@ -0,0 +1,15 @@
+package org.qi4j.bootstrap.assembly.config;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.layered.LayerAssembler;
+import org.qi4j.bootstrap.LayerAssembly;
+
+public class ConfigurationLayer implements LayerAssembler
+{
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        return layer;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/connectivity/ConnectivityLayer.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/connectivity/ConnectivityLayer.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/connectivity/ConnectivityLayer.java
new file mode 100644
index 0000000..5631a68
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/connectivity/ConnectivityLayer.java
@@ -0,0 +1,17 @@
+package org.qi4j.bootstrap.assembly.connectivity;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.layered.LayerAssembler;
+import org.qi4j.bootstrap.LayerAssembly;
+
+public class ConnectivityLayer implements LayerAssembler
+{
+    public static final String NAME = "Connectivity";
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/DomainLayer.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/DomainLayer.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/DomainLayer.java
new file mode 100644
index 0000000..ea7a12f
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/DomainLayer.java
@@ -0,0 +1,17 @@
+package org.qi4j.bootstrap.assembly.domain;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.layered.LayeredLayerAssembler;
+
+public class DomainLayer extends LayeredLayerAssembler
+{
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        createModule( layer, InvoicingModule.class );
+        createModule( layer, OrderModule.class );
+        return layer;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/InvoicingModule.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/InvoicingModule.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/InvoicingModule.java
new file mode 100644
index 0000000..0a654b5
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/InvoicingModule.java
@@ -0,0 +1,17 @@
+package org.qi4j.bootstrap.assembly.domain;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+import org.qi4j.bootstrap.layered.ModuleAssembler;
+
+public class InvoicingModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module 
)
+        throws AssemblyException
+    {
+        return module;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/OrderModule.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/OrderModule.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/OrderModule.java
new file mode 100644
index 0000000..b721332
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/domain/OrderModule.java
@@ -0,0 +1,38 @@
+package org.qi4j.bootstrap.assembly.domain;
+
+import org.qi4j.api.association.Association;
+import org.qi4j.api.property.Property;
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+import org.qi4j.bootstrap.layered.ModuleAssembler;
+
+public class OrderModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module 
)
+        throws AssemblyException
+    {
+        module.entities( Order.class, Customer.class );
+        module.values( Address.class );
+        return module;
+    }
+
+    public interface Order
+    {
+        Association<Customer> customer();
+
+        Property<Address> invoicingAddress();
+
+        Property<Address> deliveryAddress();
+    }
+
+    public interface Customer
+    {
+    }
+
+    public interface Address
+    {
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/IndexingModule.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/IndexingModule.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/IndexingModule.java
new file mode 100644
index 0000000..a06a0f7
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/IndexingModule.java
@@ -0,0 +1,26 @@
+package org.qi4j.bootstrap.assembly.infrastructure;
+
+import org.qi4j.api.common.Visibility;
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+import org.qi4j.bootstrap.layered.ModuleAssembler;
+
+public class IndexingModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "Indexing Module";
+    private final ModuleAssembly configModule;
+
+    public IndexingModule( ModuleAssembly configModule )
+    {
+        this.configModule = configModule;
+    }
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module 
)
+        throws AssemblyException
+    {
+        return module;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/InfrastructureLayer.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/InfrastructureLayer.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/InfrastructureLayer.java
new file mode 100644
index 0000000..5ba33ba
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/InfrastructureLayer.java
@@ -0,0 +1,29 @@
+package org.qi4j.bootstrap.assembly.infrastructure;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+import org.qi4j.bootstrap.layered.LayerAssembler;
+import org.qi4j.bootstrap.layered.LayeredLayerAssembler;
+
+public class InfrastructureLayer extends LayeredLayerAssembler
+    implements LayerAssembler
+{
+    public static final String NAME = "Infrastructure Layer";
+    private final ModuleAssembly configModule;
+
+    public InfrastructureLayer( ModuleAssembly configModule )
+    {
+        this.configModule = configModule;
+    }
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        new StorageModule( configModule ).assemble( layer, layer.module( 
StorageModule.NAME ) );
+        new IndexingModule( configModule ).assemble( layer, layer.module( 
IndexingModule.NAME ) );
+        createModule( layer, SerializationModule.class );
+        return layer;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/SerializationModule.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/SerializationModule.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/SerializationModule.java
new file mode 100644
index 0000000..19edd6f
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/SerializationModule.java
@@ -0,0 +1,18 @@
+package org.qi4j.bootstrap.assembly.infrastructure;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+import org.qi4j.bootstrap.layered.ModuleAssembler;
+
+public class SerializationModule
+    implements ModuleAssembler
+{
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module
+    )
+        throws AssemblyException
+    {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/StorageModule.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/StorageModule.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/StorageModule.java
new file mode 100644
index 0000000..424c653
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/infrastructure/StorageModule.java
@@ -0,0 +1,26 @@
+package org.qi4j.bootstrap.assembly.infrastructure;
+
+import org.qi4j.api.common.Visibility;
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.LayerAssembly;
+import org.qi4j.bootstrap.ModuleAssembly;
+import org.qi4j.bootstrap.layered.ModuleAssembler;
+
+public class StorageModule
+    implements ModuleAssembler
+{
+    public static final String NAME = "Storage Module";
+    private final ModuleAssembly configModule;
+
+    public StorageModule( ModuleAssembly configModule )
+    {
+        this.configModule = configModule;
+    }
+
+    @Override
+    public ModuleAssembly assemble( LayerAssembly layer, ModuleAssembly module 
)
+        throws AssemblyException
+    {
+        return module;
+    }
+}

http://git-wip-us.apache.org/repos/asf/zest-qi4j/blob/b86b66d4/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/service/ServiceLayer.java
----------------------------------------------------------------------
diff --git 
a/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/service/ServiceLayer.java
 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/service/ServiceLayer.java
new file mode 100644
index 0000000..14f6ae1
--- /dev/null
+++ 
b/core/bootstrap/src/test/java/org/qi4j/bootstrap/assembly/service/ServiceLayer.java
@@ -0,0 +1,17 @@
+package org.qi4j.bootstrap.assembly.service;
+
+import org.qi4j.bootstrap.AssemblyException;
+import org.qi4j.bootstrap.layered.LayerAssembler;
+import org.qi4j.bootstrap.LayerAssembly;
+
+public class ServiceLayer implements LayerAssembler
+{
+    public static final String NAME = "Service";
+
+    @Override
+    public LayerAssembly assemble( LayerAssembly layer )
+        throws AssemblyException
+    {
+        return null;
+    }
+}

Reply via email to